恢复损坏的合并并使用Gi​​t重新应用选定的提交

时间:2012-02-04 13:38:43

标签: git merge tortoisegit

我们最近遇到一个问题,合并以某种方式导致所有更改导致在合并提交中撤消一个父级,并且在该点之后已应用了几个提交。所有这些都被推送到我们的共享源存储库。我希望能够恢复错误的合并并重新应用其他更改集。最简单的方法是什么?

ASCII艺术示例:

    A-B-C-D
   /       \
P-Q         M-X-Y-Z
   \       /
    1-2-3-4

  ---time--->

提交M已包含更改A到D,但所有更改1到4都被该提交还原。

我希望能够恢复,例如。更改集4,并重新应用更改A-D和X到Z,理想情况下无需手动重做每个更改。

如果无法做到这一点,我想听听最好的解决方法 - 例如。也许从4分支,再次合并D小心不要破坏任何东西,然后手动重新应用X到Z?

(一个理想的情况是知道如何使用TortoiseGit,虽然只知道命令行应该允许我推断其余部分。)

1 个答案:

答案 0 :(得分:10)

你想结束一些逻辑效果是:

P-Q-1-2-3-4-A-B-C-D-X-Y-Z

有几种方法。我们现在假设主要点为Z


恢复合并提交(最安全但更麻烦)

我们需要首先恢复损坏的合并提交M。我们会这样做:

git revert -m 1 M

接下来,让我们重新应用否定的或可能被否定的提交:

git cherry-pick 1
git cherry-pick 2
git cherry-pick 3
git cherry-pick 4
git cherry-pick A
git cherry-pick B
git cherry-pick C
git cherry-pick D

现在我们有了这个:

# M reverts some of A..D and 1..4
# !M undoes the logical effect of the merge

    A-B-C-D
   /       \
P-Q         M-X-Y-Z-!M-1'-2'-3'-4'-A'-B'-C'-D'
   \       /
    1-2-3-4

这是最安全的方法,因为它不会触及任何以前的历史记录,因此不会影响任何人的上游回购。但它也是最混乱的,因为它留下了很多碎屑。唉,这是你为草率合并付出的代价。


扔掉破碎的历史(最危险但最干净)

这需要大家一致认为你的方法是合理的。你将破坏人们的历史,任何有污染的合并提交M的人都会遇到问题,如果你这样做的话。但是你的历史看起来会更清晰。

因为您将打破任何拥有污染提交的团队成员的历史记录,直到他们下拉远程存储库并且直到他们将本地主人重置为该点为止,这是最危险的方法。

首先,我们将master重新回到Q,最后一次提交没有问题。

git checkout master
git reset --hard Q       # rewind `master` branch to `Q`

接下来,我们需要交互式地修改损坏的提交序列。

git checkout Z         # move to Z
git branch tmp         # make a branch pointing to Z
git rebase -i master   # rework this branch onto master

您将看到编辑器中的提交列表,如下所示:

pick aaaaaaa Commit message one
pick bbbbbbb Commit message two
pick ccccccc Commit message three
# ...

其中一个是破解的合并提交。删除这一行;保存并关闭。

Git现在将按照您要求的顺序应用提交,并且您将使用tmp。如果一切都很好,那么重置master:

git checkout master
git reset --hard tmp

现在强制推动原点:

git push -f origin master

将删除损坏的历史记录,并且主人将指向新的历史记录。


最后

你应该考虑让你的团队使用类似nvie's git-flow的东西,以避免将来出现混乱并防止混乱。

更新:看起来nvie放弃了对git-flow的支持。但是,Peter van der Does forked并且正在维护版本