我有一个类似下面的提交图。标有*
的提交代表了大量提交。
A*
|
B---------
| |
C* D* <- old feature branch
| |
E---------
|
F*
|
G <- master
合并提交E未正确完成,并且C *中的某些更改(不是全部)已丢失。如何重做该合并以将更改重新引入当前主服务器?
所有内容都已被推送(开源项目),因此不能改变历史记录。
我尝试从提交C *创建补丁并将其应用于主服务器,但是因为某些来自C *的更改已正确合并,并且因为项目自该提交后进化,所以80%的补丁都失败了。
理想情况下,我们会接受C *中的所有更改,将它们应用于掌握并解决所有冲突。但由于分支已经合并,git没有检测到任何变化,也不允许再次合并。
$ git checkout 5bc5295 # C
HEAD is now at 5bc5295... cleanup
$ git checkout -b "missing-commits"
Switched to a new branch 'missing-commits'
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.
$ git merge missing-commits
Already up-to-date.
答案 0 :(得分:2)
理想情况下,我们会采用C *中的所有更改,将其应用于掌握并解决所有冲突。
不,理想情况下,您会回放时间,按照当时的时间进行合并(但是这次正确),然后重新应用F*
更改,最后得到正确的master
。
你可以这样做:
git checkout missing-commits
git checkout -b correct-merge
git merge D # do it right, this time around!
git checkout master
git checkout -b correct-master
git rebase --onto correct-merge wrong-merge correct-master # have fun with the mother of all rebases!
如果您设法在rebase期间处理所有冲突,那么您最终将在分支correct-master
中最终得到您想要的内容。
由于您不想更改历史记录,因此您可以创建一个大补丁并将其应用于当前的master
,但我更喜欢这种方法(假设您在工作目录中完成了所有工作{{ 1}}):
yourrepos
现在,当您输入cd yourrepos ; git checkout correct-master ; cd ..
cp -a yourrepos newrepos
rm -rf newrepos/.git
cd yourrepos ; git checkout master ; cd ..
cp -a yourrepos/.git newrepos/
并执行newrepos
时,您将进入分支git status
并准确查看master
和master
之间的所有更改,好像你已经应用了一个补丁。它将捕获已删除的文件,新文件,更改的文件,更改的权限,更改的符号链接等。
理想情况下,如果一切正常,它将准确显示correct-master
中缺少的提交。使用您最喜欢的C
变种,最后是一个不错的git add
(或者几个,如果您愿意的话),并且您已经完成了。没有重写历史。
答案 1 :(得分:1)
你可以尝试采摘樱桃:
git checkout master
git cherry-pick B..[last_commit_of_C*]
Git可能会要求你确认樱桃选择,因为提交是在祖先。
答案 2 :(得分:1)
Git存储快照并动态检测更改,因此处理错误提交和良好提交之间差异的方法是将商品记录为坏的后代 - 几乎与任何事物相同,来思考它的。使用git reset --soft
告诉git正确的祖先:
git checkout badmerge^1 # generate the right result
git merge badmerge^2
git reset --soft badmerge # as an improvement on the wrong result
git commit
git checkout master # merge the difference now that git sees it
git merge @{1} -m "applying corrections to a bad merge"
答案 3 :(得分:0)
尝试而不是创建普通补丁并应用它们以使用git format-patch
和git am
。这应该为您提供正常的冲突状态,然后您可以使用合并工具来解决冲突,这与应用程序失败的git apply
不同。