git log:总结包含大量文件的目录移动

4
我正在对我的存储库进行目录级别的重新组织。由此产生的提交显示了许多文件级别的重命名,这使得概念上我所做的只是一两个git mv dir1/ dir2/ 命令无法清楚地体现。
有没有一种方法可以使git log总结这种操作,以显示整个目录的移动?我认为 --dirstat 或者 --summarize 可以让我接近完成,但它们似乎并不能做到我想要的。
(我知道git的存储库模型不跟踪任何关于目录的信息,只跟踪文件。然而,文件重命名也是如此,但它能够在事后推导出有关文件级别重命名的信息。)
下面是一个简单的示例:
#setup
git init
mkdir dir1
for f in foo bar baz; do echo $f > dir1/$f; done
git add dir1
git commit -m 'dir1'

#do the directory move
git mv dir1 dir2
git commit -m 'rename dir1 to dir2'

此时,我希望看到像这样的东西:
$ git log -1 --what-options-go-here?
b0ba9c9 rename dir1 to dir2
0       0       {dir1 => dir2}/

相反,我似乎只能制作出这样的东西:
$ git log -1 --numstat --oneline
b0ba9c9 rename dir1 to dir2
0       0       {dir1 => dir2}/bar
0       0       {dir1 => dir2}/baz
0       0       {dir1 => dir2}/foo
1个回答

1
Git可以动态计算文件重命名(使用“相似性指数”,请参见diff -M选项;还有-B-C)。如果给定提交和,路径从中消失,而路径在中出现,则为“重命名候选”。如果的文件内容与的文件内容足够相似,则该文件必须已被重命名(并且可能也已被修改,如果-M小于100%)。
要确定重命名是“目录重命名”,您需要添加以下代码形式:
  • dir1 中的每个文件都消失了(包括未跟踪和被忽略的文件)
  • dir2 中没有出现任何文件(包括未跟踪和被忽略的文件)
  • 鉴于动态检测到的重命名,有足够多的名为 dir1 的文件被重命名,以使路径中的 dir1 成为 dir2,而其余部分名称保持不变

通过以上判断,dir1 被重命名为 dir2。(最后一点中的 "足够" 允许少数文件在新的 dir2 之外被重命名。)

这里真正棘手的问题是两个括号内的内容,即 "包括未跟踪和被忽略的文件"。显然,git 无法告诉您这些文件的历史记录。(当然,可以假设不存在这样的文件,或者通过选项标志来控制。)我不确定这是否是决定不编写该算法的因素;但据我所知,它并没有在其中。


未跟踪和被忽略的文件在定义上不属于历史记录的一部分,因此我认为它们不会被任何log命令的变体考虑在内,包括这个目录移动检测。 - Matt McHenry
请记住,git diff 输出被输入到各种补丁应用程序中(包括 git applygit am)。如果差异输出说“重命名此文件”,并且您重命名了目录中的所有文件,则它会“正常工作”(除了留下一个空目录)-但是如果您得到一个“重命名此目录”的命令,并且您重命名了包含未跟踪/忽略文件的目录,则这可能是错误的行为。我认为这里没有实际的对错答案,只有一个永恒的争论来源。 :-) - torek

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