难以理解的内容,没有关于将提交从一个分支移动到另一个分支的图表

问题描述 投票:0回答:1

我不理解页面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的语法。但是我不明白这里到底发生了什么。

如果您通过在每个命令后绘制一个提交树图来帮助我,我将不胜感激。

git rebase
1个回答
1
投票

这里的部分混乱可能来自术语“移动提交”。从技术上讲,没有移动提交这样的事情。创建提交后,其内容以及父指针都是不可变的,永远无法更改。

但是有可能创建新的提交与另一个父对象来实现相同的更改,在这种情况下就是这种情况。

记住分支只是指向提交的可变指针也是有用的。

起点:让我们假设以下情况

  • $destination是目标分支
  • $source是源分支
  • [$firstC(我们要“移动”的系列中的第一个提交)
  • [$lastD(我们要“移动”的系列中的最后一个提交)]
                      $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

  • 获取$firstnonce的父级之间的所有差异(即CD引入的更改,并将它们作为新的提交应用于$destination之上)>
  • 这将导致新的提交C'D'(原始提交CD不受影响)
    • 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                    
    
  • [从外部看,提交CD的效果已从$source中删除,而是应用于$destination

    编辑:

从上面可以看出,原始提交CD仍然存在,但是无法从任何分支访问,它们是“分离的”。它们仍然存在于存储库中,但是因为git非常严格地禁止删除或修改现有的提交(毕竟它们是不可变的)。要显式删除此提交,请使用git prune
                                 $destination
                                      |  
A -- B ------------------- F -- C' -- D'
      \-- E'                     
          |                           
       $source                    
© www.soinside.com 2019 - 2024. All rights reserved.