Edmundo's answer 是正确的(并且被赞成),但值得指出一些额外的项目。
首先,您的问题是关于“移动分支的根”——但这是 Git;分支没有有根,反正不是你想的那样。让我们看看你的图表绘制:
A - B - C - D - E - F master
\
\- G - H new feature branch
我认为你和我刚开始使用 Git 时一样,想将提交 A-B-C-D-E-F 视为在 master 分支上,并将提交 G-H 视为在功能分支上。但这不是 Git 的工作方式。让我们重新绘制它,而不更改任何提交链接:
E--F <-- master
/
A--B--C--D
\
G--H <-- feature
这应该更清楚地表明,就 Git 而言,提交 A-B-C-D 位于 both 分支上。只有一个根。那是提交A:它是一个根,因为它没有父提交,在从提交到父的链中没有反向链接。
其次,无论你怎么做,你最终都不得不复制一些提交。原因是每个提交的父 ID 都是该提交身份的一部分。任何提交的“真实名称”都是其哈希 ID,哈希 ID 是通过读取提交的完整内容构建的:源树、提交消息、作者姓名和日期等,但也始终包括父 ID。 1 您希望最终的图表类似于:
D--E--F <-- master
/
A
\
B--C--G--H <-- feature
但现有的D 链接(或指向)回现有的C,而不是A,现有的G 又指向现有的D。
这就是cherry-pick有效的原因:git cherry-pick本质上是复制一个提交。新副本与原始副本“做同样的事情”,但有一些东西不同,即使它像“我的父母是......”一样简单。 (通常它也有一个不同的附加 tree 对象,只是它所做的 change 与它的新父级相比,与原来的更改相同将原件与原件的父代进行比较时生成)。这意味着you can't actually get what you want, just what you need:
D'-E'-F' <-- master
/
A
\
B--C--G'-H' <-- feature
小勾号表示结果是原件的副本。
原件会怎样?答案是:它们仍然存在,在存储库中,以防您需要它们。全图更像这样:
D'-E'-F' <-- master
/
/ E--F [abandoned]
/ /
A--B--C--D
\ \
\ G--H [abandoned]
\
G'-H' <-- feature
虽然git cherry-pick 有效,但git rebase——尤其是git rebase -i——所做的是以一种奇特的自动化方式完成这些副本,最后一步是移动分支名称,放弃原始提交。所以git rebase -i 有时是一种更容易的方式。
如果你运行git rebase -i,你会看到所有那些pick 命令,而那些实际上运行git cherry-pick:它确实是在做一系列的挑选。如果您自己执行这些操作,可能会更清楚发生了什么,并且您可以更好地控制何时移动分支标签。
1对于合并提交,这是父s,复数形式。所有父母都参与哈希。