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

aki*_*adu 0 git

假设功能分支合并到master后被删除。

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

如果我具有功能分支,则可以使用以下命令来生成补丁:

git format-patch $(git merge-base master my_feature_branch)..my_feature_branch
Run Code Online (Sandbox Code Playgroud)

因此,如何重新创建功能分支,以便可以使用上述命令?

tor*_*rek 5

好吧,首先,分支不会真正被删除。仅分支名称被删除。但这使我们陷入一个棘手的问题:“分支”到底是什么意思?

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

...--o--*-----o   <-- master
         \
          o--o--o--o--o   <-- feature
Run Code Online (Sandbox Code Playgroud)

然后,我们运行:

git checkout master
git merge feature
Run Code Online (Sandbox Code Playgroud)

这在某种程度上计算出我们在这两个已经改变masterfeature自上次我们合并它们(这实际上是永远,但他们一起在同一时间,在标注点*这里)。然后,Git进行新的合并提交,使其指向这两个分支提示提交:

...--o--*-----o---------o   <-- master
         \             /
          o--o--o--o--o   <-- feature
Run Code Online (Sandbox Code Playgroud)

并且我们有一个“合并”:类型为commit commit的提交

现在,我们可以删除单词feature和箭头,即删除名称。该保持不变,并保留名称master

...--o--*-----o---------M   <-- master
         \             /
          o--o--o--o--F
Run Code Online (Sandbox Code Playgroud)

如果我们希望看到mastervia 进入了什么feature,我们要做的就是在这里找到我标记为F(针对Feature)的提交。请注意,我还标记了合并提交M(用于合并)。

找到它的方法是从头开始master并向后工作,直到找到为止M。(这正好遇上的尖端master眼下,虽然后来,这将是某些步骤数从后倾)。然后,我们简单看一下第二父提交M

要找到我们知道其哈希ID的提交的第二个父对象,我们只需要告诉Git:告诉我另一个哈希ID的第二个父对象的哈希ID。 最简单的方法是使用git rev-parse。假设的哈希ID Mbadf00d

git rev-parse badf00d^2
Run Code Online (Sandbox Code Playgroud)

Git吐出完整的哈希ID F。帽子二后缀的意思是“第二父母”(帽子一或仅帽子本身的意思是“第一父母”)。

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

git merge-base badf00d^1 badf00d^2
Run Code Online (Sandbox Code Playgroud)

然后,我们可以查看范围中的每个提交,从合并基础之后开始*,一直到并包括commit F,使用git loggit format-patch或其他方法。

我们可以用生哈希做到这一点,或者我们可以点名称(暂时性或永久性的,他们将生活完全一样,只要你喜欢),以提交MF和/或*使用git branchgit tag。每个名称都会为您记住哈希ID。标记名称和分支名称之间的主要区别在于,如果您git checkout使用标记名称,则会得到一个“分离的HEAD”并且不在分支上,但是如果您使用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)
Run Code Online (Sandbox Code Playgroud)

这就是Git中分支的全部内容:名称仅指向提交,而分支结构,历史记录或DAGlet或所需的任何名称由提交DAG的永久部分组成。分支名称具有特殊的功能,您可以使用git checkout它们并通过运行使它们前进git commit