是否有一个git命令可以为每个提交输出以下内容:
- id
- 主题
- 它创建的blob及其路径和大小(类似于
git ls-tree -l -r <commit>
,但仅适用于创建的blob)
获取提交记录(全部)并每行输出一个提交记录:
git rev-list --all --pretty=oneline
然后按照限制为2的空格拆分提交,并获取每个提交ID和消息。
要获取由提交创建的blob(递归到子目录,显示合并提交,检测重命名和复制,在第一行不显示提交ID):
git diff-tree -r -c -M -C --no-commit-id <commit-sha>
对每行进行一些解析并排除其中一些行 - 我们得到新Blob的列表和它们在提交中的路径。
最后是获取Blob的大小:
git cat-file --batch-check < <list-of-blob-shas>
还有一次稍微解析一下
git rev-list
并不总是足够的,因为它只列出了由给定提交的父链接可到达的提交。(git help rev-list
)因此,它不会列出其他分支上的提交,也不会列出任何分支都无法到达的提交(可能是由于某些rebase
和/或游离状态操作而创建的)。类似地,git log
只是从当前签出的提交中跟随父链接。同样,你看不到其他分支引用的提交或处于游离状态的提交。你可以像这样使用命令真正获取所有提交:for i in `(find .git/objects -type f |
sed 's@^.*objects/\(..\)/\(.\+\)$@\1\2@' ;
git verify-pack -v .git/objects/pack/*.idx |
grep commit |
cut -f1 -d' '; ) | sort -u`
do
git log -1 --pretty=format:'%H %P %ai %s%n' $i
done
为了简单起见,循环体为每个提交打印一行,包含其哈希值、父哈希值、日期和主题。请注意,要遍历所有提交,您需要考虑已打包和未打包的对象。git log --all
怎么样?文档似乎暗示这将包括每个(可达)提交... - peterflynngit log --name-status
基于tig的答案,有一个解决方案:
#!/usr/bin/perl
foreach my $rev (`git rev-list --all --pretty=oneline`) {
my $tot = 0;
($sha = $rev) =~ s/\s.*$//;
foreach my $blob (`git diff-tree -r -c -M -C --no-commit-id $sha`) {
$blob = (split /\s/, $blob)[3];
next if $blob == "0000000000000000000000000000000000000000"; # Deleted
my $size = `echo $blob | git cat-file --batch-check`;
$size = (split /\s/, $size)[2];
$tot += int($size);
}
print "$tot $rev" if $tot > 1000000; # Show only if > 1MiB
}
当搜索时,另一个有用的命令是
git fsck --lost-found
该命令将显示悬空提交。我需要使用它来找到一个被我错误地使用reset --hard擦除的提交
但不要只听我的话:
https://www.kernel.org/pub/software/scm/git/docs/git-fsck.html
你也可以使用以下命令获取包括悬空提交在内的所有提交记录:
git log --walk-reflogs | grep -E -o '[0-9a-f]{40}'
将此行命令添加到 gitk 的新视图设置中(在最后一个输入字段中,生成额外提交的命令),您将获得一个显示项目“遗忘历史”的树形结构。
git log --walk-reflogs
给出的列表比仅使用 git log
要 _短_。根据手册所述,引用日志不能保证是所有提交或所有分支的详尽列表... - peterflynn
--stdin
选项来加快速度。例如,git rev-list --all | git diff-tree -r --root --diff-filter=AMC --pretty=oneline --stdin
。 - Jed