识别引入大量文件的提交

时间:2015-10-05 01:33:08

标签: git

我有一些资产元数据提交引入了数千个文件(数百兆字节的小文件)。此后几次,整个元数据已被替换或删除。

知道其中一些过去的提交不再与存储库的当前状态相关。

如何找到按引入的文件数排序的提交列表?

2 个答案:

答案 0 :(得分:3)

对于任何特定的SHA,您可以获得添加此文件的文件数量,这将打印出来并仅使用添加文件的A的diff过滤器计算添加的文件。

numFiles=$(git diff --name-status --diff-filter=A ${sha}^! | wc -l)

如果您将其包装在一个简单的脚本中,您可以打印出一个带有相关文件的SHA列表,您可以通过管道进行排序。指定START和END SHA以限制结果。

#!/bin/sh

for sha in $(git rev-list ${START_SHA}..${END_SHA})
do
   numFiles=$(git diff --name-status --diff-filter=A ${sha}^! | wc -l)
   echo "${numFiles} ${sha}"
done

答案 1 :(得分:1)

从根本上说,每次提交都是(或者#34;有")存储的树,它独立于每个其他提交,因此要获得通过提交添加的文件"你必须比较(即差异)提交与其他提交。

对于许多/大多数提交,可以轻松选择其他提交:使用提交的(单个)父提交。对于合并提交(那些有两个或更多父母的人),答案不太明显,我也不知道你会为这些做什么。

对于根提交(没有父提交的提交),您仍然可以通过对git' s "well known, if poorly advertised, empty tree"进行区分来获取相对于空树添加的文件数。或者,您可以选择完全忽略root提交(这简化了您的任务)。

没有一个git命令会在这里为你做所有事情,但很容易将一个脚本或管道放在一起来完成这个任务。要知道的主要事情是您将使用git rev-list生成所有候选提交ID:

git rev-list --min-parents=1 --max-parents=1 HEAD
例如,

将为您提供一个列表,其中列出了每个可以从HEAD到达的具有1个父项的提交(即,既不是合并提交也不是根提交)。由您来决定这是否是您要检查的提交。

如果是的话,我们现在处于相当不错的状态,因为我们可以简单git diff针对其(单个)父母进行每次此类提交:

git rev-list --min-parents=1 --max-parents=1 HEAD | \
while read sha1; do \
    ...
done

现在的诀窍是让git diff给我们添加的文件数量,也许可以从另一个命令获得一点帮助。这非常简单,因为git diff具有--name-status--name-only选项,还有--diff-filter选项。使用--name-status会得到如下输出:

$ git diff --name-status 0df0541bf13723658d31b8d1376b505b710e63c6^ \
  0df0541bf13723658d31b8d1376b505b710e63c6
A       Documentation/RelNotes/2.4.5.txt
M       Documentation/git.txt
M       GIT-VERSION-GEN
M       RelNotes

添加--diff-filter=A会删除除A dded文件以外的所有文件,之后我们真的不需要--name-status(也不会伤害它),因为只有名称,{ {1}},会告诉我们在比较这两个提交时添加了哪些文件:

--name-only

通过$ git diff --name-only --diff-filter=A \ 0df0541bf13723658d31b8d1376b505b710e63c6^ \ 0df0541bf13723658d31b8d1376b505b710e63c6 Documentation/RelNotes/2.4.5.txt 运行此输出得到一个行数,这也是一个文件计数,因为每个文件名都在它自己的行上。 1

所以,现在我们有一个看起来像这样的脚本(我现在将反斜杠留出来):

wc -l

然后,可以将此脚本的输出传递给git rev-list --min-parents=1 --max-parents=1 HEAD | while read sha1; do echo $(git diff --name-only --diff-filter=A ${sha1}^ ${sha1} | wc -l) $sha1 done

您可能希望稍微调整一下,具体取决于您需要对合并执行的操作。您可能还希望在sort -rn命令上击败重命名检测(或者可能不是,它确实取决于您如何使用它)。

1 无论如何,忽略将换行符嵌入文件名的可能性。如果你想要一个非常通用的工具,你应该考虑这种可能性,但你可以根据自己的情况忽略它。