以下文本的 tl;dr 是:master 反映了自错误合并 A 以来累积的差异。您希望将正确的合并结果作为错误合并的子项提交,因此当您将正确的结果合并回 master 并合并两个提示时,它会看到并合并错误合并和正确合并之间的差异。
这里是如何,叙述或多或少反映了我是如何得到这个结果的。
您现在拥有的合并基础,功能提示,您不想要。此后没有任何更改与master 上的更改合并。如果您在原始合并中完成了整个工作,您需要合并历史记录和结果。提交图的精简版本,供参考:
# /-B.....-\ featureB
# ---A0---B0---APM---BM---? master [APM, featureA partial merge, is bad]
# \-A...../??????????/ featureA [can keep history, merge rest of A?]
第一步是首先得到你想要的合并结果:
# redo the original merge to get the right parents and the right content
git checkout $APM^ # checkout the original merge parent
git merge $APM^2 # do the correct merge with its other parent
git checkout -b AM # give this work a name
现在你有:
# /-B......\
# ---A0---B0---APM---BM---?
# \ \-/-AM
# \-A.../-/
其中AM 与$APM 具有相同的父级,但结果正确。无论$APM 做对了什么现在都在AM 中:AM 体现了需要对$APM 进行的更改以获得正确的结果。 $APM 提交中的所有内容都已生效(按字面意思)合并到 AM。
git merge -s ours $APM # $APM is correctly incorported in AM. Tell git.
这使得历史正确:AM 反映了对$APM 的一组更改,master 反映了另一组更改。是时候合并它们了:
git checkout master
git merge AM
git branch -d AM 如果我做对了,你就完成了。
以防万一我有什么问题,但作为提醒或谨慎,请在临时存储库中执行上述操作:
git clone -s . ../wip # safety play: sandbox the changes
# do the above, and when you're satisfied you've got `master` correct,
cd ../$mainrepo
git checkout master # okay, incorporate the results
git pull # .
rm -rf ../wip # (everything in wip is now also here)
测试:
# drop this as file `script` in an empty directory and
# say `sh script` to recreate the described situation:
set -x
git init --template=
for f in {1..5}; do seq -ffile$f%4.0fx 10 >f$f; done
git add .
git commit -m'Initial commit'
git checkout -b featureA
sed -si s/4x/4-featureA/ f2 f3
git commit -am4featureA-f2f3
git checkout master
sed -si s/1x/1-master/ f1 f2 f3
git commit -am1master-f1f2f3
git checkout -b featureB
sed -si s/8x/8-featureB/ f3 f4
git commit -am8featureB-f3f4
git checkout master
git merge --no-commit featureA
git checkout HEAD f3
git commit -m'Merge branch featureA - less the f3 changes'
git tag APM
git merge --no-edit featureB
# and test the given solution:
git checkout -b AM APM^
git merge --no-edit featureA
git merge --no-edit -s ours APM
git checkout master
git merge --no-edit AM
# say `rm -rf f* .git` to cleanup