Git 如何重新设置已覆盖历史记录的分支的基础?
假设我的分支Git 如何重新设置已覆盖历史记录的分支的基础?,git,version-control,rebase,Git,Version Control,Rebase,假设我的分支1带有提交A 1:A 从1开始,我创建另一个分支,2 2:A 在2上,我添加了一个提交 2:A->B 然后在1上,我做了一些更改,并git提交--amend,覆盖A 1:C 在2上,我想在1上进行这些新的更改,并且只想将我的更改从B应用到C。然而,据我所知,git将看到分支2有新的提交A和B,并尝试在C之上应用这两个提交。因此,当我完成重定基址时,2将看起来像 2:C->A->B 当我真正想要的是C->B 处理这种情况的正确方法是什么?到目前为止,我处理这个问题的方法是创建1的一个新
1
带有提交A
1:A
从1开始,我创建另一个分支,2
2:A
在2
上,我添加了一个提交
2:A->B
然后在1
上,我做了一些更改,并git提交--amend
,覆盖A
1:C
在2
上,我想在1
上进行这些新的更改,并且只想将我的更改从B
应用到C
。然而,据我所知,git将看到分支2
有新的提交A
和B
,并尝试在C
之上应用这两个提交。因此,当我完成重定基址时,2
将看起来像
2:C->A->B
当我真正想要的是C->B
处理这种情况的正确方法是什么?到目前为止,我处理这个问题的方法是创建
1
的一个新分支,然后cherry从2
中选择commitB
。但这似乎有点老套,而且当2
有不止一个新提交时,这样做也不是那么简单。让我们更常规地安排一下,看看发生了什么
如果A是第一个提交,那么事情会变得复杂,因此我将添加一个祖先Z
假设我有一个带有提交A的分支1
从1开始,我创建另一个分支2
在2上,我添加了一个commit
然后在1上,我做了一些更改,git commit--amend,覆盖了A
这就是事情不稳定的地方
C [1]
/
Z - A
\
B [2]
Git从不“覆盖”提交。不可能。提交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,所以您真正想要的是a之后2的所有内容
结果就是你想要的
B1 [2]
/
C [1]
/
Z - A
\
B
(A和B将不可见,它们最终将被垃圾收集。)
如果你认为这很复杂,充满了危险,那就是 这就是为什么最好不要重新设置或修改“稳定”分支的基础,通常是
master
。相反,只需使用普通提交或功能分支进行更大的更改。然后应用更新分支的正常过程
C [1]
/
Z - A
\
B [2]
A1 - B1 [2]
/
C [1]
/
Z - A
\
B
git rebase --onto 1 A..2
B1 [2]
/
C [1]
/
Z - A
\
B