Git - 如何确定一个提交属于哪个分支?

3
作为一个对 Git 相对陌生的人,我最近(终于!)明白了分支实际上只是指向特定提交的指针,有时候将“某个提交属于哪个分支”改为“哪些分支可以到达某个提交”可能更好一些。
例如,下面这张图来自官方 Git 文档:
在这张图片中,我本能地认为提交 C4 属于分支 master,而提交 C3 和 C5 属于 iss53。但是 C0 到 C2 呢?它们会属于两个分支吗?还是说我必须说它们是可以通过分支 master 和 iss53 到达的?
当我将 iss53 合并到 master 中时,这就变得更加复杂了:
因为将分支 iss53 合并到 master 中,所以 C0 到 C2 是否比属于 iss53 更加属于 master?
如果我在合并后删除分支 iss53 呢?那么提交 C3 和 C5 会属于哪个分支?经过更多思考之后,似乎在合并后,提交 C4、C3 和 C5 在分支历史方面是“相等”的,我无法确定它们三个属于哪个分支,因为删除 iss53 后,没有任何信息表明 C4 比 C3 和 C5 更像任何历史分支。
我找到了这个答案,它说用“哪些分支可以到达这个提交”来思考会更好。但这是否意味着 C4、C3 和 C5 都可以从 master 分支到达?但是如何处理图中发生的分支父关系呢?那重要吗?

另外,我提供的答案中还说明了可能有一些情况下某个提交可能无法被任何分支所引用,这种情况是如何发生的?它会带来哪些影响?

但我的主要问题仍然是:如何将提交与分支相关联?

P.S. 由此带来的一个侧面或离题问题是:一个提交是否可以有超过两个父提交?


2
是的,一个提交可以有两个以上的父节点。 - evolutionxbox
3
按照原文,我倾向于称之为“不清楚你在问什么”。你提出了很多澄清问题,这些问题与你的标题问题都不同。你链接的问题似乎已经准确回答了它。我认为你的困惑在于,在你的最后一个图示中,所有提交都在主分支(或由主分支可达)。此外,查看章鱼合并以获取超过两个父级的更多信息。 - TTT
@TTT:感谢您的批评。我必须承认,对于分支的学习过程对我来说是一个令人困惑的过程,如果我的问题不清楚,我很抱歉。我认为我试图问的是,在我在帖子中提到的众多情况下,您如何考虑提交和分支之间的关系?我想更具体地表达,但我承认这对我来说很难。如果您能建议更好的方法,我将倾听。 - hpy
1
那很有道理。理解DAG需要一些时间来适应(请参见torek的答案)。请注意,您的编辑询问了孤立的提交如何可能存在,正如Greg Burghardt所描述的那样-例如,如果一个提交仅可通过一个分支访问,并且该分支被删除,则提交将变为孤立状态并最终被垃圾回收,除非其他东西指向它(例如标签或reflog条目-回到torek的答案)。 - TTT
1
顺便提一句,回答你的标题问题时,重要的是要意识到措辞实际上应该是:“如何确定提交属于哪些分支?”更多信息请参见此处:https://dev59.com/kXE85IYBdhLWcg3wl0jF - TTT
2个回答

9
提交并不属于分支,它没有所有权。分支是指向提交的指针。每个提交都有一个或多个父提交。当多个分支合并在一起时,回溯分支历史不仅涉及直线。你需要重新调整对提交和分支的观点。
提交存在于许多分支中。
提交也可以不存在于任何分支中。
从概念上讲,Git存储库只是一个大的链表,其中每个节点至少指向另一个节点。 "分支" 只是指向其中一个节点的标记。 Git中的节点称为提交。在Git中删除分支只会删除指向提交的指针,但不会删除提交对象本身。你可以 恢复意外删除的分支,因为提交数据库被排列成一个链表,并且分支只是指针 - 一种书签。
“但这是否意味着C4、C3和C5都可以从主分支访问?”
是的,这正是它的含义。所有这些提交都是可达的,因为提交 C6 指向了 2 个不同的提交:C5C4
"branching parentage" 如何处理?这样做有什么影响吗?
提交 C6 有两个父提交。这意味着两个分支被合并在一起。这就是如何处理“分支衍生”的方法。拥有多个父提交的提交是通过 git mergegit pull 创建的(其中 git pullgit fetch 后跟着一个 git merge)。

3
为了补充Greg Burghardt的答案可达性(reachability)确实是关键概念。包含哈希ID和箭头的提交图(commit graph)就如同是这一切的全部。分支名称(branch names)只是提供给你(以及Git)进入图形的便捷方式(但请参考接下来段落中的git gc)。
提交图采用有向无环图(Directed Acyclic Graph或DAG)的形式。整个系统要求提交可以从某个外部名称中访问——一个分支名称就够了,但标签名称或者甚至Git的reflog条目也可以——以保持提交处于“活跃”状态。维护程序git gc会在需要时遍历整个提交数据库,找到那些没有从任何外部名称中访问到的提交,并将其从提交图中清除。可以从名称或从一个可访问到名称的提交中访问到的提交将保留在图形中。添加新提交到图形的命令通常都以运行git gc --auto结束,它告诉git gc稍微探测一下,猜测这个维护操作是否在此时是有益的,如果是,就会执行一次维护操作。
Git的其他部分会在必要和适当的时候进行图形遍历。例如git log命令就会从给定的提交开始做一个遍历,使用DAG进行操作。这种图形遍历使用队列(像许多图形遍历算法一样)并跟踪已经访问过的提交,以便它可以访问每个提交一次,即使有多种方法可以到达该提交。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接