繁体   English   中英

git rebase没有应用提交

[英]git rebase is not applying a commit

我有一个文件,看起来像这样:

line 1
line 2
line 3
line 4

我做了3件事的提交:

  1. 添加第5行,表示line 5
  2. 将第2行中的L大写
  3. 在第2行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你的意思是CD都将父母从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提供的待办事项列表不代表修订图的拓扑。 编辑提交和重写他们的提交消息应该可以正常工作,但尝试重新提交提交往往会产生违反直觉的结果。

例如,尝试重新安排......

请参阅https://git-scm.com/docs/git-rebase

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM