我有以下情况:
$ git --version
git version 2.7.3.windows.1
$ git log --graph --oneline
* 83e3254 version 1.1
* 34188af merge of feature into master
|\
| * 784ba31 awesome change
|/
* 6eec273 added file1
* 84d80a5 added version file
要在新目录中重现
rm -rf .git
git init
echo version 1.0 > version.txt
git add version.txt
git commit -m "added version file"
echo file1 > file1
git add file1
git commit -m "added file1"
git checkout -b feature
echo awesome change >> file1 && git commit -am "awesome change"
git checkout master
git merge --no-ff --no-commit feature
echo "small fixup" >> file1
git commit -am "merge of feature into master"
echo version 1.1 > version.txt
git commit -am "version 1.1"
现在我看到此功能适用于1.1版。所以我这样做了:
git rebase --preserve-merges -i master~3
将其作为git-rebase-todo
pick 6eec273 added file1
pick 83e3254 version 1.1
pick 784ba31 awesome change
pick 34188af merge of feature into master
得到了这个:
$ git log --graph --oneline
* 34188af merge of feature into master
|\
| * 784ba31 awesome change
|/
* 6eec273 added file1
* 84d80a5 added version file
83e3254发生了什么?我错过了什么吗?当我需要保留合并时,我应该在todofile中使用34188af吗?
答案 0 :(得分:5)
这可能与rebase机制的不完整性有关。来自git rebase
文档:
-p --preserve-merges
重新创建合并提交,而不是通过重放合并提交引入的提交来展平历史记录。合并冲突 不保留对合并提交的解决方案或手动修改。
这会在内部使用
--interactive
机制,但明确地将其与--interactive
选项结合使用通常不是一个好主意 除非你知道自己在做什么(见下面的BUGS)。
-i
和--interactive
选项是同义词。
让我们看看BUGS部分:
--preserve-merges --interactive
提供的待办事项列表没有 表示修订图的拓扑。编辑提交和 重写他们的提交消息应该工作正常,但尝试 重新提交提交往往会产生违反直觉的结果。例如,尝试重新排列
1 --- 2 --- 3 --- 4 --- 5
到
1 --- 2 --- 4 --- 3 --- 5
移动"选择4" line将产生以下历史记录:
3 / 1 --- 2 --- 4 --- 5
答案 1 :(得分:4)
Melebius' answer是正确的(并且被赞成);它与交互式rebase试图以一系列樱桃选择重播提交的方式有关。由于合并实际上不是挑选,因此保留合并模式使用秘密侧通道 1 来确定如何重新执行合并,以及此侧通道取决于提交顺序。
然而,重新执行合并还有另一个问题。通过运行git merge
重新合并。这是您的原始合并:
git checkout master
git merge --no-ff --no-commit feature
echo "small fixup" >> file1 # DANGER WILL ROBINSON
git commit -am "merge of feature into master"
(注意我的补充评论)。这个“小修正”不是两个输入的一部分:它是通过--no-commit
功能手动添加的,以及手动操作。这有时被称为“邪恶合并”:
当git rebase -p
“重播”合并时,它会在没有 --no-commit
的情况下执行,然后自动在上移动到下一个线性化提交。因此,即使您保留提交顺序并因此获得其他正确的重新历史记录,任何故意引入的更改都将丢失。
此 记录在案 - 请参阅引用的文字,其中写着:
不保留合并冲突解决方案或手动修改合并提交。
- 但在我看来,这句话需要用粗体闪烁的72磅字体或其他东西。 : - )
1 这根本不是什么秘密:只需查看交互式rebase代码即可。使用文件查看器或编辑器,查看$(git --exec-path)/git-rebase--interactive
。搜索字符串“preserv”(如保留或保留)并观察函数pick_one_preserving_merges
和pick_one
中的代码,如果存在名为$rewritten
的目录,则调用它。 $rewritten
目录的使用相当复杂(它适用于保留合并和非合并保留的交互式rebase,并依赖于不 {{1}的事实}或--preserve
选项,初始“todo”列表不包含实际的合并,因此只是将它们展平。)