埃德蒙多的回答是正确的(并且已投票),但值得指出一些额外的项目。
首先,你的问题涉及“移动分支的根”——但这是 Git;分支机构没有have根源,无论如何都不是你思考的方式。让我们看看你的图表绘制:
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
are on both分支机构。只有一个根。这就是承诺A
:它是根,因为它没有父提交,从提交到父的链中没有向后链接。
Second, no matter how you go about this, you wind up having to copy some commits. The reason is that each commit's parent ID is part of that commit's identity. The "true name" of any commit is its hash ID, and the hash ID is built by reading the complete contents of the commit: source tree, commit message, author name and date, etc., but always including the parent ID too.1 You want your final graph to resemble:
D--E--F <-- master
/
A
\
B--C--G--H <-- feature
但现有的D
链接(或点)回现有的C
,不A
,以及现有的G
指向现有的D
.
这就是cherry-pick 起作用的原因:git cherry-pick
本质上copies一次提交。新副本与原始副本“做同样的事情”,但具有某物不同,即使它像“我的父母是......”一样简单。 (通常它还有一个不同的附件tree对象也是如此,只是change与新的父级相比,它所做的更改与将原始父级与原始父级进行比较时原始级所做的更改相同)。这意味着什么你实际上无法得到你想要的东西,而只是得到你需要的东西:
D'-E'-F' <-- master
/
A
\
B--C--G'-H' <-- feature
其中小勾号表示结果是copy原来的。
原件会怎样?答案是:它们仍然存在于存储库中,以备您需要时使用。完整的图片更像是这样的:
D'-E'-F' <-- master
/
/ E--F [abandoned]
/ /
A--B--C--D
\ \
\ G--H [abandoned]
\
G'-H' <-- feature
While git cherry-pick
有效,什么git rebase
-尤其git rebase -i
— 的作用是以一种奇特的自动化方式完成这些副本,最后一步是移动分支名称,放弃原始提交。所以git rebase -i
有时是一个easier解决这个问题的方法。
如果你跑git rebase -i
你看到所有这些pick
命令,以及那些字面上运行的命令git cherry-pick
:它确实在做一系列的挑选。如果您自己执行这些操作,可能会更清楚发生了什么,并且您可以更好地控制何时移动分支标签。
1For merge commits, this is parents, plural. All parents participate in the hash.