gpt4 book ai didi

git - 如何获取整个git历史记录中每个文件的大小?

转载 作者:太空狗 更新时间:2023-10-29 14:31:42 24 4
gpt4 key购买 nike

我想从git存储库中删除大文件。但是,我想详细说明一下,所以我想查看存储库历史记录中的所有文件大小?
我已经创建了以下bash脚本,但它似乎效率很低,并且可能丢失了历史上某个地方删除的文件:

git log --pretty=tformat:%H | while read hash; do
git show --stat --name-only $hash | grep -P '^(?:(?!commit|Author:|Date:|Merge:| ).)*$' | while read filename; do
if [ ! -z "$filename" ]; then
git show "$hash:$filename" | wc -c | while read filesize; do
if [ $(echo "$filesize > 100000" | bc) -eq 1 ]; then
printf "%-40s %11s %s\n" "$hash" "$filesize" "$filename"
fi
done
fi
done
done

有什么更好的办法吗?

最佳答案

你是最棒的,真的。

git log --pretty=tformat:%H

这应该是 git rev-list <start-points>,例如 git rev-list HEADgit rev-list --all。您可能需要添加 --topo-order --reverse,原因我们稍后会联系您。
 | while read hash; do
git show --stat --name-only $hash

您可能只想在散列上使用 git show --stat,而不是 git ls-tree。使用递归 git ls-tree可以找到给定提交中的每个树和blob及其对应的路径名。
这些树可能不有趣,所以我们可能会掉下来。注意,顺便说一下,除非使用 git ls-tree,否则 -z将对一些有问题的文件名进行编码(但这会使读取项变得更困难;bash可以做到,而普通sh不能做到)。
 | grep -P '^(?:(?!commit|Author:|Date:|Merge:|   ).)*$' | while read filename; do

使用 git ls-tree我们可以将其替换为:
git ls-tree -r $hash | while read mode type objhash path; do
然后我们将跳过任何类型不是blob的内容:
[ $type == blob ] || continue
  if [ ! -z "$filename" ]; then

我们根本不需要这个。
      git show "$hash:$filename" | wc -c | while read filesize; do
if [ $(echo "$filesize > 100000" | bc) -eq 1 ]; then
printf "%-40s %11s %s\n" "$hash" "$filesize" "$filename"
fi

我不清楚为什么你有一个 while read filesize循环,也不清楚复杂的测试。在任何情况下,获取blob对象大小的简单方法是使用 git cat-file -s $objhash,并且很容易测试 [ $blobsize -gt 100000 ],例如:
    blobsize=$(git cat-file -s $objhash)
if [ $blobsize -gt 100000 ]; then
echo "$hash contains $filename size $blobsize"
fi

然而,通过放弃 git show而选择 git ls-tree -r,我们可以在每次提交中看到每个文件的每个副本,而不仅仅是在它出现的第一次提交中看到一次。例如,如果commit f00f1e添加了大文件 bigfile并且它在commit baafba6中保持不变,我们将看到这两次。使用 git show --stat运行 git diff的变体,将每个提交与其父级进行比较,这样,如果我们以前看到过该文件,就会忽略它。
轻微的缺陷(或者可能不是缺陷)是我们“重新看到”一个文件,如果它回来。例如,如果这个大文件在第三次提交时被删除,在第四次提交时被还原,我们将看到它两次。
这是我们可能想要的 --topo-order --reverse。如果我们使用这个,我们会在他们的孩子之前得到所有父母的承诺。然后,我们可以保存每个诊断对象哈希,并禁止重复诊断。这里有一个很好的编程语言,它有关联数组(散列表)会很方便,但是我们可以在纯bash中使用包含以前显示的对象散列的文件或目录来实现这一点:
#! /bin/sh

# get temporary file to hold viewed object hashes
TF=$(mktemp)
trap "rm -f $TF" 0 1 2 3 15

BIG=100000 # files up to (and including?) this size are not-big

git rev-list --all --topo-order --reverse |
while read commithash; do
git ls-tree -r $commithash |
while read mode type objhash path; do
[ $type == blob ] || continue # only look at files
blobsize=$(git cat-file -s $objhash)
[ $blobsize -lt $BIG ] && continue # or -le
# found a big file - have we seen it yet?
grep $objhash $TF >/dev/null && continue
echo "$blobsize byte file added at commit $commithash as $path"
echo $objhash >> $TF # don't print again under any path name
done
done

请注意,由于我们现在通过散列ID记住大文件,因此即使它们以另一个名称出现(例如,g e t git mved,或者被删除,然后以相同或另一个名称重新出现),我们也不会重新通知它们。
如果您更喜欢 git show使用的diff调用方法,我们可以使用它而不是保存临时文件的散列,但仍然可以通过使用适当的管道命令(即 git diff-tree)避免提交消息的笨拙重映射。使用-topo-order(就像一般规则一样)可能仍然是明智的,尽管它不再是必需的。所以这给出了:
BIG=100000 # just as before

git rev-list --all --topo-order | while read commithash; do
git diff-tree -r --name-only --diff-filter=AMT $commithash |
tail -n +2 | while read path; do
objsize=$(git cat-file -s "$commithash:$path")
[ $objsize -lt $BIG ] && continue
echo "$blobsize byte file added at commit $commithash as $path"
done
done

git diff-tree需要 -r递归工作(与 git ls-tree相同),需要 --name-only只打印文件名,需要 --diff-filter=AMT只打印添加、修改或更改的文件名(从符号链接到文件或从符号链接到文件)。令人讨厌的是, git diff-tree再次将提交ID打印为第一行。我们可以用 --no-commit-id来抑制id,但随后我们会得到一个空行,所以我们最好使用 tail -n +2来跳过第一行。
脚本的其余部分与您的相同,只是我们使用 git cat-file -s简单地获得对象的大小,并使用 [/ test程序直接测试它。
请注意,对于合并提交, git diff-tree(类似于 git show)使用组合diff,仅显示合并结果中不匹配任何父级的文件。这应该没问题,因为如果合并结果中的文件 huge是4gb,但与两个合并提交中的一个中的文件 huge是4gb相同,我们将在将其添加到该提交时看到 huge,而不是在合并本身中看到它。
(如果不需要,可以将 -m添加到 git diff-tree命令中。但是,您需要删除 tail -n +2并放入 --no-commit-id,它在 -m下的行为不同。git中的这种特殊行为有点烦人,尽管使用默认输出格式(类似于 git log --raw)是有意义的。
(注意:以上代码未经测试-在最后一次重读时发现并修复了 $hashvs $commithash。)

关于git - 如何获取整个git历史记录中每个文件的大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41623237/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com