Как "git показать" комманду слияния с комбинированным выходом diff, даже если каждый измененный файл согласуется с одним из родителей?

После выполнения "простого" слияния (без конфликтов) git show обычно показывает только что-то вроде

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <[email protected]>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

Это связано с тем, что для слияния git show используется комбинированный формат diff, который пропускает файлы, которые согласуются с любой из родительских версий.

Есть ли способ заставить git показать все различия в комбинированном режиме diff?

Выполнение git show -m покажет различия (используя парные различия между новой и всеми родительскими версиями соответственно), но я предпочел бы иметь это с отличиями, отмеченными +/- в соответствующих столбцах, например, в комбинированном режиме.

Ответ 1

Нет, это невозможно сделать с помощью git show. Но иногда это было бы неплохо, и, вероятно, это было бы относительно легко реализовать в исходном коде git (в конце концов, вы просто должны сказать ему, чтобы он не обрезал то, что он считает посторонним выводом), так что патч для этого вероятно, будут приняты сопровождающими git.

Будьте осторожны с тем, что вы желаете; объединение ветки с однострочным изменением, которое было разветвлено три месяца назад, будет по-прежнему иметь огромную разницу по сравнению с основной линией, и поэтому такая полная разница будет почти полностью бесполезной. Вот почему Git не показывает это.

Ответ 2

Посмотрите сообщение фиксации:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <[email protected]>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

обратите внимание на строку:

Merge: fc17405 ee2de56

возьмите эти два идентификатора фиксации и отмените их. поэтому, чтобы получить diff, который вы хотите, вы бы сделали:

git diff ee2de56..fc17405

чтобы показать только имена измененных файлов:

git diff --name-only ee2de56..fc17405

и для их извлечения вы можете добавить это в свой gitconfig:

exportfiles = !sh -c 'git diff $0 --name-only | "while read files; do mkdir -p \"$1/$(dirname $files)\"; cp -vf $files $1/$(dirname $files); done"'

затем используйте его, выполнив:

git exportfiles ee2de56..fc17405 /c/temp/myproject

Ответ 3

Лучшее решение (упомянутое @KrisNuttycombe):

git diff fc17405...ee2de56

для коммита слияния:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <[email protected]>
Date:   Tue Feb 22 00:27:17 2011 +0100

показать все изменения на ee2de56, которые достижимы из fc17405 на fc17405. Обратите внимание на порядок принятия хэшей - он такой же, как показано в информации о слиянии: Merge: fc17405 ee2de56

Также обратите внимание на 3 точки ... вместо двух !

Для получения списка измененных файлов вы можете использовать:

git diff fc17405...ee2de56 --name-only

Ответ 4

Вы можете создать ветку с HEAD, установленным в один коммит перед слиянием. Затем вы можете сделать:

git merge --squash testing

Это объединит, но не совершит. Затем:

git diff

Ответ 5

Мне кажется, вам просто нужно git show -c $ref '. Попытка этого в репозитории git на a8e4a59 показывает комбинированные символы diff (плюс/минус в одном из 2 столбцов). Как упоминается в руководстве git -show, он в значительной степени делегирует 'git diff-tree', поэтому эти параметры выглядят полезными.

Ответ 6

Похоже, здесь ответил: http://thread.gmane.org/gmane.comp.version-control.git/191553/focus=191557

Таким же образом, работая

$git diff --cc $M $M ^ 1 $M ^ 2 $(git merge-base $M ^ 1 $M ^ 2)

должен показать комбинированный патч, который объясняет состояние в $M относительно состояния, записанные в его родителях и базу слияния.

Ответ 7

в вашем случае вам просто нужно

git diff HEAD^ HEAD^2

или просто хеш для фиксации:

git diff 0e1329e55^ 0e1329e55^2

Ответ 8

Я построил универсальный подход к выполнению различных операций с фиксацией слияния.

Шаг первый: добавьте псевдоним к git, отредактировав ~/.gitconfig:

[alias]
  range = "!. ~/.githelpers && run_on_merge_range"

Шаг второй. В ~/.githelpers определите функцию bash:

run_on_merge_range() {
  cmd=$1; shift
  commit=$1; shift
  range=$(git show $commit | grep Merge: | awk '{print $2 "..." $3}')
  echo "git $cmd $range [email protected]"
  if [ -z $range ]; then
    echo "No merge detected"
    exit 1
  fi
  git $cmd $range [email protected]
}

Шаг третий: прибыль!

git range log <merge SHA> --oneline
git range diff <merge SHA> --reverse -p
git range diff <merge SHA> --name-only

Вероятно, здесь есть много возможностей для улучшения, я просто взбивал это вместе, чтобы преодолеть раздражающую ситуацию. Не стесняйтесь издеваться над синтаксисом и/или логикой bash.

Ответ 9

Вы можете использовать команду diff-tree с флагом -c. Эта команда показывает, какие файлы были изменены в коммите слияния.

git diff-tree -c {merged_commit_sha}

Я получил описание флага -c от Git-Scm:

Этот флаг изменяет способ отображения коммита слияния (что означает, что он полезен только тогда, когда команда дана, или --stdin). Он показывает различия от каждого из родителей к результату слияния одновременно, вместо того, чтобы показывать попарно разницу между родителем и результатом по одному (что и делает опция -m). Кроме того, в нем перечислены только файлы, которые были изменены от всех родителей.

Ответ 10

Если ваш коммит слияния является коммитом 0e1329e5, как указано выше, вы можете получить diff, который содержался в этом слиянии:

git diff 0e1329e5^..0e1329e5

Надеюсь, это поможет!

Ответ 11

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

git diff HEAD~1..HEAD

Если вы не в коммите слияния, просто замените HEAD коммитом слияния. Этот метод кажется самым простым и интуитивно понятным.