如何查看git存储库中单个文件的文件大小历史记录?

41

有没有办法在Git存储库中查看文件大小随时间的变化? 我想看看我的main.js文件(它是几个文件的组合,并经过了缩小处理)随着时间的推移如何增长和缩小。

9个回答

20

您可以使用 git ls-tree -r -l <revision> <path> 来获取给定版本的 blob 大小,例如:

$ git ls-tree -r -l v1.6.0 gitweb/README
100644 blob 825162a0b6dce8c354de67a30abfbad94d29fdde   16067    gitweb/README

从文档中可以得知:

 -r                    recurse into subtrees
 -l, --long            include object size

在这个例子中,Blob的大小为“16067”。这种解决方案的缺点是git ls-tree一次只能处理一个版本。相反,您可以使用git cat-file --batch-check < <list-of-objects>,将其提供给Blob标识符。如果文件的位置在历史中没有更改(文件未移动),则可以使用git rev-list <starting-point> -- <path>获取触及给定路径的修订列表,使用<revision>:<path>扩展SHA-1语法(请参见git-rev-parse手册)将它们转换为Blob名称,并将其提供给git cat-file。例如:
$ git rev-list -5 v1.6.0 -- gitweb/README | 
  sed -e 's/$/:gitweb\/README/g' |
  git cat-file --batch-check
使用Git命令列出版本v1.6.0中最新的五个提交,其中包括文件"gitweb/README"。将输出结果进行处理,将每一行结尾的"$"替换为":gitweb/README"。最后通过git cat-file命令批量检查输出结果中的对象。

ls-tree 输出通过管道传递给 awk '{print $4 " " $5}',以仅获取文件大小和名称。 - l0b0

15
创建一个名为.gitattributes的文件,并添加以下行:
main.js -diff

这将关闭main.js的基于行的差异。现在运行以下命令:

git log --stat main.js

日志将包括以下行:

main.js | Bin 4316 -> 4360 bytes

完成后,你应该删除.gitattributes文件。我不知道其他的-diff属性可能会导致Git行为发生什么变化。

经过测试,使用Git版本1.7.12.4和1.7.9.5。

来源:ewall的回答和https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html#_marking_files_as_binary


11
这是一个Bash函数,它会以以下格式报告时间内的大小。
 LoC  Date                       Commit ID   Subject
 942  2019-08-31 18:09:34 +0200  35fc67c122  Declare some XML namespaces in replacement of OGCPrefixMapper, which has been removed from Apache SIS. https://issues.apache.org/jira/browse/SIS-126
 943  2019-08-09 16:52:29 +0200  e8438ab869  fix(GML): fix relative path resolving inside a jar
 934  2019-08-05 15:37:46 +0200  1e0c0b03c4  fix(GML): fix all test cases
 932  2019-07-30 15:54:53 +0200  fddea5db24  feat(GML): work on fallback for non-xsd Feature store
 932  2019-07-23 16:40:23 +0200  8d9a6a7dd0  feat(GML): improve support for custom XML mappings
 932  2019-06-26 15:18:43 +0200  43ea6e0bd7  feat(GML): add concurrency support for read/write operations
 932  2019-06-21 09:27:41 +0200  07a9993b4b  feat(GML): support group reference min/max occurs attributes
 932  2019-06-21 09:27:41 +0200  352a9104ae  feat(GML): fix resolving local files xsd paths
 919  2018-06-08 15:41:26 +0200  01ac7538e7  Merge branch 'master' into sis-migration
 919  2018-05-16 16:40:04 +0200  16fe7590c5  fix(JAXP): various fix for  WFS 2.0.0
 912  2018-04-11 10:09:22 +0200  bf3a38bdc4  chore(*): update JTS version 1.15.0
 912  2017-11-09 20:15:23 +0100  bc14dc4be1  fix(Client): fix minor problems on WFS querying
 901  2017-10-20 11:41:43 +0200  f686d7ff15  feat(Storage): add support for GML 2.1.2
 882  2017-05-16 23:07:31 +0200  f20c34c1e2  refactor(Feature): renamed the Geotk flavor of org.apache.sis.feature package as org.geotoolkit.feature.

这是函数:

git-log-size() {
    git rev-list HEAD -- "$1" | while read cid; do
        git cat-file blob "$cid:$1" | wc -l | tr -d '\n'
        echo -n $'\t'
        git log -1 "--pretty=%ci%x09%h%x09%s" $cid
    done | column -t -s$'\t'
}

虽然不是特别高效,但能胜任工作。它使用了一些很常见的实用程序(如wc、tr、column)。

代码行数(LoC)被报告为大小,这是软件开发中常见的度量标准,如果你喜欢其他度量标准,只需更改“wc”的“-l”选项即可。

以下是调用方法:

git-log-size <path>

正是我想要的,因为我也想要提交的时间戳。谢谢 :) - nealmcb
1
谢谢,这个像魔法一样好用!使用说明:请在代码库的根目录下调用 git-log-size - benjifisher

9
你可以创建一个脚本,使用 git show --pretty=raw <commit> 的输出获取树,并使用 git ls-tree -r -l 获取你要查找的 blob,包括文件大小。
如果你安装了 Ruby 和 grit 宝石,这里是我写的一个小脚本:
require 'grit'

if ARGV.size < 1
  puts 'usage: file-size FILE'
  puts 'run from within the git repo root'
  exit
end

filename = ARGV[0].to_s

repo = Grit::Repo.new('.')
commits = repo.log('master', filename)
commits.each do |commit|
  blob = commit.tree/filename
  puts "#{commit} #{blob.size} bytes"
end

示例用法(脚本文件名为file-size.rb),将显示somedir / somefile的历史记录:

myproject$ ruby file-size.rb somedir/somefile

花了我一分钟才弄清楚如何在安装grit gem后使用它(路径问题),但现在它运行得非常好。谢谢。 - Echo says Reinstate Monica
小建议:将commits = repo.log('master', filename) 改为 commits = repo.log('HEAD', filename),以便根据你当前所在的位置(HEAD)显示文件系统,而不是假设为 master。当然,允许参数会很酷,但现在需要考虑更多的工作。;-) - Slipp D. Thompson
此外,在文件开头插入#!/usr/bin/env ruby,使其可执行,将其命名为git-file-size而不是file-size.rb,并将其放在bin-PATH-y目录中_(例如,我使用~/bin/存储很多类似的自定义程序)_,然后现在只需像使用git一样运行git file-size some-file.png - Slipp D. Thompson
Grit不再维护,并且无法处理新的打包文件格式。 - jthill

2
如果有人需要,这个脚本可以显示给定文件在不同提交中的大小:
git log <file_name> | grep "^commit" | cut -f2 -d" " | while read hash; do
   echo -n "$hash -- "
   git show $hash:<file_path_off_of_git_root_without_leading_slash> | wc -c
done

2

只需要执行以下命令:
git log --stat /path/to/file

结果为: enter image description here


1

虽然像git log <filename>git whatchanged等命令可以显示与该文件相关的历史记录,但我在内置或自定义漂亮格式中都没有看到显示大小的选项(遗憾的是,--log-size选项仅用于日志消息!)。

但是,您可以通过查看每个提交中添加和删除的总行数来大致了解其大小。您可以使用命令git log --stat <filename>以加号和减号的形式进行可视化。或者使用git log --numstat <filename>收集每个提交中添加或删除的行数,并在其他可视化工具中使用这些数字。


1
在Windows上,我正在使用以下命令:
cmd /c "@echo off & for /l %N in (1 1 30) do git ls-tree -r -l HEAD~%N "C:\path\to\file.txt"

它将显示最近30个版本的每个大小。如果有人能将其转换为Linux命令,欢迎...))

0

列出文件按版本的大小的Bash函数:

function git-filehist() {
  for rev in $(git rev-list HEAD -- $1); do
    git ls-tree -r -l $rev $1
  done
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接