我们最近遇到一个问题,合并以某种方式导致所有更改导致在合并提交中撤消一个父级,并且在该点之后已应用了几个提交。所有这些都被推送到我们的共享源存储库。我希望能够恢复错误的合并并重新应用其他更改集。最简单的方法是什么?
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,虽然只知道命令行应该允许我推断其余部分。)
答案 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并且正在维护版本