我对git比较陌生,之前我使用过Subversion。
我注意到,如果文件已重命名,大多数图形git前端和IDE插件似乎都无法显示文件的历史记录。当我使用
git log --follow
在命令行上,我可以看到重命名的整个日志。
According to Linus Torvalds --follow switch是一个“SVN noob”,严肃的git用户不使用它:
- follow是一个彻头彻尾的黑客,意味着只满足从未使用的前SVN用户 知道任何事情 父母身份或漂亮的修订图 反正。
这不是完全基本的,但是 当前实施的“--follow” 真的是一个快速的预处理事情 用螺栓固定在修正行走上 逻辑,而不是任何东西 真的不可或缺。
它实际上被设计为“SVN noob“喜欢,不是一个真正的混蛋 功能“的东西。这个想法是 你离开了(坏了) 重新思考的思维方式 大局中的问题。
我的问题:你们中的硬核git用户如何在重命名时获取文件的历史记录?这样做的“真实”方式是什么?
答案 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概述了理想的内容跟踪系统如何让您了解代码块如何进入当前形状。您将从文件中的当前代码块开始,返回历史记录以查找更改文件的提交。然后检查提交的更改以查看您感兴趣的代码块是否被它修改,因为更改文件的提交可能不会触及您感兴趣的代码块,而只会触及您感兴趣的代码块。文件。
如果在提交之前发现文件中不存在代码块,则会更深入地检查提交。您可能会发现这是许多可能的情况之一,包括:
- 提交真正引入了代码块。提交的作者是你寻找其起源的那个很酷的功能的发明者(或者是介绍这个bug的有罪方);或
- 文件中不存在代码块,但是在不同的文件中存在五个相同的副本,所有这些副本在提交后都消失了。提交的作者通过引入单个辅助函数重构了重复的代码;或
- (作为一种特殊情况)在提交之前,当前包含您感兴趣的代码块的文件本身不存在,但是存在具有几乎相同内容的另一个文件,并且您的代码块是感兴趣的是,与当时存在的文件中的所有其他内容一起,确实存在于该另一个文件中。提交后它就消失了。提交的作者在对文件进行了少量修改时重命名了该文件。
醇>在git中,Linus的终极内容跟踪工具尚未以完全自动化的方式存在。但大多数重要成分已经可以使用。
请告诉我们您在此方面取得的进展。
答案 2 :(得分:11)
我注意到,如果文件已重命名,大多数图形git前端和IDE插件似乎都无法显示文件的历史记录
您会很高兴知道一些流行的Git UI工具现在支持这一点。有许多可用的Git UI工具,所以我不会将它们全部列出,但例如:
有关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 ca4e3ca见SZEDER Gábor (szeder
)(2016年3月30日)
(由Junio C Hamano -- gitster
--合并于commit 26effb8,2016年4月13日)
如果这两条路径是
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
每个中间目录名。