Git: показати загальну різницю в розмірі файлу між двома комітами?


79

Чи можна показати загальну різницю в розмірі файлу між двома комітами? Щось на зразок:

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

Я пробував:

$ git diff --patch-with-stat

І це показує різницю в розмірі файлу для кожного двійкового файлу в різниці - але не для текстових файлів і не загальну різницю в розмірі файлу.

Будь-які ідеї?


3
Ось це 3 х ліній bashscript даючи вам розмір напевно зробити stackoverflow.com/a/23985353/2062041
Стас Дашковский

Відповіді:


92

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

EDIT: додана підтримка порівняння індексу з іншим деревом за допомогою використання --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 Дякую! Це було б абсолютно ідеально, якби це роздруковувало загальну різницю розмірів внизу. Я хочу побачити, скільки байтів було додано / видалено за весь проект між двома посиланнями (не лише на файл, а й у цілому).
Матіас Байнс,

Інше питання: чому ви git-sh-setupтут постачаєте ? Здається, ви не використовуєте жодної із визначених функцій . Просто цікаво!
Mathias Bynens

3
Він виконує основні перевірки, такі як створення розумного повідомлення, якщо ви запускаєте цю команду в каталозі, який не є сховищем git. Це також може допомогти абстрагувати деякі відмінності платформи. В основному це звичка. Під час написання скрипта git - спочатку введіть файл git-sh-setup.
patthoyts

1
Дякую за сценарій! Я заархівував його в суть ( 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>
csch

1
@ mr5 HEAD ~ 850 - це 850 комітів перед HEAD. Це просто ще одне позначення для коміту, і так, ви можете використовувати певний ідентифікатор коміту або тег або що-небудь, що може бути вирішено для коміту. Сценарій використовує, git rev-parseтому дивіться розділ керівництва "Вказівки на редагування" в документації git-rev-parse для отримання детальної інформації. ( git-scm.com/docs/git-rev-parse )
patthoyts

21

Ви можете прокласти трубу

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

і порівняйте 2 числа.


9
+1 Це чудово підходить для швидкої перевірки різниці розмірів файлу між версіями. Але як це можна використовувати для отримання загальної різниці у файлах між двома комітами? Я хочу побачити, скільки байт було додано / видалено за весь проект між двома посиланнями.
Mathias Bynens

1
Ви можете пропустити, | wc -cякщо використовуєте cat-file -sзамістьshow
neu242

Використовуючи вдосконалення, запропоноване @ neu242, я написав цю функцію bash: gdbytes () { echo "$(git cat-file -s $1:$3) -> $(git cat-file -s $2:$3)" } що дозволяє легко побачити, як змінився розмір файлу з часу останнього gdbytes @~ @ index.html
коміту,

якщо some-ref:частина пропущена, ви отримуєте розмір файлу в робочому каталозі?
40 детективів


3

Розширюючи відповідь 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 насправді є коренем файлової системи.


Вам не потрібно було коментувати допис Маттіаса - замість цього ви могли б запропонувати його редагування з цими деталями, яких він не надав. За чинними стандартами, його відповідь вважатиметься "відповіддю лише на посилання" та буде видалена, тому такі типи деталей важливі.
Могсдад,

хто може взяти мою відповідь і включити її до матіасів?
гість

Якщо ви хочете, ви можете зробити запропоновану редакцію самостійно. (З мого досвіду, це може бути відхилене рецензентами, але чітке пояснення у Редагуванні резюме може допомогти.) Але, можливо, я не зрозумів у своєму коментарі до вас ... ваша відповідь - це окрема відповідь , гарне оновлення старшої відповіді Матіаса. Вам не потрібно було включати текст, який пояснював, що ви мали намір коментувати. Я відредагував відповідь таким чином, щоб дати належну заслугу Маттіасу. Вам не потрібно робити більше.
Могсдад,

2

Коментар до сценарію: 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 $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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.