如何重新创建合并的Git分支

如何重新创建合并的Git分支,git,Git,假设某个功能分支在合并到主功能后被删除 几天/几周后,我需要为该功能分支中的所有提交生成补丁文件 如果我有功能分支,我可以使用以下命令生成修补程序: git format-patch $(git merge-base master my_feature_branch)..my_feature_branch 那么,我如何才能重新创建功能分支,以便使用上述命令呢?如果您有一个基本提交,即现在已删除的功能分支已从中分离出来的提交,您可以按照以下步骤进行操作- 签出基于基本提交的分支 使用git ch

假设某个功能分支在合并到主功能后被删除

几天/几周后,我需要为该功能分支中的所有提交生成补丁文件

如果我有功能分支,我可以使用以下命令生成修补程序:

git format-patch $(git merge-base master my_feature_branch)..my_feature_branch

那么,我如何才能重新创建功能分支,以便使用上述命令呢?

如果您有一个基本提交,即现在已删除的功能分支已从中分离出来的提交,您可以按照以下步骤进行操作-

  • 签出基于基本提交的分支
  • 使用
    git cherry pick
    ,cherry选择已将功能分支合并到master中的合并提交。如果这不起作用,您可以选择作为功能分支一部分的单个提交

  • 首先,分支实际上不会被删除。只删除分支名称。但这让我们陷入了一个棘手的问题:

    让我们快速了解一下合并的过程。我们从提交图(或“DAG”;参见链接问题)中的一系列提交开始,如下所示:

    ...--o--*-----o   <-- master
             \
              o--o--o--o--o   <-- feature
    
    从某种程度上可以看出,自从上次我们合并它们以来,
    master
    feature
    都发生了什么变化(实际上从未发生过,但它们曾经在一起,在这里标记为
    *
    )。Git然后进行新的合并提交,该提交指向这两个分支提示提交:

    ...--o--*-----o---------o   <-- master
             \             /
              o--o--o--o--o   <-- feature
    
    如果我们希望通过
    feature
    查看进入
    master
    的内容,我们所要做的就是在这里找到我标记为
    F
    (用于feature)的提交。注意,我还标记了merge commit
    M
    (用于合并)

    找到它的方法是从
    master
    开始,然后向后工作,直到找到
    M
    。(它现在就在
    master
    的顶端,尽管稍后会从顶端返回一些步骤。)然后,我们只看
    M
    的第二个父提交

    要查找哈希ID已知的提交的第二个父级,我们只需告诉Git:告诉我另一个哈希ID的第二个父级的哈希ID。简单的方法是使用
    Git rev parse
    。假设
    M
    的散列ID是
    badf00d

    git rev-parse badf00d^2
    
    Git吐出
    F
    的完整散列ID。hat-two后缀表示“第二个家长”(hat-one,或仅hat本身,表示“第一个家长”)

    现在,我们可能还想找到commit
    *
    。这是commit的合并基础,它是
    M
    的第一个父级,也是我们刚刚找到的这个特定commit
    F
    。为了找到两个提交的合并基,我们要求Git:

    git merge-base badf00d^1 badf00d^2
    
    然后,我们可以使用
    git log
    git format patch
    或其他方法查看范围内的每个提交,该范围从合并基
    *
    之后开始,一直到并包括提交
    F

    我们可以使用原始散列来实现这一点,或者我们可以使用
    git branch
    git标记
    ,将名称(临时或永久,它们会一直存在,只要您愿意)指向提交
    M
    F
    、和/或
    *
    。每个名称都会为您记住哈希ID。标记名和分支名之间的主要区别在于,如果
    git checkout
    标记名,则会得到一个“分离头”,并且不在分支上,但如果
    git checkout
    分支名,则会进入该分支,如果进行新的提交,则会导致该分支前进:

    $ git branch newname <hash-ID-of-commit-F>
    
    ...--o--*-----o---------M--o--o--o   <-- master
             \             /
              o--o--o--o--F   <-- newname
    
    $ git checkout newname
    ... hack away ...
    $ git commit ...
    
    ...--o--*-----o---------M--o--o--o   <-- master
             \             /
              o--o--o--o--F--o   <-- newname (HEAD)
    
    $git branch newname
    
    让我们假设以下简化的历史:特性分支基于提交
    N
    ,包含提交
    p
    Q
    。同时,commit
    O
    被添加到主分支。功能分支已合并到提交
    R
    中。在此之后,创建了提交
    S
    T
    ,这就是master现在所在的位置

    M -- N -- O -- R -- S -- T [master]
          \       /
           P --- Q
    
    您要查找提交
    Q
    。我认为没有一种编程方式可以做到这一点,因此您需要使用任何存储库浏览器,例如
    gitk

    找到
    Q
    后,可以轻松地重新创建要素分支:

    $ git branch my_feature_branch <hash of commit Q>
    
    $git branch my\u feature\u branch
    

    我不确定您是否意识到这一点,但理解这一点的关键是知道分支只不过是提交的“指针”或“书签”;所以你知道你需要给某人一个补丁来描述在该分支中发生的一切,但你不记得什么时候开始了?你想知道如何找到功能分支中最新提交的提交,还是在找到后如何在该提交上创建一个分支?这是行不通的。请参阅此图:-合并“我的功能分支”的基础有4FA54C2F300A6C7B00568270C153B215D5B8D8与46436103594f6bc35ce1106fc09fd702011b08ad,后者是根据您建议的提交ID创建的。@akirekadu这是因为您在那里重新创建了一个不同的情况。注意合并时的
    快进
    。最后,你有一个简单的线性历史
    a-B-C-D
    ,在
    D
    上有
    master
    new\u my\u feature\u branch
    C
    上有
    。我们的CI系统没有做到这一点。假设我们可以改变它。“my_feature_branch”和“new_my_feature_branch”的合并基数仍然不同。试一试..读了@torek的答案后,我明白你的建议是指向正确方向的指针。他的帖子提供了恢复有问题的功能分支所需的所有信息,所以决定接受这个。比你多。非常有用的信息。我了解在合并分支中查找提交所涉及的各种命令。
    
    M -- N -- O -- R -- S -- T [master]
          \       /
           P --- Q
    
    $ git branch my_feature_branch <hash of commit Q>