[英]git rebase is not applying a commit
我有一个文件,看起来像这样:
line 1
line 2
line 3
line 4
我做了3件事的提交:
line 5
22
我已经在3个单独的提交中完成了这个,所以我有以下图表:
* F - add line 5
* E - Merge branch 'branch' into 'master'
|\
| * D - change 2 to 22
* | C - capitalize line 2
|/
* B - adding line numbers
* A - Initial commit
我的文件现在看起来像这样:
line 1
Line 22
line 3
line 4
line 5
显然, E
的合并包含了我手动解决的冲突。 我想移动F
使其落在B
之后(最终压扁它们,但这是一个单独的问题)。 所以我做了一个git rebase -i --preserve-merges A
,编辑器打开了,我这样做了:
pick B adding line numbers
pick F add line 5
pick C capitalize line 2
pick D change 2 to 22
pick E Merge branch 'branch'
问题是在rebase之后,我完全丢失了提交F
我的图表现在看起来像这样:
* E - Merge branch 'branch' into 'master'
|\
| * D - change 2 to 22
* | C - capitalize line 2
|/
* B - adding line numbers
* A - Initial commit
F
刚走了。 它没有被rebase应用。 出了什么问题,我该如何解决?
先前的评论和答案(包括我的评论)在事实上是正确的,因为你所做的事情可能不起作用,但可能并不是很有用的答案。
首先,虽然答案“这是一个记录的错误”可能不是很令人满意,但我会指出你的例子中重新排序的TODO列表实际上并没有告诉git你想要重现什么拓扑。 这就是第一条线索是你想做的事不会那么容易的事情,因为你将如何让Git你想要什么拓扑? 你怎么解释git你的意思是C
和D
都将父母从B
改为F
,这种方式也不能被理解为“在C
之前放置F
,所以F'
和D'
各自有B
为父“; 或“放F
之前D
,使得F'
和C'
分别具有B
作为父”? 当然事实证明git没有做过那些事情,我想这是有点儿的错误。 (也就是说,我敢打赌它会重写F
,但是后来F'
, C'
和D'
的父母都是B
,这使得F'
最终无法到达。)
无论如何,我认为你的意思是:你能得到吗?
A -- B - C - E -- F <--(master)
\ /
- D -
至
A -- B -- F' - C' - E' <--(master)
\ /
- D' -
无需手动重新解决E
处的合并冲突。
答案是,你可以; 但它不会像找到正确的rebase
选项和发出单个命令那么简单。
事实上, rebase
旨在产生线性历史; 它的支持者倾向于坚持线性历史“更容易阅读”或“更清洁”,并且这比“准确”或“由经过测试的提交组成”更重要。 这些陈述不是客观普遍的,但这就是rebase
的工具所要做的。 preserve-merges
选项试图让你吃蛋糕并吃掉它,但它有很多问题(不仅仅是与-i
一起使用它时的错误)。 它可能恰好适用于一些简单的情况,但总的来说,试图通过合并进行重新绑定可能会让您感到头疼。
那又怎么办呢? 这是一种方式...请注意,在引用提交时,我已经给出了一个表达式,该表达式解析为此示例中的正确提交,而不是仅使用占位符字母。
git checkout master
git branch temp
git rebase -i master~4
// in the editor, move F after B and remove D
此时你应该有
F' -- C' <--(master)
/
A -- B - C - E -- F <--(temp)
\ /
- D -
然后你需要改变D
(在这种情况下,由于它是一次提交,你可能会做一个cherry-pick
。)
git checkout temp^^2
git checkout -b branch
git rebase --onto master^ master branch
此时你有
D' <--(branch)
/
F' -- C' <--(master)
/
A -- B - C - E -- F <--(temp)
\ /
- D -
你需要重现合并。 还有几种方法可以看到这个问题,但简化的观察是你的最终内容应该与原始历史中的F
匹配。 所以有效的解决方案是
git checkout master
git reset --hard $(git commit-tree -p master -p branch -m "Merging branch into master" temp^{tree})
(对于-m
您可以提供最初在E
处提交的任何提交消息。)然后,您可以删除temp
分支,如果已完成,则删除branch
分支。
在更复杂的场景中,从现有提交中获取合并结果TREE
这种小小的欺骗可能不起作用,因为可能没有现有提交与预期状态匹配。 在这种情况下,我认为你最好的选择是尝试git rerere
(记录在https://git-scm.com/docs/git-rerere )。 此命令的目的是将解决方案记录到合并冲突,以便在不同的合并中看到相同的冲突时可以重新应用它,我认为可以在此处应用它。 (也就是说,我从不使用它,因为我不同意导致通常需要它的工作流程的前提,所以我不能确切地说它将在这里服务的程度。)
我应该补充一点, 如果合并是非冲突的(并且非“邪恶”;即默认合并策略和选项产生所需的结果),并且在所需的重新排序下保持非冲突,那么以下过程将起作用代替上述:
// first rewrite F
git checkout master
git checkout -b temp
git rebase --onto master~3 master^
// now move master to exclude the original F
git checkout master
git reset --hard HEAD^
// now move the rest of the history
git rebase --preserve-merges temp
所以,这可能是因为,与rerere
到位,这个(概念比较简单)的方法可能会奏效,即使在冲突的情况。
git文档中有关于rebase的警告,preserve-merges选项不应与交互模式一起使用。 此组合的文档中还提到了一个错误:
BUGS由--preserve-merges --interactive提供的待办事项列表不代表修订图的拓扑。 编辑提交和重写他们的提交消息应该可以正常工作,但尝试重新提交提交往往会产生违反直觉的结果。
例如,尝试重新安排......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.