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

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

我注意到,如果文件已被重命名,大多数graphicsgit前端和IDE插件似乎无法显示文件的历史logging。 当我使用

git log --follow 

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

根据Linus Torvalds的说法,下面的开关是一个“SVN noob”pleaser,严重的git用户不会使用它:

– 下面是一个彻头彻尾的黑客,意味着只是满足前SVN的用户谁也不知道什么东西,如父母或良好的修订图。

这不完全是根本性的,但目前实施的“跟随”实际上是一个快速预处理的事情,它被固定在修订行走逻辑上,而不是任何真正不可或缺的东西。

它从字面上被devise成“SVN noob”,而不是“真正的gitfunction”。 这个想法是,你将摆脱思维的思维模式,重新思考大事情。

我的问题 :你们当中的硬核用户如何在重命名时得到一个文件的历史logging? 什么是“真正”的方式来做到这一点?

我认为,Linus观点背后的一般驱动力是 – 用一小撮盐 – 硬核git用户从不关心“文件”的历史。 你把内容放在一个git仓库中,因为整个内容有一个有意义的历史。

文件重命名是在path之间移动的“内容”的一个小特例。 你可能有一个函数在一个git用户可能用“镐”function(例如log -S )跟踪的文件之间移动。

其他“path”更改包括合并和分割文件; git并不关心你考虑重命名哪个文件,你认为哪个文件被复制(或重命名和删除),它只是跟踪你的树的完整内容。

git鼓励“整棵树”的思想,尽可能多的版本控制系统都是以文件为中心的。 这就是为什么git比“filenames”引用更多的“path”。

我有完全相同的问题,你正面临着。 尽pipe我可以不给你答复,但我相信你可以阅读Linus在2005年写回的这封电子邮件 ,这是非常恰当的,可能会给你一个关于如何处理这个问题的暗示:

…我声称任何试图跟踪重命名的SCM,除非内部原因(即允许高效的delta),否则基本上是中断的,因为重命名并不重要。 他们不帮你,他们也不是你所感兴趣的。

重要的是find“这是从哪里来的”,git架构确实做得非常好 – 比其他任何东西都要好得多。 …

我发现这篇博客文章引用了这篇文章,这对您也可以find一个可行的解决scheme:

在消息中,Linus概述了一个理想的内容跟踪系统如何让你find一块代码如何进入当前的形状。 您将从文件中的当前代码块开始,回到历史logging中查找更改文件的提交。 然后你检查提交的变化,看看你感兴趣的代码块是否被修改,作为一个提交,修改文件可能不会触及你感兴趣的代码块,但只有其他部分文件。

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

  1. 提交真正引入了代码块。 提交人的作者是那个你正在寻找它的来源(或引入臭虫的有罪方)的那个很酷的function的发明者; 要么
  2. 该代码块不存在于该文件中,而是存在于不同文件中的五个相同的副本,所有这些副本在提交之后都消失了。 该提交的作者通过引入一个辅助函数来重构重复的代码; 要么
  3. (作为特殊情况)在提交之前,当前包含您感兴趣的代码块的文件本身并不存在,但是存在几乎相同内容的另一个文件,并且您感兴趣的代码块,以及当时存在的文件中的所有其他内容,确实存在于其他文件中。 它提交后就消失了。 该提交的作者给它一个小的修改时重命名了该文件。

在git中,Linus的终极内容跟踪工具还没有以全自动的方式存在。 但是大部分重要的成分已经可用了。

请告诉我们你的进度。

我注意到,如果文件已被重命名,大多数graphicsgit前端和IDE插件似乎无法显示文件的历史logging

你会很高兴知道一些stream行的Git UI工具现在支持这个。 有几十个Git UI工具可用,所以我不会列出所有的,但是例如:

  • SourceTree在查看文件日志时,在左下angular有一个checkbox“关注重命名的文件”
  • TortoiseGit在左下angular的日志窗口上有一个“follow renames”checkbox。

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

注意:git 2.9(June2016)会改善git log --follow的“buggy”本质 – git log --follow

参见SZEDERGábor ( szeder )的 commit ca4e3ca (2016年3月30日) 。
(由Junio C gitster合并- gitster -在26effb8 ,2016年4月13日提交 )

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

如果' dir/A/file '和' dir/B/file '这两个path具有相同的内容,并且父目录被重命名,例如' 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 ,和A/file -> B/file

虽然在技术上没有错,但是这不仅混淆了用户,而且也混淆了基于重命名信息的git命令,例如' git log --follow other-dir/A/file '跟在' dir/B/file '过去的重命名。

这种行为是提交diffcore-rename.c ^ diffcore-rename.cdiffcore-rename.c :简化查找精确重命名,2013-11-14) diffcore-rename.c :存储源的hashmap返回来自同一个桶的条目,即来源与当前目的地相匹配,按LIFO顺序。
因此迭代首先检查' other-dir/A/file '和' dir/B/file ',并在find相同的内容和基名后报告一个确切的重命名。

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