Git:显示两次提交之间的总文件大小差异?

Posted

技术标签:

【中文标题】Git:显示两次提交之间的总文件大小差异?【英文标题】:Git: show total file size difference between two commits? 【发布时间】:2012-06-06 09:16:08 【问题描述】:

是否可以显示两次提交之间的总文件大小差异?比如:

$ git file-size-diff 7f3219 bad418 # I wish this worked :)
-1234 bytes

我试过了:

$ git diff --patch-with-stat

这显示了 diff 中每个 binary 文件的文件大小差异——但不是文本文件,也不是总文件大小差异。

有什么想法吗?

【问题讨论】:

这是 3 行 bashscript,为您提供特定提交的大小 ***.com/a/23985353/2062041 【参考方案1】:

git cat-file -s 将在 git 中输出对象的大小(以字节为单位)。 git diff-tree 可以告诉你一棵树和另一棵树之间的区别。

将它放在一个名为git-file-size-diff 的脚本中,该脚本位于您的 PATH 的某个位置,您就可以调用git file-size-diff <tree-ish> <tree-ish>。我们可以尝试以下方法:

#!/bin/bash
USAGE='[--cached] [<rev-list-options>...]

Show file size changes between two commits or the index and a commit.'

. "$(git --exec-path)/git-sh-setup"
args=$(git rev-parse --sq "$@")
[ -n "$args" ] || usage
cmd="diff-tree -r"
[[ $args =~ "--cached" ]] && cmd="diff-index"
eval "git $cmd $args" | 
  total=0
  while read A B C D M P
  do
    case $M in
      M) bytes=$(( $(git cat-file -s $D) - $(git cat-file -s $C) )) ;;
      A) bytes=$(git cat-file -s $D) ;;
      D) bytes=-$(git cat-file -s $C) ;;
      *)
        echo >&2 warning: unhandled mode $M in \"$A $B $C $D $M $P\"
        continue
        ;;
    esac
    total=$(( $total + $bytes ))
    printf '%d\t%s\n' $bytes "$P"
  done
  echo total $total

在使用中如下所示:

$ git file-size-diff HEAD~850..HEAD~845
-234   Documentation/RelNotes/1.7.7.txt
112    Documentation/git.txt
-4     GIT-VERSION-GEN
43     builtin/grep.c
42     diff-lib.c
594    git-rebase--interactive.sh
381    t/t3404-rebase-interactive.sh
114    t/test-lib.sh
743    tree-walk.c
28     tree-walk.h
67     unpack-trees.c
28     unpack-trees.h
total 1914

通过使用git-rev-parse,它应该接受所有指定提交范围的常用方法。

编辑:更新以记录累计总数。请注意,bash 在子 shell 中运行 while read,因此需要额外的花括号以避免在子 shell 退出时丢失总数。

编辑:通过使用--cached 参数调用git diff-index 而不是git diff-tree,添加了对将索引与另一个树进行比较的支持。例如:

$ git file-size-diff --cached master
-570    Makefile
-134    git-gui.sh
-1  lib/browser.tcl
931 lib/commit.tcl
18  lib/index.tcl
total 244

【讨论】:

+1 谢谢!如果它能在底部打印出总尺寸差异,这将是绝对完美的。我想看看在两个 refs 之间添加/删除了多少字节(不仅仅是每个文件,而是总共)。 另一个问题:你为什么要在这里采购git-sh-setup?你似乎没有使用any of the functions it defines。只是想知道! 如果您在非 git 存储库的目录中运行此命令,它会执行基本检查,例如生成合理消息。它还可以帮助抽象出一些平台差异。不过主要是习惯。编写 git 脚本时 - 首先引入 git-sh-setup 文件。 感谢脚本!我把它归档在一个要点(gist.github.com/cschell/9386715)中,希望你不介意。不耐烦的人现在可以做类似curl -s https://gist.githubusercontent.com/cschell/9386715/raw/43996adb0f785a5afc17358be7a43ff7ee973215/git-file-size-diff | bash -s &lt;tree-ish&gt; &lt;tree-ish&gt; @mr5 HEAD~850 是 HEAD 之前的 850 次提交。它只是提交的另一种表示法,是的,您可以使用特定的提交 id 或标签或任何可以解析为提交的东西。该脚本使用git rev-parse,因此请参阅 git-rev-parse 文档中的手册部分“指定修订版”以获取完整详细信息。 (git-scm.com/docs/git-rev-parse)【参考方案2】:

你可以通过管道输出

git show some-ref:some-path-to-file | wc -c
git show some-other-ref:some-path-to-file | wc -c

并比较这两个数字。

【讨论】:

+1 这对于快速检查版本之间文件的大小差异非常有用。但是如何使用它来获得两次提交之间的总文件差异?我想看看在两个 refs 之间在项目范围内添加/删除了多少字节。 如果你使用cat-file -s而不是show,你可以跳过| wc -c 使用 @neu242 建议的改进,我编写了这个 bash 函数:gdbytes () echo "$(git cat-file -s $1:$3) -&gt; $(git cat-file -s $2:$3)" 这可以很容易地看到自上次提交以来文件大小如何变化,例如 gdbytes @~ @ index.html 如果some-ref:部分被跳过,是否获取工作目录下的文件大小?【参考方案3】:

我制作了一个 bash 脚本,通过实际文件/内容大小来比较分支/提交等。 它可以在https://github.com/matthiaskrgr/gitdiffbinstat 找到,还可以检测文件重命名。

【讨论】:

有这个用法的例子吗?【参考方案4】:

扩展matthiaskrgr's answer,https://github.com/matthiaskrgr/gitdiffbinstat 可以像其他脚本一样使用:

gitdiffbinstat.sh HEAD..HEAD~4

Imo 它确实运行良好,比此处发布的任何其他内容都快得多。示例输出:

$ gitdiffbinstat.sh HEAD~6..HEAD~7
 HEAD~6..HEAD~7
 704a8b56161d8c69bfaf0c3e6be27a68f27453a6..40a8563d082143d81e622c675de1ea46db706f22
 Recursively getting stat for path "./c/data/gitrepo" from repo root......
 105 files changed in total
  3 text files changed, 16 insertions(+), 16 deletions(-) => [±0 lines]
  102 binary files changed 40374331 b (38 Mb) -> 39000258 b (37 Mb) => [-1374073 b (-1 Mb)]
   0 binary files added, 3 binary files removed, 99 binary files modified => [-3 files]
    0 b  added in new files, 777588 b (759 kb) removed => [-777588 b (-759 kb)]
    file modifications: 39596743 b (37 Mb) -> 39000258 b (37 Mb) => [-596485 b (-582 kb)]
    / ==>  [-1374073 b (-1 Mb)]

./c/data 的输出目录很时髦...因为 /c 实际上是文件系统根目录。

【讨论】:

您无需对 Matthias 的帖子发表评论 - 您可以建议对其进行修改,但他并未提供这些详细信息。按照目前的标准,他的答案将被视为“仅链接答案”,将被删除,因此这些细节很重要。 谁能接受我的答案并将其包含在 matthias 中? 如果需要,您可以自己进行建议的编辑。 (根据我的经验,它往往会被审稿人拒绝,但编辑摘要中的明确解释可能会有所帮助。)但也许我对你的评论不清楚......你的答案是一个独立的答案,很好地更新了马蒂亚斯的旧答案。您不需要包含解释您要评论的文本,仅此而已。我以适当的方式编辑了答案,以给予马蒂亚斯适当的荣誉。你不需要做更多。【参考方案5】:

对脚本的注释:git-file-size-diff,由 patthoyts 建议。该脚本非常有用,但是我发现了两个问题:

    当有人更改文件的权限时,git 在 case 语句中返回另一种类型:

    T) echo >&2 "Skipping change of type"
    continue ;;
    

    如果 sha-1 值不再存在(出于某种原因),则脚本会崩溃。您需要在获取文件大小之前验证 sha:

    $(git cat-file -e $D) if [ "$?" = 1 ]; then continue; fi

完整的 case 语句将如下所示:

case $M in
      M) $(git cat-file -e $D)
         if [ "$?" = 1 ]; then continue; fi
         $(git cat-file -e $C)
         if [ "$?" = 1 ]; then continue; fi
         bytes=$(( $(git cat-file -s $D) - $(git cat-file -s $C) )) ;;
      A) $(git cat-file -e $D)
         if [ "$?" = 1 ]; then continue; fi
         bytes=$(git cat-file -s $D) ;;
      D) $(git cat-file -e $C)
         if [ "$?" = 1 ]; then continue; fi
         bytes=-$(git cat-file -s $C) ;;
      T) echo >&2 "Skipping change of type"
         continue ;;
      *)
        echo >&2 warning: unhandled mode $M in \"$A $B $C $D $M $P\"
        continue
        ;;
    esac

【讨论】:

以上是关于Git:显示两次提交之间的总文件大小差异?的主要内容,如果未能解决你的问题,请参考以下文章

git:显示两次提交之间所有更改的文件

git导出有差异的文件列表

我可以通过 GH API 在两次提交之间获取一个文件的差异数据吗?

GIt:使用BFG从存储库中删除了几个文件,并且存在巨大的提交差异

git log 查看指定文件的提交记录

git更新代码