Как определить конфликтующие коммиты по хешу во время git rebase? - PullRequest
39 голосов
/ 22 января 2010

Когда я сталкиваюсь с конфликтом слияния с использованием git rebase, как я могу определить источник конфликта в терминах фиксаций , а не только из-за различий файлов?

Я уже знаю, как сделать (базовое) использование git mergetool или git add до git rebase --continue, но иногда различий между файлами просто недостаточно: я хочу увидеть журнал фиксации и разницу в фиксации это просто не удалось применить к рабочему дереву.

Я читал в других вопросах, что git log --merge будет показывать родительские коммиты, если я буду использовать git merge. Я все равно попробовал, когда столкнулся с конфликтом и мне сказали fatal: --merge without MERGE_HEAD?.

Как я могу определить проблемный коммит?

Ответы [ 6 ]

39 голосов
/ 22 января 2010

Короткий ответ

Если там написано

Patch failed at 0001 commit message for F

Затем запустите

$ head -1 .git/rebase-apply/0001
From ad1c7739c1152502229e3f2ab759ec5323988326 Mon Sep 17 00:00:00 2001

Чтобы получить SHA ad1c77 неудачного коммита, а затем используйте git show ad1c77, чтобы взглянуть на него.

Длинный ответ

Давайте начнем с этого дерева:

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

$ git checkout G
$ git rebase D

Когда возникает конфликт перебазирования, это конфликт между

  • восходящие изменения (C--D) от общего предка (B) PLUS уже отмененные изменения и уже разрешенный конфликт (E') против
  • патч следующего коммита (F)

Посмотрим, что получится:

1) A---B---C---D---E'          <- E patched and committed successfully as E'
2) A---B---C---D---E'---       <- failed to patch F onto E'

Вот сообщение об ошибке:

First, rewinding head to replay your work on top of it...
Applying: commit message for F
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging 1.txt
CONFLICT (content): Merge conflict in 1.txt
Failed to merge in the changes.
Patch failed at 0001 commit message for F

Во-первых, вы можете видеть, что это было F, потому что появляется сообщение о коммите. Однако, если все ваши сообщения коммита выглядят как «foo», «документация» или «некоторые исправления», то это не поможет, и вам действительно нужен идентификатор SHA ad1c77 или содержимое патча.

Вот как узнать настоящую личность F:

Когда он перечисляет конфликт rebase, он говорит что-то вроде:

Patch failed at 0001 commit message for F

Теперь посмотрите в .git/rebase-apply/, где вы найдете файл патча 0001:

$ ls .git/rebase-apply
0001          head-name     msg           orig-head     sign
0002          info          msg-clean     patch         threeway
apply-opt     keep          next          quiet         utf8
final-commit  last          onto          rebasing

Файл патча включает в себя оригинальный идентификатор фиксации

$ head -1 .git/rebase-apply/0001
From ad1c7739c1152502229e3f2ab759ec5323988326 Mon Sep 17 00:00:00 2001

Вы можете посмотреть на это.

Должен быть более простой способ, но это работает.

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

$ git checkout D
$ git rebase G
9 голосов
/ 18 января 2017

Во время git rebase, которое останавливается для разрешения конфликтов, следующая команда покажет конфликтующий коммит (все, а не только конфликтующие файлы), то есть ваш коммит в настоящее время воспроизводится / перебазируется на новую базу независимо где вы до:

git show $(< .git/rebase-apply/original-commit)

Если вы хотите видеть только конфликты для конкретного конфликтующего файла (того, который вы решаете), в изоляции:

git show $(< .git/rebase-apply/original-commit) -- /path/to/conflicting/file

Ни один кот не подвергался насилию при построении этого ответа:).

4 голосов
/ 03 октября 2018

Показать текущий / неудачный коммит

Это может быть новая функция, но REBASE_HEAD дает вам коммит, на котором вы остановились (например, если он не был применен). Если вы хотите увидеть коммит полностью, вы можете использовать

git show REBASE_HEAD

В качестве более подробной альтернативы вы можете использовать git rebase --show-commit-patch. Документы говорят, что они эквивалентны.

Покажите, что изменилось с тех пор, как вы начали свою работу

Если вы хотите увидеть, что изменилось между тем, откуда вы перебазируете, и тем, куда вы перебазируете, вы можете получить разницу между двумя ветвями. Например, если вы переходите с master на origin/master, вы можете использовать:

git diff master..origin/master

Или, если вы хотите видеть изменения как отдельные коммиты:

git log -p master..origin/master

Если вы предпочитаете использовать хеш или, возможно, через некоторое время возвращаетесь к перебазированию и не можете вспомнить, какие ветви вы перебазируете, вы можете использовать git status, чтобы увидеть две ветви. Например:

В настоящее время вы перебазируете ветку 'master' на 'b5284275'

Затем, чтобы увидеть, что изменилось, вы можете использовать:

git diff master..b5284275
2 голосов
/ 03 сентября 2014
cat .git/rebase-apply/original-commit

Учитывая это:

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

$ git checkout G
$ git rebase D

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

A---B---C---D--E'--!
     \
      E---F---G

тогда файл original-commit покажет хэш F. Это "их" версия.

Кроме того, HEAD (.git / HEAD) будет E 'в этом случае. Это «моя» версия. HEAD ^ будет "базовой" версией.

Это верно как минимум для git 1.7.9

1 голос
/ 25 декабря 2014

Не уверен, почему у меня нет .git/rebase-apply в моей ситуации. Для тех, кто в той же ситуации, вот мой вариант.

git show $(cat .git/rebase-merge/stopped-sha)

Или как псевдоним ...

git config --global alias.sp='!git show $(cat .git/rebase-merge/stopped-sha)'
0 голосов
/ 28 мая 2018

Много раз вы будете в середине перебазирования и захотите пропустить те коммиты, которые не нужны.

К сожалению, хотя git status сообщает вам, что вы находитесь в середине коммита и рекомендует использовать git rebase --continue git rebase --skip или git rebase --abort, он не сообщает вам, какой коммит вы используете в данный момент. *

Так что часто бывает трудно понять, стоит ли вам git rebase --skip или нет.

Тем не менее, есть еще способ узнать, на каком коммите вы находитесь, запустив:

git log -1 $(< .git/rebase-apply/original-commit)
...