Ответ 1
diff <(git show COMMIT1SHA) <(git show COMMIT2SHA)
Есть ли способ проверить, являются ли два diff или patches эквивалентными?
Предположим, что у вас есть следующая история событий git, где функции F и G являются чисто перемасштабируемыми для E:
G
/
A--B--C--D--E
\
F
Из-за ограничений в нашем текущем процессе развертывания мы имеем следующий, несколько связанный граф (он не контролируется версией)
G'
/
------------E'
\
F'
F 'и G' в конечном итоге будут применены к голове E ', в некоторых из которых будет определен порядок, так что это закончится как
------------E'--G'--F'
Есть ли способ проверить, что diff от E 'до G' совпадает с патчем, созданным фиксацией git G из B?
Я полностью понимаю, что в идеальном мире контроль над версиями позволит решить эту проблему, и мы добираемся туда, но не там, где мы сейчас находимся.
Вы могли бы по-разному играть в оба патча на отдельных кассах и сравнивать выходы, но это кажется довольно неуклюжим. И сравнение самих различий, я предполагаю, не будет работать, потому что номера строк могут измениться. Даже если G 'и F' были переустановлены на E ', патч для F' в конечном итоге будет применен к G ', что делает diff-контекст патча другим.
diff <(git show COMMIT1SHA) <(git show COMMIT2SHA)
Я просто хотел бы 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
В интересах читателя, здесь обновляется ответ @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
(aka. /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 first-argument", а затем выводит второй аргумент. Это трюк, чтобы уменьшить накладные расходы, если что-то не получится. (Правильное управление ошибками было бы слишком.)
diff "${O[@]}" <(g 0 1) <(g 1 0)
запускает diff
с заданными параметрами в отношении первого аргумента и второго аргумента (при этом FAIL-ошибка возвращается к другому аргументу, чтобы уменьшить diff
).
--
позволяет передать diff
-options (-something
) в этот псевдоним /script.
Ошибка:
Число аргументов не проверяется. Все, что находится за вторым аргументом, игнорируется, и если вы даете ему слишком мало, вы просто видите FAIL
или ничего вообще.
Ошибки действуют немного странно и загромождают выход. Если вам это не нравится, запустите его с помощью 2>/dev/null
(или соответствующим образом измените script).
Он не возвращает ошибку, если что-то ломается.
По всей видимости, вы хотите передать это в пейджер по умолчанию.
Обратите внимание, что легко определить еще несколько псевдонимов, например:
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 "[email protected]" 2>&1 | less -XFR; }; pager'
git config --global alias.ddiff '!git pager udiff'
Надеюсь, это не нужно объяснять дальше.
Для получения дополнительных псевдонимов, возможно, посмотрите мой репозиторий GitHub