如何使用git真正显示重命名文件的日志?

时间:2011-04-21 11:55:57

标签: git

我对git比较陌生,之前我使用过Subversion。

我注意到,如果文件已重命名,大多数图形git前端和IDE插件似乎都无法显示文件的历史记录。当我使用

git log --follow

在命令行上,我可以看到重命名的整个日志。

According to Linus Torvalds --follow switch是一个“SVN noob”,严肃的git用户不使用它:

  

- follow是一个彻头彻尾的黑客,意味着只满足从未使用的前SVN用户   知道任何事情   父母身份或漂亮的修订图   反正。

     

这不是完全基本的,但是   当前实施的“--follow”   真的是一个快速的预处理事情   用螺栓固定在修正行走上   逻辑,而不是任何东西   真的不可或缺。

     

它实际上被设计为“SVN   noob“喜欢,不是一个真正的混蛋   功能“的东西。这个想法是   你离开了(坏了)   重新思考的思维方式   大局中的问题。

我的问题:你们中的硬核git用户如何在重命名时获取文件的历史记录?这样做的“真实”方式是什么?

6 个答案:

答案 0 :(得分:64)

我认为Linus背后的一般驱动力是 - 并且带着一点点盐 - 硬核git用户不关心“文件”的历史。您将内容放在git存储库中,因为整个内容具有有意义的历史记录。

文件重命名是在路径之间移动的“内容”的一个小特例。您可能有一个在git用户可能跟踪的文件之间移动的功能,其功能是“pickaxe”(例如log -S)。

其他“路径”更改包括合并和拆分文件; git并不关心您考虑重命名的文件以及您认为复制(或重命名和删除)的文件只跟踪树的完整内容。

git鼓励“整棵树”思考,因为许多版本控制系统都是以文件为中心的。这就是为什么git比“文件名”更频繁地引用“路径”。

答案 1 :(得分:34)

我遇到的问题完全相同。即使我没有给你答案,我相信你可以阅读this email Linus在2005年写的,这是非常恰当的,可能会给你一个关于如何处理问题的提示:

  

...我声称任何试图跟踪重命名的SCM都是基本的   除非由于内部原因(即允许有效率)这样做而破裂   deltas),正是因为重命名并不重要。他们没有帮助你,而且   它们不是你对无论如何感兴趣的

     

重要的是找到“这是从哪里来的”和git   建筑确实做得非常好 - 比其他任何东西都好   在那里。 ...

我发现它由this blog post,引用,这对您找到可行的解决方案也很有用:

  

在消息中,Linus概述了理想的内容跟踪系统如何让您了解代码块如何进入当前形状。您将从文件中的当前代码块开始,返回历史记录以查找更改文件的提交。然后检查提交的更改以查看您感兴趣的代码块是否被它修改,因为更改文件的提交可能不会触及您感兴趣的代码块,而只会触及您感兴趣的代码块。文件。

     

如果在提交之前发现文件中不存在代码块,则会更深入地检查提交。您可能会发现这是许多可能的情况之一,包括:

     
      
  1. 提交真正引入了代码块。提交的作者是你寻找其起源的那个很酷的功能的发明者(或者是介绍这个bug的有罪方);或
  2.   
  3. 文件中不存在代码块,但是在不同的文件中存在五个相同的副本,所有这些副本在提交后都消失了。提交的作者通过引入单个辅助函数重构了重复的代码;或
  4.   
  5. (作为一种特殊情况)在提交之前,当前包含您感兴趣的代码块的文件本身不存在,但是存在具有几乎相同内容的另一个文件,并且您的代码块是感兴趣的是,与当时存在的文件中的所有其他内容一起,确实存在于该另一个文件中。提交后它就消失了。提交的作者在对文件进行了少量修改时重命名了该文件。
  6.         

    在git中,Linus的终极内容跟踪工具尚未以完全自动化的方式存在。但大多数重要成分已经可以使用。

请告诉我们您在此方面取得的进展。

答案 2 :(得分:11)

  

我注意到,如果文件已重命名,大多数图形git前端和IDE插件似乎都无法显示文件的历史记录

您会很高兴知道一些流行的Git UI工具现在支持这一点。有许多可用的Git UI工具,所以我不会将它们全部列出,但例如:

  • SourceTree,在查看文件日志时,有一个复选框"关注重命名的文件"在左下角
  • TortoiseGit有一个"跟随重命名"左下角的日志窗口上的复选框。

有关Git UI工具的更多信息:

答案 3 :(得分:6)

注意:git 2。9(2016年6月)将改善相当多的" buggy" [{ "TableName": "Table_A", "FieldCode": "Title_MR", "FieldDescription": "MR" }, { "TableName": "Table_A", "FieldCode": "Title_MRS", "FieldDescription": "MRS" }, { "TableName": "Table_B", "FieldCode": "Code", "FieldDescription": "Z0912" }] 的性质:

commit ca4e3caSZEDER Gábor (szeder)(2016年3月30日) (由Junio C Hamano -- gitster --合并于commit 26effb8,2016年4月13日)

diffcore:修复重命名检测期间相同文件的迭代顺序

  

如果这两条路径是git log --follow'和' dir/A/file'内容相同   并且重命名父目录,例如' dir/B/file',然后   git mv dir other-dir报告以下确切重命名:

diffcore

(请注意此处的反转:renamed: dir/B/file -> other-dir/A/file renamed: dir/A/file -> other-dir/B/file B/file -> A/file

  

虽然技术上没有错,但这不仅令用户感到困惑,   但也适用于根据重命名做出决定的git命令   信息,例如' A/file -> B/file'如下   ' git log --follow other-dir/A/file'过了重命名。

     

此行为是commit v2.0.0-rc4~8 ^ 2~14的副作用   (dir/B/file:简化查找精确重命名,2013-11-14):.   存储源的hashmap返回同一桶中的条目,即   以LIFO顺序匹配当前目的地的来源。
  因此,迭代首先检查' diffcore-rename.c'和' other-dir/A/file'并且,在找到相同的内容和基本名称后,报告确切的重命名。

答案 4 :(得分:2)

在Linux上,我已经确认SmartGit和GitEye能够在跟踪特定文件的历史记录时遵循重命名。但是,与gitk和GitEye不同,SmartGit显示单独的文件视图和存储库视图(包含目录结构,但不包含其中包含的文件列表)

答案 5 :(得分:1)

这是你的做法:

git log -M --summary | grep rename | grep BASENAME

只需将基本名称放在那里即可。

如果结果太多那么你也可以连续grep每个中间目录名。