假设我的分支1
有提交A
。
1: A
从1开始,我创建了另一个分支2
。
2: A
在2
上,我添加一个提交。
2: A->B
然后在1
,我做了一些更改并git commit --amend
,覆盖了A
。
1: C
在2
上,我希望在1
上进行这些新的更改,并希望将我的更改从B
应用到C
。但是,根据我的理解,git会看到分支2
有新的提交A
和B
,并尝试在C
之上应用这两个提交。所以,当我完成变基,2
看起来像
2: C->A->B
当我真正想要的是C->B
。
处理这种情况的正确方法是什么?到目前为止,我一直在处理这个问题的方法是从1
创建一个新分支,然后从B
挑选提交2
。但是这似乎有些苛刻,而且当2
不仅仅有一个新提交时,这并不是那么简单。
答案 0 :(得分:2)
让我们更常规地说明这一点,看看会发生什么。
如果A是第一次提交事情变得复杂,那么我将添加一个祖先Z.
假设我的分支1有提交A。
Z - A [1]
从1开始,我创建另一个分支,2。
Z - A [1][2]
在2上,我添加一个提交。
Z - A [1]
\
B [2]
然后在1,我做了一些更改并且git commit --amend,覆盖A。
这里的事情变得不稳定。
C [1]
/
Z - A
\
B [2]
Git never"覆盖"提交。它不可能。提交ID是提交内容及其所有祖先的校验和。 commit --amend
(以及rebase
)所做的是创建新提交并假装它一直都是这样。
但旧的承诺仍然存在。如果有任何东西作为祖先,就像这里的分支2一样,它将是可见的。
在2上,我想在1上进行这些新的更改,并希望将我的更改从B应用到C.但是,根据我的理解,git将看到分支2有新的提交A和B,并尝试同时应用这两个这些提交在C之上。所以当我完成变基时,2将看起来像2:C-> A-> B当我真正想要的是C-> B。
这里的问题是因为commit --amend
分支1和分支2不再有A作为共同的祖先。它现在是Z.如果你试图将2变为1,它会将A和B都放在C之上。
A1 - B1 [2]
/
C [1]
/
Z - A
\
B
虽然这可能有效,但也可能导致混乱的冲突。您必须使用更精确的rebase命令让Git知道您真正想要的是什么。由于C实际上是一个重写的A,你真正想要的是之后的所有内容。
git rebase --onto 1 A..2
结果将是你想要的。
B1 [2]
/
C [1]
/
Z - A
\
B
(A和B不会被看见,最终会被垃圾收集。)
如果你认为这很复杂且充满危险,那就是它!
这就是为什么不改变或修改你的稳定"分支,通常master
。相反,只需使用普通提交或功能分支进行更大的更改。然后应用更新分支的正常程序。