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

时间:2019-03-05 13:58:05

标签: git


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

2 个答案:

答案 0 :(得分:0)

如果不弄乱,就无法解决此问题,因为已经弄乱了。在您陷入困境之前,最后一个故障保险是推送到共享远程服务器。

问题是,如何最好地清理烂摊子。有两种选择。

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

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


历史记录重写

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

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的一部分,因此要撤消操作,可以删除{{1} },AB来自原产地的C-但这是历史记录。

重写会产生最干净的结果,但如果(a)您一个人使用遥控器,或(b)小型(或最多中等规模)的团队共享遥控器,则您只能通过重写来获得最佳结果可以合理地与所有团队成员进行协调。

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

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

如果被允许这样做,那么第一步就是要与仓库的所有用户沟通,将要进行历史重写(最好是说明发生了什么,为什么需要重写以及何时进行重写)将要发生)。这是因为一旦您进行重写,将originAB中的任何一个复制到C副本中的任何人都将处于“损坏”状态并且必须执行本地清理程序。

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

一旦所有人都加入,便会

rebase

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

请注意,C替换了较旧的origin/master(或--force-with-lease)选项,此选项的安全性较低,因为它会悄无声息地掩盖在{{1}之上的所有提交}。 --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,但在此之前,我们应该解决一个新问题:

此时,mastermastertemp已整合到A的历史记录中,但更改未反映在最终状态中(因为它们已还原);这意味着B无法重新合并。修复此问题稍微复杂一点,因为您已将C推到master,并且我们不想创建另一个历史记录重写方案

还是要解决此问题,我们需要branchbranchorigin/branch的新副本。

A

将创建副本

B

现在,所有内容都可以通过快进合并和快进推送来解决。

C

收益

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

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

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

git checkout branch
git push

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

答案 1 :(得分:-1)

AFAIK只有一种方法,您需要force push来使用正确的分支指针来创建母版。

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

git push -f origin HEAD:master

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