Git存储库维护和审计工具

时间:2017-08-06 16:22:46

标签: git

我想在Git存储库中执行一些审核维护操作,因为有些开发人员有时候版本文件不应该是常规版本(健康)存储库:已编译的二进制文件,第三方文档文件......

在过去几个月中,存储库的大小已大大增加,我想知道原因:添加了哪些文件,文件扩展名,文件大小...即使这些文件可能已被删除,元数据仍然存在,影响克隆,拉取和获取命令,而git元数据目录确实很大。

我知道 git log 命令提供了这样的功能,但我想知道是否有其他工具( UI工具可能?)提供更多集成,易于比较和对比有关 git存储库使用情况的信息。

总而言之,我有哪些选择来获取Git信息:

  1. 添加到某个大小文件的存储库中的文件 延期,来自某个时间和(如果可能)这样做。

  2. 删除的文件。是否有可能消除他们?

2 个答案:

答案 0 :(得分:7)

关于git的好处在于它暴露了所有的内容,所以你可以看看它们。

在您的情况下,您正在关注大型 blob 。如果您不熟悉git如何在内部工作,它基于将对象映射到SHA-1哈希的对象数据库。提交是对象,每个提交包含一个,它是一个列出目录内容的对象,这些对象可以是其他树(对于子目录)或< em> blobs (用于文件数据)。

这意味着如果两个文件具有相同的内容,则它们将共享一个 blob 。这也意味着如果你改变一个对象,它的ID也会改变(你会在这个答案的最后看到那个的后果)。

如何获取报告

首先,确保您正在使用镜像存储库,因此请使用--mirror选项进行克隆:

git clone --mirror https://my-host/my-repo.git

好的,现在这里有一个命令可以显示200个最大的blob:

git rev-list --objects --all | git cat-file --batch-check='%(objectname) %(objecttype) %(objectsize) %(rest)' | sort -nr -k 3 | perl -ne 'm#^(\w+) blob (\d+) (.+)# or next; print "$1\t$2\t$3\n";' | head -n 200 | column -t -s $'\t'

让我们稍微分解一下:

  • git rev-list --objects --all将输出存储库中使用的所有对象ID(SHA-1哈希值),然后输出blob的文件路径(docs)。
  • git cat-file --batch-check='%(objectname) %(objecttype) %(objectsize) %(rest)'将重新格式化git rev-list的输出并插入一些我们感兴趣的数据(如对象大小)(docs)。
    在此处,%(rest)将替换为之后的部分输入上的对象ID - 它是指向blob的文件路径。
  • sort -nr -k 3将对blob size进行反向排序
  • perl -ne 'm#^(\w+) blob (\d+) (.+)# or next; print "$1\t$2\t$3\n";'只会输出任何不是blob的内容并重新格式化输出
  • head -n 200将采用前200项
  • column -t -s $'\t'将很好地重新格式化输出

请注意要删除的blob的对象ID。

请记住,我们在这里谈论的是 blob ,而不是文件。如果更改文件,则该文件将包含2个blob:每个已提交的版本都有一个blob。另外,请记住,由于git执行GC时发生的增量压缩,总磁盘使用量将 小于每个blob的大小总和。如果两个blob非常相似(因为提交通常只会改变文件的一小部分),则delta压缩将非常有效。

现在您可以调整此命令以生成其他报告。这是一个不那么花哨的版本,可以做同样的事情:

git rev-list --objects --all | git cat-file --batch-check='%(objectname) %(objectsize) %(rest)' | sort -nr -k 2 | head -n 200

以下是如何按文件扩展名分组blob大小:

git rev-list --objects --all | git cat-file --batch-check='%(objectname) %(objecttype) %(objectsize) %(rest)' | perl -ne 'm#^(\w+) blob (\d+) .+?(?:\.(\w+))?$# or next; next if $h{$1}++; $ext = $3 ? lc $3 : "<none>"; $s{$ext} += $2; ++$c{$ext}; END { foreach $ext (keys %s) { print "$ext $s{$ext} $c{$ext}\n"; } }' | sort -nr -k 2 | column -t

相同的技术,但Perl脚本是不同的。您可以通过在第一个脚本中插入grep来迭代,以获取给定文件扩展名的所有对象ID及其大小。

如何删除不需要的数据

到现在为止,您应该清楚自己想要摆脱什么。是时候使用BFG repo cleaner了。请务必仔细阅读网站上的说明。

非常重要: BFG将重写您的整个提交历史记录,这意味着所有您从第一个更改后的提交哈希值将会有所不同。您和有权访问repo的所有其他人必须放弃旧存储库并将其替换为新存储库。这是对象ID如何在git中工作的直接结果,并且你无能为力。

此工具具有允许您删除给定扩展名的所有文件的命令,它还有一个开关,允许您提供要删除的对象ID列表。结合上述报告的结果,这个非常有用。假设您有一个要在名为blobs-to-delete.txt的文件中删除的对象ID列表:

java -jar bfg.jar --no-blob-protection --private --strip-blobs-with-ids blobs-to-delete.txt my-repo.git

由于显而易见的原因,这比使用--strip-blobs-bigger-than等选项更安全。

一对夫妇注意到:

  • --no-blob-protection会将您的最新提交标记为可修改(否则BFG默认不会触及其内容 - 只需确保您有备份)。
  • --private将阻止该工具在新提交的提交消息中包含旧的提交ID(如果您需要跟踪每个提交消息中发生的事情,请将其删除,但IMO只会污染提交消息,该工具无论如何输出一个地图文件。)

然后,你必须使reflog过期并触发一个完整的GC,以便删除的对象真正消失:

git reflog expire --expire=now --all && git gc --prune=now --aggressive

现在,如果您对所做的事情有200%的肯定,请强制推送您的更改,然后强制您团队中的每个人进行新的克隆。享受精简的回购!

答案 1 :(得分:0)

您可以尝试github.com上的存储库中的数据洞察选项卡,看看谁会随着时间推移贡献多少,进一步检查构成这些代码部分的提交。如果你不在github上,你可以通过git gui获得类似的见解。