Git 如何恢复将本地分支推送到远程主机

Git 如何恢复将本地分支推送到远程主机,git,Git,1我已将本地分支推送到源主机,而不是远程分支。 2然后我将本地分支按原样推到了远程分支 但是: 如何在不造成混乱的情况下删除第一个操作?如果只有一种方法,您需要使用正确的分支指针强制推送到原始主机 因此,您可以在本地将主分支重置为正确的原点/主状态,然后 git push -f origin HEAD:master 这会将原点上的主指针重置为正确状态。 任何在你之间拉/拉的人都犯了错误,你修复了它,应该再次拉/拉。你不能在不弄乱的情况下修复它,因为已经弄乱了。在您陷入混乱之前,最后一个故障保护

1我已将本地分支推送到源主机,而不是远程分支。 2然后我将本地分支按原样推到了远程分支 但是:
如何在不造成混乱的情况下删除第一个操作?

如果只有一种方法,您需要使用正确的分支指针强制推送到原始主机

因此,您可以在本地将主分支重置为正确的原点/主状态,然后

git push -f origin HEAD:master
这会将原点上的主指针重置为正确状态。
任何在你之间拉/拉的人都犯了错误,你修复了它,应该再次拉/拉。

你不能在不弄乱的情况下修复它,因为已经弄乱了。在您陷入混乱之前,最后一个故障保护是推送到共享远程设备

所以问题是,如何最好地清理混乱。有两种选择

一种选择是重写历史记录。这将产生最干净的最终结果,但需要与回购协议的每个用户进行协调。如果你不能与所有可能复制了回购协议的人进行协调,那么你就无法安全地进行历史重写,如果你试图进行历史重写,那么它最终可能会被撤销

另一种选择是添加新的提交以达到所需的状态,留下混乱的历史记录。这并不伟大,但对于共享回购协议来说,它确实倾向于在没有重大协调努力的情况下自行解决问题,这是历史改写所没有的

历史改写

“历史重写”是从分支的历史记录中删除提交的任何操作。就你而言,你有

O -- x -- x <--(master)(origin/master)
           \
            A -- B -- C <--(branch)
就遥控器而言,A、B和C现在是master的一部分,因此要撤消,您可以从origin的master中删除A、B和C,但这是一个历史重写

重写会产生最干净的结果,但它实际上只是一个合适的解决方案,如果A您单独使用远程,或b远程由小型或最多中等规模的团队共享,这样您就可以合理地与所有团队成员协调

历史重写的问题是,它会导致分支以意外的方式移动;如果git将这种移动视为常规,它将导致并发更改常规丢失——这与分支和合并的目的相反

您可以通过多种方式在本地重写历史记录,但在本例中,您不必这样做,因为您的本地分支已经处于正确的状态。但要让远程设备重写其分支的历史记录,您必须进行强制推送。您可以这样做,也可以不这样做,这取决于原始回购协议的设置方式

如果允许您这样做,那么第一步是向回购协议的所有用户传达历史重写即将发生,最好是解释发生了什么,为什么需要重写,以及何时会发生。这是因为,一旦您推动重写,任何将A、B和C中的任何一个拉入其母版副本的人都将处于损坏状态,并且必须执行本地清理过程

您可以在git rebase文档中的Recovery from upstream rebase(从上游rebase恢复)下阅读更多关于此问题以及如何解决此问题的信息。这在rebase下有记录,但适用于任何远程历史重写。请注意,repo的任何用户都可能错误地执行清理,从而使问题永久化,并可能撤消重写

一旦你有了所有人,你就会

git checkout master
git push --force-with-lease origin master
只要没有人将其他更改推到C上的origin/master,这应该会将origin/master移回它所属的位置,其他用户可以根据需要开始清理其本地状态

请注意,-force with lease将替换较旧的-force或-f选项,后者不太安全,因为它将默默地关闭推到C之上的任何提交。在这种情况下,-force with lease将中止,这将是不进行历史重写的进一步原因,或者如果继续重写,将需要进行额外的工作

不改写历史

如果出于任何原因,历史重写是不合适的,或者如果你只是喜欢一个破坏性较小的解决方案,可以忍受混乱的历史,那么你会这样做。再说一次

O -- x -- x <--(master)
           \
            A -- B -- C <--(branch)(origin/master)(origin/branch)
这给你

O -- x -- x <-(master)
           \
            A -- B -- C <--(branch)(origin/master)(origin/branch)
                       \
                        ~CBA <--(temp)
将创建副本

O -- x -- x <-(master)
           \
            A -- B -- C <--(origin/master)(origin/branch)
                       \
                        ~CBA <--(temp)
                            \
                             A' -- B' -- C' <--(branch)
屈服

O -- x -- x -- A -- B -- C <--(origin/branch)
                          \
                           ~CBA <--(master)(origin/master)
                            \
                             A' -- B' -- C' <--(branch)
O -- x -- x -- A -- B -- C -- ~CBA <--(master)(origin/master)
                                  \
                                   A' -- B' -- C' <--(branch)(origin/branch)
屈服

O -- x -- x -- A -- B -- C <--(origin/branch)
                          \
                           ~CBA <--(master)(origin/master)
                            \
                             A' -- B' -- C' <--(branch)
O -- x -- x -- A -- B -- C -- ~CBA <--(master)(origin/master)
                                  \
                                   A' -- B' -- C' <--(branch)(origin/branch)


但IMO过于习惯于指定,这使得推送到错误的远程分支太容易了。相反,我建议设置您的配置,以便您可以在大多数情况下依赖默认设置。

远程主机是与其他人共享的,还是您自己处理的?取决于您是否可以控制主机,其他人是否已经更新了主控器,以及您是否要重置或还原。-我个人认为还原更混乱,但当你们分享大师或者不控制大师的时候,回复会更好。这是我自己的训练项目。如果这是你们自己的训练项目,那么一定要做推力。唯一的缺点是其他用户共享您的
回购协议。如果没有其他用户,那么就没有坏处了。标志-f表示什么?它的-force表示您正在覆盖原始状态。通常你不会这么做,但如果你毁了它,这是你唯一的选择。它不是唯一的选择,在很多情况下也不是最好的选择。即使需要强制推送,也应该使用-force with lease而不是-f。是的,但是强制with lease应该失败。在这种情况下,OP更新了分支指针him self,这将阻止强制with lease。这种情况很糟糕,部分取决于时机,但如果动作迅速,强行推倒一个糟糕的推手通常没有问题。当然,您总是可以从分支恢复所有提交,但在我看来,这不会删除请求的第一个操作。一如既往地接受解释。
O -- x -- x -- A -- B -- C <--(origin/branch)
                          \
                           ~CBA <--(master)(origin/master)
                            \
                             A' -- B' -- C' <--(branch)
git checkout branch
git push
O -- x -- x -- A -- B -- C -- ~CBA <--(master)(origin/master)
                                  \
                                   A' -- B' -- C' <--(branch)(origin/branch)
git push origin master
git push origin branch