编辑:要回溯启用rerere,请参见此处。本答案中的脚本不会启用rerere,而且在E
的历史(如下所示)中对n...D
冲突的块进行了更改,则会与rerere的行为有所不同,以解决o
中发生的冲突。 rerere
执行n...E
合并,并应用仍然有效的任何n...D
分辨率,而此脚本执行标准的o...E
合并(但将父节点o
替换为o
)
复制图表供参考:
before desired after
Master A\--B--C\--D\....E \ Master A\--B--C\-D...E\
Branch l--m---n---o--p--q / Branch l--m---n------o'--p'--q'
因此,rerere将绕过E-reverted ND冲突,而脚本将把reversion视为进一步的更改。这两个脚本都生成上面所示的“desired after”图形,但它们通过不同的路径到达那里。
一个小时的尝试并没有产生比仅仅观察图表和推导出更多易于理解的文本描述。
我不清楚rerere或脚本的行为哪一个总是更好。
当我执行
返回o,合并E
使用:
git checkout o
git merge E
我理解
Master A\--B--C\--D\---------E
Branch l--m---n---o\-p--q \
HEAD `--------o'
使用
o
作为
o'
的父节点。你需要保留
o'
的内容(以保存你已经在
o
中应用的任何冲突解决方���),但是你希望它的父节点是
n
和
E
,而不是
o
和
E
。这实际上相当容易。
因此,完整的程序如下:
#!/bin/sh
update=`git rev-list -1 --min-parents=2 $1`
test "`git merge-base $1 $2`" = "`git rev-parse $update^2`" \
|| { echo "most recent merge isn't of $1 from $2"; exit 1; }
set -e
git checkout $update
git merge $2
git checkout $(
git cat-file -p HEAD \
| sed 1,/^$/d \
| git commit-tree -p $update^ -p $2 HEAD^{tree}
)
test $update = `git rev-parse $1` || git cherry-pick $update..$1
git checkout -B $1
如果你愿意失去在 o
中完成的任何冲突解决,你可以改为执行以下操作(从 set -e
开始)
set -e
git checkout $update^
git merge $2
test $update = `git rev-parse $1` || git cherry-pick $update..$1
git checkout -B $1
如果在子shell中执行工作,并且从该shell退出以继续工作不会有任何问题,那么您可以通过执行以下操作使其更加稳定:
git merge $2 \
|| { echo "Resolve conflicts and \`exit\`, or \`exit 1\` to not continue"; $SHELL; }
编辑:更新以处理在没有需要cherry-pick的情况下更新合并。
git rerere
(例如在https://dev59.com/4Wkw5IYBdhLWcg3wUI_x#10018939中)可能有助于记录合并决策并避免在下一次rebase中出现相同的冲突。 - VonC