Есть ли способ сравнить два различия или патчи? - PullRequest
25 голосов
/ 20 декабря 2011

Есть ли способ проверить, эквивалентны ли два различия или патча?

Допустим, у вас есть следующая история коммитов git, где функции F и G полностью перебазируются в E:

     G
    /
A--B--C--D--E
 \
  F

Из-за ограничений в нашем текущем процессе развертывания у нас есть следующий, несколько связанный график (он не контролируется версией) * В конечном итоге будут применены

              G'
             /
------------E'
             \
              F'

F 'и G'к голове E ', в каком-то определенном порядке, так что это будет выглядеть как

------------E'--G'--F'

Есть ли способ проверить, что разность от E' до G 'такая же, как и у произведенного патчаблагодаря git commit G из B?

Я полностью осознаю, что в идеальном мире контроль ревизий решит эту проблему, и мы доберемся до этого, но сейчас мы не там.

По сути, вы можете сыграть оба патча на отдельных проверках и сравнить результаты, но это кажется неуклюжим.И сравнение самих различий, я полагаю, не сработает, потому что номера строк могут измениться.Даже если G 'и F' были переназначены на E ', патч для F' в конечном итоге будет применен к G ', что сделает контекст diff патча другим.

Ответы [ 4 ]

33 голосов
/ 23 января 2015
diff <(git show COMMIT1SHA) <(git show COMMIT2SHA)
8 голосов
/ 26 сентября 2018

Начиная с git 2.19 для этого есть дополнительный инструмент: git range-diff

Так что вы, вероятно, хотите:

git range-diff E..G E..G'

Это должно работать даже для нескольких патчей в каждом диапазоне.

2 голосов
/ 07 июля 2017

Для удобства читателя, вот обновление ответа @ mrbrdo с небольшим изменением:

  • Добавляет git sdiff псевдоним для легкого доступа к этому. sdiff означает show diff.
  • Игнорировать аннотированные заголовки тегов, используя суффикс ^{}.
  • Разрешить использование diff параметров, таких как -u и т. Д.

Запустите это один раз для каждой учетной записи, в которой вы используете git:

git config --global alias.sdiff '!'"bash -c 'O=(); A=(); while x=\"\$1\"; shift; do case \$x in -*) O+=(\"\$x\");; *) A+=(\"\$x^{}\");; esac; done; g(){ git show \"\${A[\$1]}\" && return; echo FAIL \${A[\$1]}; git show \"\${A[\$2]}\"; }; diff \"\${O[@]}\" <(g 0 1) <(g 1 0)' --"

После этого вы можете использовать это:

git sdiff F G

Обратите внимание, что для этого требуется bash версия 3 или выше.

Разъяснения:

  • git config --global alias.sdiff добавляет псевдоним с именем git sdiff в глобальный ~/.gitconfig.

  • ! запускает псевдоним как команда оболочки

  • bash -c нам нужно bash (или ksh), так как <(..) не работает в dash (он же. /bin/sh).

  • O=(); A=(); while x="$1"; shift; do case $x in -*) O+=("$x");; *) A+=("$x^{}");; esac; done; разделяет параметры (-something) и аргументы (все остальное). Опции находятся в массиве O, а аргументы в массиве A. Обратите внимание, что ко всем аргументам также присоединяется ^{}, что пропускает аннотации (так что вы можете использовать аннотированные теги).

  • g(){ git show "${A[$1]}" && return; echo FAIL ${A[$1]}; git show "${A[$2]}"; }; создает вспомогательную функцию, которая выполняет git show для первого аргумента. Если это не удается, выводится «FAIL первый аргумент», а затем выводится второй аргумент. Это хитрость для уменьшения накладных расходов в случае сбоя. (Правильное управление ошибками было бы слишком много.)

  • diff "${O[@]}" <(g 0 1) <(g 1 0) запускает diff с заданными параметрами для первого аргумента и второго аргумента (с указанным откатом ошибки FAIL к другому аргументу для уменьшения diff).

  • -- позволяет передавать diff -опции (-something) этому псевдониму / сценарию.

Ошибка:

  • Количество аргументов не проверяется. Все, что стоит за вторым аргументом, игнорируется, и если вы дадите ему слишком мало, вы просто увидите FAIL или вообще ничего.

  • Ошибки ведут себя немного странно и загромождают вывод. Если вам это не нравится, запустите его с 2>/dev/null (или измените скрипт соответствующим образом).

  • Не выдает ошибку, если что-то сломалось.

  • Возможно, по умолчанию вы хотите передать это в пейджер.

Обратите внимание, что легко определить еще несколько псевдонимов, таких как:

git config --global alias.udiff '!git sdiff -u'
git config --global alias.bdiff '!git sdiff -b'

git config --global alias.pager '!pager() { cd "$GIT_PREFIX" && git -c color.status=always -c color.ui=always "$@" 2>&1 | less -XFR; }; pager'
git config --global alias.ddiff '!git pager udiff'

Надеюсь, это не нужно объяснять дальше.

Для получения дополнительных псевдонимов, возможно, взгляните на мой репозиторий GitHub

2 голосов
/ 20 декабря 2011

Я бы просто позволил git попробовать и посмотреть:

git checkout E -b FG
git cherry-pick F' G'
git checkout E -b GF
git cherry-pick G' F'
git diff FG GF
git branch -D FG GF
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...