Git: показать разницу в общем размере файла между двумя коммитами?

Можно ли показать общую разницу в размере файла между двумя коммитами? Что-то типа:

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

Я пробовал:

$ git diff --patch-with-stat

И это показывает разницу в размере файла для каждого двоичного файла в разнице, но не для текстовых файлов и не разницу в общем размере файла.

Любые идеи?


person Mathias Bynens    schedule 01.06.2012    source источник
comment
Вот трехстрочный bashscript, который дает вам размер определенной фиксации stackoverflow.com/a/23985353/2062041   -  person Stas Dashkovsky    schedule 02.06.2014


Ответы (5)


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 выполняет чтение while в подоболочке, отсюда и дополнительные фигурные скобки, чтобы не потерять итоговую сумму при выходе из подоболочки.

РЕДАКТИРОВАТЬ: добавлена ​​поддержка сравнения индекса с другим деревом с использованием аргумента --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
person patthoyts    schedule 01.06.2012
comment
+1 Спасибо! Было бы абсолютно идеально, если бы он распечатал общую разницу в размерах внизу. Я хочу увидеть, сколько байтов было добавлено / удалено в рамках проекта между двумя ссылками (не только для каждого файла, но и в целом). - person Mathias Bynens; 01.06.2012
comment
Другой вопрос: зачем вы здесь git-sh-setup? Похоже, вы не используете какие-либо функции, которые он определяет . Просто интересуюсь! - person Mathias Bynens; 01.06.2012
comment
Он выполняет базовые проверки, такие как создание разумного сообщения, если вы запускаете эту команду в каталоге, который не является репозиторием git. Это также может помочь абстрагироваться от некоторых различий между платформами. Но в основном по привычке. При написании сценария git - сначала загрузите файл git-sh-setup. - person patthoyts; 01.06.2012
comment
Спасибо за сценарий! Я заархивировал это в виде (gist.github.com/cschell/9386715), надеюсь ты не возражаешь. Нетерпеливые теперь могут делать что-то вроде curl -s https://gist.githubusercontent.com/cschell/9386715/raw/43996adb0f785a5afc17358be7a43ff7ee973215/git-file-size-diff | bash -s <tree-ish> <tree-ish> - person csch; 06.03.2014
comment
Спасибо за отличный сценарий! Я искал способ отслеживать увеличение размера после каждого коммита, и это мне очень помогает. Я сделал небольшую суть, чтобы показать только общее увеличение между всеми (некоторыми) коммитами в gist. github.com/iamaziz/1019e5a9261132ac2a9a еще раз спасибо! - person Aziz Alto; 23.04.2015
comment
Вариант использования, который я ищу, - это предварительный просмотр больших коммитов, прежде чем я их сделаю. Есть ли способ найти изменения размера текущих поэтапных изменений? Я прочитал древовидную документацию и не смог найти способ сослаться на текущие поэтапные изменения. - person escapecharacter; 14.10.2016
comment
Добавлена ​​поддержка сравнения с индексом с использованием git-diff-index. - person patthoyts; 14.10.2016
comment
вы можете запустить echo $PATH, чтобы увидеть свои каталоги пути, чтобы увидеть, где вы можете поместить этот файл сценария. Я вставил свой /usr/local/git/bin, и он отлично сработал. Вы также можете добавить путь к вашему $PATH, если хотите поместить сценарий в другое место. - person Josh; 10.01.2017
comment
Как мне это использовать? Что такое HEAD~850? Могу я просто использовать вместо этого идентификатор фиксации? - person mr5; 24.08.2017
comment
@ mr5 HEAD ~ 850 - это 850 коммитов перед HEAD. Это просто еще одна нотация для фиксации, и да, вы можете использовать конкретный идентификатор фиксации или тег или что-то еще, что может быть преобразовано в фиксацию. Сценарий использует git rev-parse, поэтому подробные сведения см. В разделе руководства «Указание редакций» документации git-rev-parse. (git-scm.com/docs/git-rev-parse) - person patthoyts; 24.08.2017
comment
Как я смогу узнать, какой размер были у файлов раньше? В настоящее время я готовлю запрос на перенос, который оптимизирует структуру вывода файла, и хотел бы вычислить процент уменьшения размера. - person Philzen; 07.04.2020

Вы можете вывести выход из

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

и сравните 2 числа.

person Adam Dymitruk    schedule 01.06.2012
comment
+1 Это отлично подходит для быстрой проверки разницы в размере файла между версиями. Но как это можно использовать для получения общей разницы в файлах между двумя коммитами? Я хочу увидеть, сколько байтов было добавлено / удалено в рамках проекта между двумя ссылками. - person Mathias Bynens; 01.06.2012
comment
Вы можете пропустить | wc -c, если используете cat-file -s вместо show - person neu242; 24.08.2017
comment
Используя усовершенствование, предложенное @ neu242, я написал эту функцию bash: gdbytes () { echo "$(git cat-file -s $1:$3) -> $(git cat-file -s $2:$3)" } Она позволяет легко увидеть, как изменился размер файла с момента последней фиксации, например, gdbytes @~ @ index.html - person webninja; 29.12.2017
comment
если часть some-ref: пропущена, получите ли вы размер файла в рабочем каталоге? - person 40detectives; 06.07.2018

Я создал сценарий bash для сравнения ветвей / коммитов и т. Д. По фактическому размеру файла / содержимого. Его можно найти по адресу https://github.com/matthiaskrgr/gitdiffbinstat, а также обнаруживает переименования файлов.

person matthiaskrgr    schedule 29.12.2012
comment
Есть пример использования этого? - person AlecRust; 14.01.2014

Расширяя ответ matthiaskrgr, 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 на самом деле является корнем файловой системы.

person guest    schedule 12.04.2016
comment
Вам не нужно было комментировать сообщение Матиаса - вместо этого вы могли бы предложить его отредактировать, указав детали, которые он не предоставил. По нынешним стандартам, его ответ будет считаться ответом, содержащим только ссылку, и будет удален, поэтому такие детали важны. - person Mogsdad; 15.04.2016
comment
кто может взять мой ответ и включить его в Матиас? - person guest; 25.04.2016
comment
При желании вы можете внести предлагаемые изменения самостоятельно. (По моему опыту, рецензенты, как правило, отвергают его, но может помочь четкое объяснение в сводке редактирования.) Но, возможно, я не был ясен в своем комментарии к вам ... ваш ответ является отдельным ответом , хорошее обновление старого ответа Матиаса. Вам не нужно было включать текст, объясняющий, что вы хотели прокомментировать, вот и все. Я отредактировал ответ таким образом, чтобы отдать должное Матиасу. Вам не нужно делать больше. - person Mogsdad; 25.04.2016

Комментарий к скрипту: git-file-size-diff, предложено patthoyts. Скрипт очень полезен, однако я обнаружил две проблемы:

  1. Когда кто-то меняет права доступа к файлу, git возвращает другой тип в операторе case:

    T) echo >&2 "Skipping change of type"
    continue ;;
    
  2. Если значение 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
person Richard Nilsson    schedule 22.06.2017