为什么git commit不包含在其上创建分支的名称?


20

在使用功能分支的团队中使用git时,我经常发现很难理解历史上的分支结构。

例:

假设有一个功能分支Feature / make-coffee,并且在master上与该功能分支并行地进行了错误修复。

历史记录可能如下所示:

*     merge feature/make-coffee
|\
| *   small bugfix
| |
* |    fix bug #1234
| |
| *    add milk and sugar
| |
* |    improve comments
| |
* |    fix bug #9434
| |
| *    make coffe (without milk or sugar)
| |
* |    improve comments
|/
*

问题

乍一看,我很难分辨要素分支的哪一侧。我通常需要浏览双方的一些评论以了解哪个是哪个。如果有多个平行的要素分支(尤其是针对紧密相关的要素),或者在要素分支和母版之间都在两个方向上合并,则情况会变得更加复杂。

相比之下,在Subversion中,这非常容易,因为分支名称是历史记录的一部分-因此我可以立即告诉您,最初是在“功能/制造咖啡”上进行的。

通过创建提交时(连同作者,日期等),Git 可以通过在提交元数据中包括当前分支的名称来简化此过程。但是,git不会这样做。

是否有一些根本原因无法做到这一点?还是只是没有人想要该功能?如果是后者,还有其他方法可以在不看到名称的情况下了解历史分支的目的吗?


1
相关问题:查找提交来自哪个分支。尽管git并未明确记录该信息,但这是关于如何查找此信息的信息。
sleske 2013年

1
自我注意:有趣的是,在Mercurial中,提交确实包含分支名称。因此,Mercurial开发人员似乎做出了与git开发人员不同的设计决策。有关详细信息,请参见例如felipec.wordpress.com/2012/05/26/…
sleske 2014年

Answers:


14

可能是因为分支名称仅在一个存储库中有意义。如果我在make-coffee团队中并通过网守提交所有更改,我的master分支可能会被拉到网守的make-coffee-gui分支,他将与make-coffee-backend分支合并,然后重新部署到make-coffee合并到中央master分支的分支。

即使在一个存储库中,分支名称也可以并且确实随着工作流程的发展而变化。 例如,master稍后可能会更改development为。

正如CodeGnome所暗示的,git具有很强的设计理念,即在不需要时不将某些内容烘焙到数据中。用户应在事实发生后使用选项,git loggit diff根据自己的喜好输出数据。我建议您尝试一下,直到找到适合自己的格式。 git log --first-parent,例如,不会显示来自合并分支的提交。


2
但应注意的是,第一父母通常是错误的父母。因为通常一个人只是将母带拉进他们正在从事的工作,然后将他们的工作推向第一父级,而将母带到第二父级。
2013

1
@ JanHudec:实际上,这取决于:-)。如果从事这项工作的人将其合并,则可以。如果合并是在审核之后进行的,则审核者很可能已检出master并将功能分支合并到master中,对其进行测试并进行推送。
sleske 2014年

5

跟踪分支历史 --no-ff

在Git中,提交有祖先,但是“分支”实际上只是某些开发线的当前负责人。换句话说,提交是某个时间点工作树的快照,并且一次可以属于任何数量的分支。与其他DVCS相比,这是使Git分支如此轻便的部分原因。

Git提交不包含分支信息,因为它们对于Git历史记录不是必需的。但是,并非快进的合并当然可以携带有关合并了哪个分支的其他信息。通过始终将--no-ff标志传递给合并,可以确保您的历史记录包含此信息。git-merge(1)说:

   --no-ff
       Create a merge commit even when the merge resolves as a
       fast-forward. This is the default behaviour when merging an
       annotated (and possibly signed) tag.

通常,这将创建类似于的合并消息Merge branch 'foo',因此通常可以通过类似于以下内容的行找到有关“祖先分支”的信息:

$ git log --regexp-ignore-case --grep 'merge branch'

谢谢,但是(大部分)并不能回答我的问题。我不是在问还有什么其他方法可以找到原始分支,而是为什么不将这些信息作为常规元数据包括在内-这更多是一个设计问题。
sleske

1
@sleske我认为我的回答是响应性的:Git不会跟踪它,因为Git历史不需要它。我认为没有比这更根本的了。您必须查看源的详细信息,但是历史记录实际上是从当前分支的尖端向后计算的。您始终可以将其与将分支视为一流对象的其他DVCS进行比较,看看您是否更喜欢这种设计理念。YMMV。
CodeGnome

1
最后一个应该是git log --merges

3

最简单的答案是分支的名称是短暂的。如果要重命名分支(git branch -m <oldname> <newname>)怎么办?针对该分支的所有提交会发生什么?或者,如果两个人在不同的本地存储库中拥有名称相同的分支,该怎么办?

在git中唯一有意义的是提交本身的校验和。这是跟踪的基本单位。

信息在那里,您只是不要求它,而且信息不完全在这里。

Git将每个分支的首部的校验和存储在中.git/refs/heads。例如:

... /。git / refs / heads $ ls测试 
-rw-rw-r-- 1 michealt michealt 41 Sep 30 11:50测试
... /。git / refs / heads $猫测试 
87111111111111111111111111111111111111d4

(是的,我破坏了我的git校验和,这并不特殊,但是它们是我正在查看的私有存储库,不需要意外泄漏任何内容)。

通过查看并跟踪作为父级,父级父级或父级父级的所有提交,您可以找出给定提交所在的分支。这只是一个要渲染的大图。

将提交存储在提交本身中的分支的名称(可以如上所述更改的分支)的位置,这是对提交无济于事的额外开销。存储提交的父项及其好处。

您可以通过运行带有相应标志的git log命令来查看分支。

git log-分支--source --pretty = oneline --graph
git log --all --source --pretty = oneline --graph

有很多不同的方法来选择您想要的东西-请查看git log文档-本-all节以及随后的一些选项。

* 87111111111111111111111111111111111111d4测试将分支'test1'合并到测试中
| \  
| * 42111111111111111111111111111111111111e8 test1更新:添加内容
* | dd11111111111111111111111111111111111159测试合并分支test3到测试
| \ \  

“ test”,“ test1”和“ test2”是这些承诺的分支。

请注意,git日志文档非常庞大,几乎可以从中获得任何想要的东西。


3

为什么git commit不包含在其上创建的分支的名称?

只是设计决定。如果您需要该信息,则可以添加prepare-commit-msg或commit-msg挂钩,以在单个存储库上实施该挂钩。

BitKeeper灾难之后,Linus Torvalds开发了git以匹配Linux内核开发过程。在那里,直到补丁被接受,才对其进行修改,编辑,修饰(多次通过Mail),签名(=编辑提交),精心挑选,徘徊在中尉的分支,也许经常会改头换面,进行更多修改, -小插针等,直到它们最终被Linus上游合并。

在这样的工作流程中,可能没有提交的特定来源,并且通常会在git分发时,在一些不重要的私有随机存储库中的某个临时调试分支中创建一个提交,并使用有趣的分支名称。

也许设计决定是偶然发生的,但是它与Linux内核开发过程完全匹配。


2

因为在Git 中,合并功能分支时,像“煮咖啡”这样的提交被视为两个分支的一部分。甚至还有一个命令来检查:

% git branch --contains @
  feature/make-coffee
  master

而且,分支机构便宜,本地且空灵。它们可以轻松地从服务器添加,删除,重命名,推送和删除。

Git遵循一切都可以完成的原则,这就是为什么您可以轻松地从远程服务器中删除分支,并且可以轻松地重写历史记录的原因。

假设我在“ master”分支中,并且进行了两次提交:“煮咖啡”和“添加牛奶和糖”,然后决定使用新的分支,因此我将“ master”重置为“ origin” /主'。没问题,所有的历史仍然是干净的:“煮咖啡”和“添加牛奶和糖”不是大师的一部分,仅是特色/煮咖啡。

水银则相反。它不想改变事情。分支是永久性的,重写历史已成问题,您不能仅从服务器中删除分支。

简而言之:Git允许您做所有事情,Mercurial希望使事情变得容易(并且让您做自己想做的事情真的很难)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.