0

在 libgit2 标头中,我读到在 fetch 之后,如果在分析期间发出快进信号可用,那么需要的是简单检查所获取的提示(并更改 head/<branch>)。这似乎是合乎逻辑的,但是我想知道如何将 refs/heads/<branch> 与 remotes/<remote>/<branch> 区分开来?提交中嵌入了父项——这构成了一个历史记录,而应该有两个历史记录,其中两个历史记录都有额外的“合并”提交。那么快进是如何实现的呢?它确实导致 SHA 哈希在两个历史记录中重复,所以 libgit2 似乎有它的意义。

4

2 回答 2

3

由于 Git 是一个 CVCS,本地 repo 和远程 repo 在逻辑上可以被视为一个 repo。refs/heads/master(r)refs/heads/master远程仓库中。

克隆后

远程主机已被其他人更新。

远程更新

现在我们想通过远程主机更新本地主机git pull origin master

首先git fetch origin master在内部运行并remotes/origin/master更新。这实际上是一个快进合并。remotes/origin/master从 移动CE

取后

然后git merge remotes/origin/master运行。refs/heads/master通过快进合并更新。它也从C到移动E

在此处输入图像描述

如果refs/heads/master在拉取之前由我们更新,那将是真正的合并。拉之前就像

另一个案例

这里我们有两个选择,git pull origin master或者git pull origin --rebase master

获取过程是相同的。

另一个获取

没有--rebase,这将是一个真正的合并。

真正的合并

有了--rebase,这将是一个变基。

变基

P现在可以忽略它,因为它现在没有被任何分支或标签引用。

以最后一种情况为例,如果我们现在推refs/heads/master送到远程,refs/heads/master(r)将通过远程 repo 中的快进合并进行更新。

最终图

于 2016-08-12T14:39:51.067 回答
3

“快进”根本不是合并,它只是将分支指针设置到合并的“他们”一侧。

考虑一些历史:

1 -- 2 -- 3 -- 4 -- 5 -- 6

并考虑我的master分支在提交 4,而服务器的master分支在提交 6。

如果我希望将父级的主分支合并到我的(可能作为拉取的一部分),合并的第一步是找到合并基础,或者这两个提交之间的共同祖先。

在这种情况下(上图),44 和 6 之间的共同祖先。因此,本地没有服务器没有的提交,因此您可以简单地“快进”您的分支,将其指针更新为指向 6。这样做不会丢失任何数据(尽管您也不会创建任何数据 - 如果您使用“不快进”选项强制进行实际合并,那么您将在 4 到 6 之间创建一个新的合并提交。

所以 libgit2 的git_merge_analysis函数,它识别合并是否可以快进,实际上只是检查“你的”分支是否是你自己与“他们的”分支的共同祖先。

当然,这不是典型的合并案例。考虑:

             F -- G
            /
A -- B -- C -- D -- E

在这种情况下,如果您在G本地提交并且上游在提交,E那么您的共同祖先是C并且不可能快进,您必须执行真正的合并。

于 2016-08-12T10:43:26.193 回答