git - Git存储库维护和审核工具

标签 git

我想在git存储库中执行一些审计和维护操作,因为有些开发人员有时会对不应该在常规(健康)存储库中的文件进行版本控制:编译的二进制文件、第三方文档文件……
在过去的几个月里,存储库的大小大大增加了,我想知道为什么:添加了哪些文件,哪些文件扩展名,哪些文件大小…尽管这些文件可能在之后被删除,但元数据仍然存在,影响clone、pull和fetch命令,git元数据目录确实很大。
我知道git log命令提供了这样的功能,但我想知道是否还有其他工具(可能是ui工具?)它提供了关于git存储库使用情况的更集成、更易于比较和对比的信息。
因此,总结一下,我可以选择哪些选项来获取有关以下内容的Git信息:
添加到存储库中的特定大小的文件
延期,从某个时间和(如果可能的话)是谁做的。
已删除的文件。有可能把它们抹掉吗?

最佳答案

git的好处是它暴露了所有的内脏,所以你可以看一眼它们。
对你来说,你在照顾大块头。如果您不熟悉git在内部的工作方式,那么它基于一个对象数据库,该数据库将对象映射到它们的sha-1散列。提交是对象,每个提交包含一棵树,这是一个列出目录内容的对象,这些对象可以是其他树(对于子目录)或blob(对于文件数据)。
这意味着,如果两个文件具有相同的内容,它们将共享一个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的输出并插入一些我们感兴趣的数据(如对象大小)。
这里,%(rest)将被替换为输入上对象id之后的部分-指向blob的是文件路径。
sort -nr -k 3将对blob大小进行反向排序
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,不是文件。如果更改文件,则该文件将有两个blob:每个提交的版本有一个blob。另外,请记住,由于git执行gc时发生的增量压缩,磁盘总使用量将小于每个blob大小的总和。如果两个blob非常相似(因为提交通常只更改文件的一小部分),增量压缩将非常有效。
现在可以调整此命令以生成其他报告。下面是一个不那么花哨的版本,它做了同样的事情:
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及其大小。
如何消除不需要的数据
到现在为止,你应该知道你想摆脱什么了。使用docs的时间。请务必仔细阅读网站上的说明。
非常重要:bfg将重写您的整个提交历史,这意味着从第一个更改的提交哈希值开始的所有提交哈希值都将不同。您和其他有权访问repo的人将不得不放弃旧的存储库并用新的存储库替换它。这是git中对象id工作方式的直接结果,对此您无能为力。
这个工具有命令,可以删除给定扩展名的所有文件,还有一个开关,可以提供要删除的对象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%的把握,那么就强制推送你的更改,然后强制团队中的每个人制作一个新的克隆。享受你的瘦身回购!

关于git - Git存储库维护和审核工具,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45534085/

相关文章:

windows - 如何让 Windows 上的 Git 忽略符号链接(symbolic link)

git - atom.io 中是否有用于逐行暂存的函数/插件?

git - 撤消将功能 merge 到开发中的 git flow 功能完成

git - 压缩特定标签之前的完整历史记录

Git 使远程 master 指向另一个分支

Git:区分本地和远程标签

git diff - 只显示远程的新内容

android - Github 对 pull 请求发表评论的 TeamCity 触发器

git - 你什么时候会使用 .git/info/exclude 而不是 .gitignore 来排除文件?

git - 如何撤消 git config --system core.askpass git-gui--askpass