Git:`git bisect`和`git blame`中 `--full-history` 的等效选项是什么?

8
我已经使用 Git 工具七年了,最近几天发现了一些令我惊讶的行为。我发现在使用 git loggit blamegit bisect 命令时出现了奇怪的行为。 一位朋友告诉我可以通过在 git log 命令中添加 --full-history 参数来解决这个问题。 我想知道是否有类似的方法可以修复 git blamegit bisect 的问题。请随意使用此存储库自行查看问题:https://dl.dropboxusercontent.com/u/1927707/problematic_repo.7z。以下是其日志:
$ git log  --graph
* commit b7a8d7aa001d06eb7491ab5fb447a8dd3aa421a8
| Author: Ram Rachum <ram@rachum.com>
| Date:   Tue Apr 19 17:45:01 2016 +0300
|
|     adding more to some-file
|
*   commit 0aa833916e908ea93902a6c4c227f9a884a1bcef
|\  Merge: 2413945 3068c7d
| | Author: Ram Rachum <ram@rachum.com>
| | Date:   Tue Apr 19 17:44:31 2016 +0300
| |
| |     Merge branch 'master' into development
| |
| * commit 3068c7d2548f1798b6840f73b13a649937339f28
| | Author: Ram Rachum <ram@rachum.com>
| | Date:   Tue Apr 19 16:02:27 2016 +0300
| |
| |     Adding sugar to coffee
| |
* | commit 24139451ab954b1f0a9ef616775a3dba0ac81669
|/  Author: Ram Rachum <ram@rachum.com>
|   Date:   Tue Apr 19 16:01:28 2016 +0300
|
|       Creating some-file
|
* commit cf02fbbc40104cd02eea4c7c6f134ef1fd7b5661
  Author: Ram Rachum <ram@rachum.com>
  Date:   Tue Apr 19 16:00:47 2016 +0300

      Create coffee

在第一次提交时,添加了文件coffee。在提交3068c7d中,我向coffee文件添加了一行“sugar”。但是,然后我将这个分支合并到development分支中,在合并过程中出现了错误,导致“sugar”行被删除,使得coffee文件变为空。接着,又添加了另一个提交b7a8d7a进行无关的更改,以确保情况稳定。

现在我看着我的咖啡,发现里面没有加糖。我清楚地记得在我的咖啡里加了糖。我运行git log coffee,并得到以下输出:

$ git log coffee
commit cf02fbbc40104cd02eea4c7c6f134ef1fd7b5661
Author: Ram Rachum <ram@rachum.com>
Date:   Tue Apr 19 16:00:47 2016 +0300

    Create coffee

就是这样。 git log 没有显示添加该文件后又删除它的合并提交和原始提交,这两个提交非常重要。

我为此问题苦恼了一个小时,因为它发生在一个巨大的企业存储库中,手动查找提交非常困难。

我还尝试使用 git bisectgit blame 来确定这两个提交,但这两个工具都忽略了这两个提交。在我完成所有 git bisect badgit bisect good 操作后,git bisect 将我指向错误的提交。

然后,正如我在开头所说的,一位朋友向我指出了 --full-history 标志:

$ git log --full-history --graph coffee                
*   commit 0aa833916e908ea93902a6c4c227f9a884a1bcef    
|\  Merge: cf02fbb 3068c7d                             
| | Author: Ram Rachum <ram@rachum.com>                
| | Date:   Tue Apr 19 17:44:31 2016 +0300             
| |                                                    
| |     Merge branch 'master' into development         
| |                                                    
| * commit 3068c7d2548f1798b6840f73b13a649937339f28    
|/  Author: Ram Rachum <ram@rachum.com>                
|   Date:   Tue Apr 19 16:02:27 2016 +0300             
|                                                      
|       Adding sugar to coffee                         
|                                                      
* commit cf02fbbc40104cd02eea4c7c6f134ef1fd7b5661      
  Author: Ram Rachum <ram@rachum.com>                  
  Date:   Tue Apr 19 16:00:47 2016 +0300               

      Create coffee                                    

这让我很高兴,因为它显示了两个相关的提交,一个添加了sugar,另一个合并了它,所以我的问题解决了。

但是我真的希望知道如何让git bisectgit blame表现得更好。 有人知道吗?


“git blame” 可能会直接在此处使用 “--full-history”(我会在您的存储库上尝试,但我无法解压缩 7zip 文件)。Bisect 可能会拒绝处理合并,因为它自己处理它们。通常,您没有看到这些内容,因为 “git rev-list” 跳过了许多合并:请参阅文档中有关 TREESAME 和合并处理的讨论(以及 --full-history 如何更改此内容)。 - torek
@torek 我现在试了一下,blame似乎接受了标志,但看起来它并没有改变任何东西。尝试使用git blame --full-historygit blame --full-history --reverse都没有显示结果。关于无法打开7z档案的问题,在这里我已经将其转换为zip格式:https://dl.dropboxusercontent.com/u/1927707/foo.zip - Ram Rachum
@torek 我也尝试了 git blame --reverse HEAD^^^..HEAD --full-history coffee,但仍然没有得到任何结果。 - Ram Rachum
这里并不是要给你一个万能解决方案,但你可能会发现 https://github.com/dreamyguy/gitlogg 很有用,可以将所有提交解析为 JSON 格式,以便您可以仔细查看它们。您可能需要取消注释 gitlogg-parse-json.js 文件中的所有注释字段,并删除 gitlogg-generate-log.sh 中的 --no-merges 以获取所有可用输出。 - Wallace Sidhrée
1个回答

1

很有趣。由于这一行不在,git blame的输出并没有什么用。正如git blame文档所述:

此报告不会告诉您关于已删除或替换的行的任何信息;您需要使用类似 git diff 或“pickaxe”界面的工具,简要提及以下段落。

在这种情况下,我们可以运行 git log -SSugar 命令查找其更改记录:

$ git log --pretty=oneline -SSugar
3068c7d2548f1798b6840f73b13a649937339f28 Adding sugar to coffee

但是git blame不能立即帮助我们找到它的去向。(正如你刚刚发现的,如果我们想要在提及文件时找到那行代码,我们可能需要使用--full-history,因为添加路径来限制git log将考虑的提交,也会通过修剪每个提交的树以仅包含所提及的文件,然后使用TREESAME代码来简化历史。)

从已知的良好版本开始,现在我们可以尝试使用--reverse [编辑: 我注意到3068c7d2548f1798b6840f73b13a649937339f28 == master,实际上在这里使用了master,可能应该直接使用SHA-1]:

$ git blame --reverse master..HEAD coffee
^3068c7d (Ram Rachum 2016-04-19 16:02:27 +0300 1) Sugar

这似乎意味着3068c7d是最后一个包含该行的版本,因此必须在沿着该特定路径的某些或所有子节点中删除它,这是正确的:
$ git log --oneline --graph --decorate --all
* b7a8d7a (HEAD -> development) adding more to some-file
*   0aa8339 Merge branch 'master' into development
|\  
| * 3068c7d (master) Adding sugar to coffee
* | 2413945 Creating some-file
|/  
* cf02fbb Create coffee

这里只有一个提交是 3068c7d 的子提交,即 0aa8339,所以:

$ git show -m 0aa8339
commit 0aa833916e908ea93902a6c4c227f9a884a1bcef (from 3068c7d2548f1798b6840f73b1
Merge: 2413945 3068c7d
Author: Ram Rachum <ram@rachum.com>
Date:   Tue Apr 19 17:44:31 2016 +0300

    Merge branch 'master' into development

diff --git a/coffee b/coffee
index 4d0f160..e69de29 100644
--- a/coffee
+++ b/coffee
@@ -1 +0,0 @@
-Sugar
diff --git a/some-file b/some-file
new file mode 100644
index 0000000..e69de29

我们需要使用-m参数让git将合并与两个父提交进行比较。这样可以找到它,尽管有点绕。

同时,似乎没有治愈分裂问题的方法。唯一的方法是“避免恶意合并”...


谢谢你的回答!我的错误在于没有使用正确的左提交来使用 --reverse - Ram Rachum
更新:我现在尝试在类似的情况下使用“blame”,但旧提交删除了之前存在的行,而合并错误地重新添加了它们。即使我使用“--full-history”和“--full-history --reverse branch..other_branch”,“blame”也无法显示错误地重新添加行的合并。有什么想法吗? - Ram Rachum
我不太确定:我自己并不常使用 git blame。总的来说,无论是向前还是向后,它只是比较(文件中的)每一对先前/后续提交的行,以查看是否有行被修改或删除。然后,该行会被分配与该对提交的相应提交ID。由于存在多个配对,这种方法在合并时并不能很好地工作。 - torek

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