我不理解页面https://sethrobertson.github.io/GitFixUm/fixup.html#move_commit中的内容:
将提交从一个分支移动到另一个分支
因此,您的提交位置错误,并且您想移动它从一个分支到另一个分支。为此,您需要知道第一次提交和最后一次提交的SHA(连续的提交)要移动(如果移动,则这些值相同仅一次提交),您正在移动提交的分支的名称来自,以及要将提交移至的分支的名称。在里面在下面的示例中,我将这四个值命名为$ first,$ last,$ source,和$ destination分别。此外,您将需要使用nonce分支作为占位符。在以下示例中,我将nonce分支称为“ nonce”。但是,您可以使用任何当前未使用的分支名称。您完成后可以立即将其删除。
git branch nonce $last git rebase -p --onto $destination $first^ nonce
[请记住,当您在上面的命令中替换$ first时,请离开单独的“ ^”,就是字面意思。
使用
gitk --all --date-order
检查以确保移动看起来像正确(假装nonce是目标分支)。请非常仔细地检查是否要移动合并,它可能有被不正确地重新创建。如果您不满意结果,则可能删除随机数分支(git branch -D nonce
),然后重试。但是,如果一切看起来不错,我们可以移动实际目的地分支指针指向随机数的位置:
git checkout $destination git reset --hard nonce git branch -d nonce
如果仔细检查
gitk --all --date-order
,您会看到目的分支看起来正确。但是,提交是仍然在源分支上。我们现在可以摆脱这些:git rebase -p --onto $first^ $last $source
最后一次使用
gitk --all --date-order
,您现在应该看到源分支上的提交已消失。你已经成功了移动了提交。请非常仔细地检查是否发生合并在删除的提交之后。它们可能已被重新创建错误地。如果是这样,您可以undo the delete或尝试删除错误的合并并尝试手动重新创建它,或者从同一个SHA创建一个伪造的(--ours)合并,以便git知道合并发生。
我将尽力解释我所知道和所不知道的。如果有人在每个命令后绘制一棵提交树,我将不胜感激。
第一,
git branch nonce $last (1)
git rebase -p --onto $destination $first^ nonce (2)
据我所知(1)副本将$ last提交到名为nonce的分支。在(2)中,从$ first到$ nonce的提交范围移动到$ destination之上。我不明白提交树在这一点上的样子,因为我不太了解(1)的效果。
然后,
git checkout $destination (3)
git reset --hard nonce (4)
git branch -d nonce (5)
(3)检出目标提交。然后在(4)处将硬重置为随机数,但这有什么作用?然后在(5)处删除分支随机数。
最后,
git rebase -p --onto $first^ $last $source (6)
文本说(6)导致源分支中的提交被删除。据我了解,这种语法将提交范围定义为$ last的子级,直到$ first的父级,包括$ source。
我确实知道git rebase --onto
的语法。但是我不明白这里到底发生了什么。
如果您通过在每个命令后绘制一个提交树图来帮助我,我将不胜感激。
这里的部分混乱可能来自术语“移动提交”。从技术上讲,没有移动提交这样的事情。创建提交后,其内容以及父指针都是不可变的,永远无法更改。
但是有可能创建新的提交与另一个父对象来实现相同的更改,在这种情况下就是这种情况。
记住分支只是指向提交的可变指针也是有用的。
起点:让我们假设以下情况
$destination
是目标分支$source
是源分支$first
是C
(我们要“移动”的系列中的第一个提交)$last
是D
(我们要“移动”的系列中的最后一个提交)] $destination
|
A -- B ------------------- F
\ -- C -- D ----- E
|
$source
步骤1:git branch nonce $last
nonce
的新分支指针附加到$last
提交 $destination
|
A -- B ------------------- F
\ -- C -- D ----- E
| |
$nonce $source
步骤2:git rebase -p --onto $destination $first^ nonce
$first
和nonce
的父级之间的所有差异(即C
和D
引入的更改,并将它们作为新的提交应用于$destination
之上)>C'
和D'
(原始提交C
和D
不受影响)nonce
分支指针已移至新创建的提交D'
的最后一个>$destination | A -- B ------------------- F \ -- C -- D ----- E \ -- C' -- D' | | $source $nonce
步骤3:
git checkout $destination
$destination
分支。这对历史记录图没有影响]步骤4:git reset --hard nonce
$destination
分支指针移动到与nonce
相同的提交git merge --ff-only nonce
完成,这应该导致快速前向合并,从而产生相同的结果。$destination | A -- B ------------------- F -- C' -- D' \ -- C -- D ----- E | | $nonce $source
步骤5:
git branch -d nonce
nonce
分支指针 $destination
|
A -- B ------------------- F -- C' -- D'
\ -- C -- D ----- E
|
$source
步骤6:git rebase -p --onto $first^ $last $source
$last
和$source
之间的所有差异(即E
引入的更改),并将它们作为新提交应用于$first^
($first
的父级,即B
)之上) >E'
(原始提交E
不受影响) $destination
|
A -- B ------------------- F -- C' -- D'
\ -- C -- D ----- E
\-- E'
|
$source
[从外部看,提交C
和D
的效果已从$source
中删除,而是应用于$destination
。
编辑:
C
和D
仍然存在,但是无法从任何分支访问,它们是“分离的”。它们仍然存在于存储库中,但是因为git非常严格地禁止删除或修改现有的提交(毕竟它们是不可变的)。要显式删除此提交,请使用git prune
$destination
|
A -- B ------------------- F -- C' -- D'
\-- E'
|
$source