Как можно просмотреть слияние в git?

У меня есть ветвь git (основная строка, например), и я хочу объединиться в другую ветку разработки. Или я?

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

Пока лучшее, что я могу придумать, это merge --no-ff --no-commit, а затем diff HEAD.

Ответ 1

Я обнаружил, что лучшим решением для меня является просто выполнить слияние и прервать его, если возникнут конфликты. Этот конкретный синтаксис кажется мне чистым и простым. Это Стратегия 2 ниже.

Однако, если вы хотите убедиться, что вы не испортили свою текущую ветку или просто не готовы к слиянию, независимо от наличия конфликтов, просто создайте из нее новую дочернюю ветвь и добавьте следующее:

Стратегия 1: Безопасный путь - объединить временную ветку:

git checkout mybranch
git checkout -b mynew-temporary-branch
git merge some-other-branch

Таким образом, вы можете просто выбросить временную ветвь, если вы просто хотите увидеть, что это за конфликты. Вам не нужно беспокоиться об "прекращении" слияния, и вы можете вернуться к своей работе - просто зарегестрируйте mybranch снова, и у вас не будет никакого кода слияния или конфликтов слияния в вашей ветке.

Это в основном всухую.

Стратегия 2: когда вы определенно хотите объединиться, но только если нет конфликтов

git checkout mybranch
git merge some-other-branch

Если git сообщает о конфликтах (и ТОЛЬКО ЕСЛИ конфликты), вы можете сделать следующее:

git merge --abort

Если слияние прошло успешно, вы не можете прервать его (только сбросить).

Если вы не готовы к слиянию, используйте более безопасный способ выше.

[EDIT: 2016-ноябрь - я поменял стратегию 1 на 2, потому что, похоже, большинство людей ищут "безопасный путь". Стратегия 2 теперь больше напоминает, что вы можете просто прервать слияние, если у слияния есть конфликты, с которыми вы не готовы иметь дело. Имейте в виду, если читаете комментарии!]

Ответ 2

  • git log ..otherbranch
    • список изменений, которые будут объединены в текущую ветку.
  • git diff ...otherbranch
    • diff от общего предка (базы слияния) до главы того, что будет объединено. Обратите внимание на три точки, которые имеют особое значение по сравнению с двумя точками (см. ниже).
  • gitk ...otherbranch
    • графическое представление ветвей с момента их объединения в последний раз.

Пустая строка подразумевает HEAD, так что почему бы просто ..otherbranch вместо HEAD..otherbranch.

Две точки против трех имеют немного другое значение для diff, чем для команд, которые перечисляют ревизии (log, gitk и т.д.). Для log и других две точки (a..b) означают все, что находится в b, но не a, а три точки (a...b) означают все, что находится только в одном из a или b. Но diff работает с двумя ревизиями, и в этом случае более простой случай, представленный двумя точками (a..b), представляет собой простую разницу от a до b, а три точки (a...b) означают разницу между общим предком и b (git diff $(git merge-base a b)..b).

Ответ 3

Если вы похожи на меня, вы ищете эквивалент svn update -n. Следующее, кажется, делает трюк. Обратите внимание, что сначала нужно сделать git fetch, чтобы в вашем локальном репо были соответствующие обновления для сравнения.

$ git fetch origin
$ git diff --name-status origin/master
D       TableAudit/Step0_DeleteOldFiles.sh
D       TableAudit/Step1_PopulateRawTableList.sh
A       manbuild/staff_companies.sql
M       update-all-slave-dbs.sh

или если вы хотите использовать различие между вашей головой и пультом дистанционного управления:

$ git fetch origin
$ git diff origin/master

ИМО, это решение намного проще и менее подвержено ошибкам (и, следовательно, намного менее рискованно), чем топовое решение, которое предлагает "объединить, а затем прервать".

Ответ 4

Добавляя к существующим ответам, можно создать псевдоним, чтобы показать diff и/или журнал до слияния. Многие ответы опускают fetch, прежде чем "просмотреть" слияние; это псевдоним, который объединяет эти два шага в один (имитирующий нечто похожее на меркуриальный hg incoming/outgoing)

Итак, опираясь на "git log ..otherbranch", вы можете добавить следующее в ~/.gitconfig:

...
[alias]
    # fetch and show what would be merged (use option "-p" to see patch)
    incoming = "!git remote update -p; git log [email protected]{u}"

Для симметрии, следующий псевдоним может использоваться, чтобы показать, что зафиксировано и будет нажато, до нажатия:

    # what would be pushed (currently committed)
    outgoing = log @{u}..

И затем вы можете запустить "git incoming", чтобы показать много изменений, или "git incoming -p", чтобы показать патч (например, "diff" ), "git incoming --pretty=oneline", для краткой сводки, и т.д. Затем вы можете (необязательно) запустить "git pull" для фактического слияния. (Хотя, поскольку вы уже выбрали, слияние может быть выполнено напрямую.)

Аналогично, "git outgoing" показывает, что было бы нажато, если вы должны были запустить "git push".

Ответ 5

Если вы уже выбрали изменения, мой любимый:

git log [email protected]{u}

Для этого требуется git 1.7.x. Обозначение @{u} является "сокращением" для восходящей ветки, поэтому оно немного более универсально, чем git log ...origin/master.

Примечание. Если вы используете zsh и расширенную функцию glog, вы, вероятно, должны сделать что-то вроде:

git log [email protected]\{u\}

Ответ 6

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

Чтобы действительно увидеть, что изменится в ветке master, если вы объедините в нее develop, прямо сейчас:

git merge-tree $(git merge-base master develop) master develop

Поскольку это сантехническая команда, она не угадывает, что вы имеете в виду, вы должны быть явными. Он также не окрашивает вывод и не использует ваш пейджер, поэтому полная команда будет такой:

git merge-tree $(git merge-base master develop) master develop | colordiff | $(git var GIT_PAGER)

- https://git.seveas.net/previewing-a-merge-result.html

(спасибо Дэвиду Нормингтону за ссылку)

P.S.:

Если вы получите конфликты слияния, они будут отображаться с обычными маркерами конфликта в выходных данных, например:

$ git merge-tree $(git merge-base a b ) a b 
added in both
  our    100644 78981922613b2afb6025042ff6bd878ac1994e85 a
  their  100644 61780798228d17af2d34fce4cfbdf35556832472 a
@@ -1 +1,5 @@
+<<<<<<< .our
 a
+=======
+b
+>>>>>>> .their

P.S. 2: на моей машине (vanilla Mac OS X) строка GIT_PAGER заканчивается использованием less, который не любит цветной ввод. Мне пришлось добавить export LESS=FRX в мой ~/.bashrc, чтобы сделать его приемлемым. Благодаря https://unix.stackexchange.com/questions/153943/git-pager-is-less-but-what-is-causing-the-output-coloring

Ответ 7

git log currentbranch..otherbranch предоставит вам список коммитов, которые войдут в текущую ветку, если вы выполните слияние. Обычные аргументы для регистрации, которые дают подробности о фиксации, предоставят вам дополнительную информацию.

git diff currentbranch otherbranch даст вам разницу между двумя коммитами, которые станут единым целым. Это будет diff, который даст вам все, что будет слито.

Помогли бы?

Ответ 8

Запрос Pull - я использовал большинство уже представленных идей, но тот, который я также часто использую, (особенно если он принадлежит другому разработчику), делает запрос Pull, который дает удобный способ просмотреть все изменения в слиянии прежде чем это произойдет. Я знаю, что это GitHub не git, но это очень удобно.

Ответ 9

За исключением того, что на самом деле выполняется слияние в режиме выброса (см. ответ Kasapo), похоже, нет надежного способа увидеть это.

Сказав это, здесь метод, который близок к концу:

git log TARGET_BRANCH...SOURCE_BRANCH --cherry

Это дает справедливое указание на то, какие коммиты превратят его в слияние. Чтобы увидеть diffs, добавьте -p. Чтобы увидеть имена файлов, добавьте любые из --raw, --stat, --name-only, --name-status.

Проблема с подходом git diff TARGET_BRANCH...SOURCE_BRANCH (см. ответ Jan Hudec) заключается в том, что вы увидите различия для изменений уже в вашей целевой ветки, если ваша ветка источника содержит перекрестные слияния.

Ответ 10

Может быть, это может вам помочь? git -diff-tree - сравнивает содержимое и режим blobs, найденных с помощью двух древовидных объектов

Ответ 11

Я не хочу использовать команду git merge в качестве предшественника для просмотра конфликтующих файлов. Я не хочу слияния, я хочу выявить потенциальные проблемы до слияния - проблемы, которые могут возникнуть в результате автоматического слияния. Решение, которое я искал, заключается в том, как git выслать список файлов, которые были изменены в обеих ветвях, которые будут объединены вместе в будущем относительно некоторого общего предка. После того, как у меня есть этот список, я могу использовать другие инструменты сравнения файлов, чтобы выяснить, что дальше. Я искал несколько раз, и я до сих пор не нашел то, что хочу, в нативной git команде.

Вот мое обходное решение, если оно помогает кому-то еще:

В этом случае у меня есть ветвь с именем QA, которая имеет много изменений в ней со времени последнего выпуска. Наш последний выпуск продукции отмечен "15.20.1". У меня есть еще одна ветвь развития, называемая new_stuff, которую я хочу объединить в ветвь QA. И QA, и new_stuff указывают на то, что "follow" (как сообщается gitk) тег 15.20.1.

git checkout QA
git pull
git diff 15.20.1 --name-only > QA_files
git checkout new_stuff
git pull
git diff 15.20.1 --name-only > new_stuff_files
comm -12 QA_files new_stuff_files

Вот несколько дискуссий, которые касаются того, почему я заинтересован в таргетинге на эти конкретные файлы:

Как я могу доверять git merge?

https://softwareengineering.stackexchange.com/info/199780/how-far-do-you-trust-automerge