【问题标题】:git log: summarize movement of directories containing lots of filesgit log:总结包含大量文件的目录的移动
【发布时间】:2013-11-13 01:54:25
【问题描述】:

我正在我的存储库中进行一些目录级别的重组。结果提交显示了很多文件级重命名,这掩盖了我所做的只是一两个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

【问题讨论】:

    标签: git rename git-log


    【解决方案1】:

    Git 动态计算文件重命名(使用“相似性索引”,参见 diff -M 选项;另见 -B-C)。如果,给定提交 c1c2,路径 path1 已经从 c1 并且 path2 出现在 c2 中,这是一个“重命名候选”。如果 path2 的文件内容与 path1 的文件内容足够相似,则该文件必须已重命名(并且可能也已修改,如果 -M 是小于100%)。

    要确定重命名是“目录重命名”,您需要添加以下形式的代码:

    • dir1 中的每个文件都消失了(包括未跟踪和忽略的文件)
    • 之前dir2 中没有出现文件(包括未跟踪和忽略的文件)
    • 鉴于动态检测到的重命名,名称为 dir1 的“足够”文件被重命名,因此路径中的 dir1 变为 dir2,而名称的其余部分保持不变

    决定将dir1 重命名为dir2。 (最后一点中的“足够”允许在新的dir2 之外重命名一些文件。)

    这里真正的关键点是括号中的两个位,“包括未跟踪和忽略的文件”。显然 git 不能告诉你这些文件的历史。 (当然可以假设不存在这样的文件,可能在选项标志的控制下。)我不确定这是否是决定不编写该算法的一个因素。但据我所知,它不在那里。

    【讨论】:

    • 未跟踪和忽略的文件根据定义不是历史的一部分,所以对我来说很明显log 命令的任何变体都不会考虑它们,包括这个目录移动-检测。
    • 请记住,git diff 输出被馈送到各种补丁应用程序(包括git applygit am)。如果 diff 输出显示“重命名此文件”并且您重命名目录中的所有文件,则它“正常工作”(除了留下一个空目录) - 但如果您收到“重命名此目录”命令并重命名包含未跟踪/忽略文件的目录,这可以说是错误的行为。我不认为这里有一个真正的正确/错误答案,只是一个常年的争论来源。 :-)
    猜你喜欢
    • 2013-07-06
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多