4

了解 Git 工作流文章说,

所以你添加了一条新规则:“当你在你的特性分支中合并时,使用 –no-ff 来强制一个新的提交。” 这样就完成了工作,然后您继续前进。

然后有一天你在生产中发现了一个严重的错误,你需要追踪它是什么时候引入的。您运行 bisect 但继续登陆检查点提交。你放弃并亲自调查。

您将错误缩小到单个文件。你跑去责备看看它在过去 48 小时内是如何变化的。您知道这是不可能的,但责备报告该文件已数周未动过。事实证明,责备报告在初始提交时发生了变化,而不是在合并时。你的第一次检查点提交几周前修改了这个文件,但今天合并了。

no-ff 创可贴、折断的二分法和怪罪之谜都是您将螺丝刀用作锤子的症状。

git merge--no-ff是您明确阻止快进合并的一种情况。但是,如果一个提交不是另一个提交的直接祖先,那么快进甚至不会发生。这是开发中罕见的情况。换句话说,大多数合并都是非快进类型。那么传递如何--no-ff破坏bisectand的功能blame呢?

4

2 回答 2

7

tl;博士

合并提交并且与或本身--no-ff没有任何关系。git bisectgit blame

混合公共私人历史使得更难理解不同提交引入的更改。git bisect这在使用和git blame调试时变得非常明显。

合并提交和git bisect

正如@torek 所说,通过传递强制创建合并提交--no-ffgit bisect.

真正的问题来自于使用临时提交(有时称为检查点提交)污染存储库的公共历史记录,程序员使用这些临时提交来跟踪他们自己的本地工作。

由于它们的临时性,这些提交往往是不一致的——可能会在代码库中引入错误——并且记录不充分。在调试会话中间进行这样的提交git bisect并不是一个愉快的经历。补丁可能难以解释,或者更糟糕的是,它可能会破坏工作树中的代码。

我认为Linus Torvalds说得最好

我想要干净的历史,但这实际上意味着(a)干净和(b)历史。

关于“干净”部分,他继续详细说明:

保持自己的历史可读。

有些人这样做只是先在头脑中解决问题,而不是犯错误。但这非常罕见,对于我们其他人来说,我们在解决问题时使用“git rebase”等。

不要暴露你的废话。

合并提交和git blame

实际上,git blame合并提交确实会对您获得的结果产生影响

git blame总是显示给定代码行的原作者;换句话说,是谁将它添加到文件中的。从 Git 的角度来看,合并提交不会向文件添加任何内容,它只是表示存储库的目录和文件的快照,这些快照是组合两行或多行历史记录的结果。除非它是一个邪恶的合并,否则就是这样。

这意味着git blame在合并文件上运行将向您显示每一行的原始作者,无论谁进行了合并提交。

这就是为什么合并提交会使跟踪特定更改的人员和时间变得更加困难。但是话又说回来,无论如何,您都不应该将私有提交合并到公共分支中,因为除了原始作者之外,它们对其他任何人都没有意义。

于 2015-12-21T12:09:39.133 回答
3

那么传递 --no-ff 是如何破坏 bisect 和 blame 的功能的呢?

我认为不会。此外,我认为您引用的博客文章也没有说明。让我重新摘录并添加一点重点:

您运行 bisect 但继续登陆检查点提交。你放弃并亲自调查。

由于检查点提交,您已经放弃了二分法。Bisect 必须测试它们,因为它们是可能引入错误的提交,但由于它们是检查点提交,它们实际上可能无法测试,您必须告诉 bisect 跳过它们。如果您坚持使用 bisect,它可能最终会发现该错误位于大范围内的提交中,并且您可以通过修复被大范围提交破坏的行来修复它,您可能会检查通过这样做git diff A B,在哪里A是大范围开始之前的提交,并且B是大范围结束时的提交。在这种情况下,为什么不直接将一个提交从AB

(这里我就不赘述git blame了。)

Ben Sandofsky(博客文章的作者)建议你在这里做的不是“避免--no-ff”,而是:“当准备一系列小的检查点提交以发布并推回实际项目时,不要只是推所有原始的小提交未更改直接进入项目。” 然后,他概述了清理它们的几个选项,最简单的是将所有小提交压缩到一个单一的多合一提交中。

我会将他的其他选项(对于更大的功能更有意义)留在他的博客文章中,但是假设您正在查看许多应该简单地压缩为单个提交的小型检查点提交,这对您来说应该是微不足道的将该壁球作为附加到当前历史记录的单个提交来执行,因此不需要分支来保存它并合并将其引入。执行“从私有分支获取大范围的提交并获取准备好进行新的单个已发布分支提交提示”是git merge --squash,它不会进行合并(也不会提交),1后跟git commit.


1因此,它可能一开始不应该拼写git merge,但这对你来说是 git:如果有一个命令git eatcake,它会有一个吃蛋糕的选项,第二个选项只是把小麦磨成面粉,同时也分离鸡蛋,以防你想先自己做蛋糕,第三个选项是测试它是否会分离的鸡蛋,如果它在做第二种模式,已经坏了。

于 2015-12-21T08:07:06.497 回答