繁体   English   中英

如何还原将本地分支推送到远程主服务器

[英]How to revert pushing local branch to remote master


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

您必须先弄乱,才能解决此问题,因为已经弄乱了。 在您陷入混乱之前,最后的故障保险是推送到共享远程服务器。

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

一种选择是进行历史记录重写。 这将产生“最干净的”最终结果,但需要与存储库的每个用户进行协调。 如果您无法与可能拥有该存储库克隆版本的所有人进行协调,那么您将无法安全地进行历史记录重写(如果尝试进行历史记录重写,那么无论如何它都可能最终被撤消)。

另一个选择是添加新的提交以达到所需状态,从而留下“混乱”的历史记录。 这不是很好,但是对于共享存储库,它确实会在没有大量协调工作的情况下“自行整理”,而历史重写就不会。


历史重写

“历史记录重写”是从分支机构的历史记录中删除提交的任何操作。

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

而您不小心将branch推到了origin/master ,给了您

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

就远程而言, ABC现在是master一部分,因此要撤消操作,您可以从原始master删除ABC ,但这是一个历史重写。

重写会产生最干净的结果,但是,如果(a)您独自使用遥控器,或者(b)小型(或最多中等规模)团队共享遥控器,以便您可以合理地协调,那么重写实际上是一个合适的解决方案与所有团队成员一起。

历史记录重写的问题是,它导致分支以意外的方式移动; 如果git将此动作视为例行程序,则会导致并发的更改例行丢失-与分支和合并的目的相反。

您可以通过多种方式在本地重写历史记录-但是在这种情况下,您不必这样做,因为本地分支已经处于正确的状态。 但是,要使远程服务器重写其分支的历史记录,您必须执行“强制推送”,根据origin回购协议的设置方式,您可能会或可能不会被允许这样做。

如果您被允许这样做,那么第一步就是要与回购的所有用户交流将要进行历史重写的情况(最好是说明发生了什么,为什么需要重写以及何时进行重写) )。 这是因为一旦您进行重写,将ABC任何A拉入其master副本中的任何人都将处于“中断”状态,并且必须执行本地清理过程。

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

一旦所有人都参加了会议,您将

git checkout master
git push --force-with-lease origin master

只要没有人推其他更改origin/master之上C ,这应该移动origin/master回到原来的位置,并根据需要其他用户就可以开始清理其本地状态。

请注意, --force-with-lease -f --force-with-lease替换了较早的--force (或-f )选项,该选项不太安全,因为它将以静默方式掩盖任何推到C之上的提交。 --force-with-lease在这种情况下将中止,这将是不进行历史记录重写的进一步原因(或者如果您继续进行重写,则需要做额外的工作)。


没有历史重写

如果由于某种原因不适合使用历史记录重写,或者如果您只希望使用破坏性较小的解决方案并且可以接受“混乱的”历史记录,那么您可以执行以下操作。 同样,你有

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

我们需要一个新的提交,使origin/master的内容与master保持一致。 为此,我们可以使用git revert

git checkout origin/master
git checkout -b temp
git revert -n master..branch
git commit

这给你

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

您可以使用git diff验证temp匹配master 最终,我们将master移到temp ,但是在这样做之前,我们应该解决一个新问题:

在这一点上, ABC已集成到master的历史记录中,但是更改未反映在最终状态中(因为它们已还原); 这意味着branch不能合并回来。解决此问题稍微复杂一点,因为您已将branch推送到origin/branch ,并且我们不想创建另一个历史记录重写方案。

不过,要解决此问题,我们需要ABC新副本。

git rebase --onto temp master branch

将创建副本

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

现在,一切都可以通过快进合并和快进推送解决。

git checkout master
git merge temp
git branch -D temp
git push

产量

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)

请注意,在这些步骤中,我对推送使用了默认的refspecs。 你可以说

git push origin master

git push origin branch

但是IMO过于习惯于指定,因此很容易将其推送到错误的远程分支。 相反,我建议您进行配置设置,以便您大多数时间都可以依赖默认值。

AFAIK只有一种方法,您需要使用正确的分支指针force push送到原始主机。

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

git push -f origin HEAD:master

这会将原点上的主指针重置为正确的状态。 在您之间拉/取的任何人都犯了错误,并且您修复了这个错误,应该再次拉/取。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM