Я столкнулся с конфликтом слияний. Как я могу прервать слияние?

2540

Я использовал git pullи имел конфликт слияния:

unmerged:   _widget.html.erb

You are in the middle of a conflicted merge.

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

Гвин Морфей
источник
30
Я понимаю, что это очень старый вопрос, но хотите ли вы отменить все слияние и оставить объединенную ветвь без слияния или просто проигнорировать этот один файл как часть большего слияния, позволяя объединить все остальные файлы как нормальный? Для меня ваше название подразумевает первое, ваше тело вопроса хочет второе. Ответы делают оба, не проясняя ничего.
Rjmunro
Я получил аналогичный случай при коммите, говоря, что автоматическое слияние не удалось; исправить конфликты и затем зафиксировать результат:[rejected] gh-pages -> gh-pages (non-fast-forward)
Chetabahana
4
Гвин, здесь может быть полезно выбрать приемлемый ответ. Один из лучших проголосовал немного менее безопасно, чем некоторые из более современных решений, поэтому я думаю, что это поможет выделить других над ним :)
Amicable

Ответы:

2223

Так как ваша pullнеудача была неудачной, то HEAD(не HEAD^) является последним "действительным" коммитом в вашей ветке:

git reset --hard HEAD

Другая часть, которую вы хотите, - позволить их изменениям перевесить ваши изменения.

Более старые версии git позволяли вам использовать «их» стратегию слияния:

git pull --strategy=theirs remote_branch

Но с тех пор это было удалено, как объяснено в этом сообщении Джунио Хамано (сопровождающий Git). Как отмечено в ссылке , вместо этого вы должны сделать это:

git fetch origin
git reset --hard origin
Пэт Нотц
источник
49
Вместо того, чтобы делать полный сброс, вы можете перевести его на более детальный уровень, выполнив: git fetch origin -> git reset origin (soft reset, your changes are still present) -> git checkout file_to_use_their_version_of another_file (steamroll your own changes back to match the origin) Я больше никогда не использую git pull. Так как в борьбе между моим последним кодом и источником, источник всегда должен побеждать, я всегда git fetchи git rebase origin. Это на самом деле делает мои слияния и конфликты немногочисленными.
Kzqai
7
Согласен. Я также хотел бы сначала получить, а затем изучить изменения в исходной версии ( git log ..@{upstream}или git diff ..@{upstream}). После этого, как и вы, я переоформлю свою работу.
Пэт Нотц
162
Как отмечено в более недавнем ответе, начиная с версии 1.6.1, можно использовать «git reset --merge»
Matt Ball
5
Я использовал git merge -X theirs remote_branchвместо , git pull --strategy=theirs remote_branchкак theirsвыглядит , как вариант изrecursive
MLT
14
git merge --abortгораздо предпочтительнее.
Даниэль Кэссиди
1956

Если ваша версия git> = 1.6.1, вы можете использовать git reset --merge.

Также, как упоминает @Michael Johnson, если ваша версия git> = 1.7.4, вы также можете использовать git merge --abort.

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

Из справочной страницы git merge

git merge --abortэквивалентно тому, git reset --mergeкогда MERGE_HEADприсутствует.

MERGE_HEAD присутствует, когда происходит слияние.

Также относительно непринятых изменений при запуске слияния:

Если у вас есть изменения, которые вы не хотите фиксировать до начала слияния, просто внесите git stashих до слияния и git stash popпосле завершения слияния или его отмены.

деревенщина
источник
3
Интересно - но руководство меня пугает. Когда именно это целесообразно использовать? Когда бы вам пришлось указать необязательный <commit>? #GitMoment: -o
Конни
1
Обычно вы используете это, когда хотите повторить слияние с самого начала. Мне никогда не приходилось указывать дополнительный коммит самостоятельно, поэтому по умолчанию (без дополнительного <commit>) все в порядке.
Карл
44
Я бы хотел, чтобы у этого ответа было больше голосов! На данный момент, это кажется наиболее актуальным решением во многих случаях.
Джей Тейлор
1
Даже при несдержанных изменениях git смог восстановить состояние до слияния. Ницца!
T3rm1
2
Это git merge --abortпросто синоним для git reset --merge? Название, безусловно, имеет больше смысла, но имеет ли оно такую ​​же функциональность?
Тихон Джелвис
518
git merge --abort

Прервите текущий процесс разрешения конфликтов и попытайтесь восстановить состояние перед объединением.

Если в момент начала слияния присутствовали незафиксированные изменения рабочего дерева, git merge --abortв некоторых случаях невозможно будет восстановить эти изменения. Поэтому рекомендуется всегда фиксировать или сохранять ваши изменения перед запуском git merge.

git merge --abortэквивалентно тому, git reset --mergeкогда MERGE_HEADприсутствует.

http://www.git-scm.com/docs/git-merge

обманчивая надежда
источник
16
Это было доступно с git v1.7.4. Это псевдоним сброса git --merge.
Майкл Джонсон
162

Это так просто.

git merge --abort

Сам Git показывает вам решение, когда вы находитесь в такой ситуации и запускаете команду git status.

git status

Надеюсь, это поможет людям.

Джагруттам Панчал
источник
97

Я думаю это git resetтебе нужно.

Имейте в git revertвиду, что это означает что-то совершенно иное, скажем, svn revert- в Subversion git revertвозврат отменит ваши (незафиксированные) изменения, вернув файл в текущую версию из репозитория, тогда как «отменяет» коммит.

git resetдолжен сделать эквивалент svn revert, то есть отменить ваши нежелательные изменения.

Дэвид Драгоценный
источник
76

В этом конкретном случае вы не хотите прерывать слияние, просто разрешите конфликт определенным образом.

Также нет особой необходимости сбрасывать и выполнять слияние с другой стратегией. Git правильно выделил конфликты, и требование принять изменения других сторон относится только к этому файлу.

Для необработанного файла в конфликте git делает доступной общую базовую, локальную и удаленную версии файла в индексе. (Это то место, откуда они читаются для использования в инструменте 3-way diff git mergetool.) Вы можете использовать их git showдля просмотра.

# common base:
git show :1:_widget.html.erb

# 'ours'
git show :2:_widget.html.erb

# 'theirs'
git show :3:_widget.html.erb

Самый простой способ разрешить конфликт - использовать дословную версию удаленной версии:

git show :3:_widget.html.erb >_widget.html.erb
git add _widget.html.erb

Или с git> = 1.6.1:

git checkout --theirs _widget.html.erb
CB Bailey
источник
5
спасибо за подсказку разве это не привкус плохого пользовательского интерфейса git?
Питер
@Peter: я не уверен. Желаемый результат достигается несколькими базовыми командами с простыми опциями. Какие улучшения вы бы предложили?
CB Bailey
10
Я думаю, что git 1.6.1команда имеет много смысла, и это хорошо. Это именно то, что я хотел бы. Я думаю, что решение до 1.6.1 не элегантно и требует знаний о других частях git, которые должны быть отделены от процесса разрешения слияния. Но новая версия отличная!
Питер
68

Для сценария, подобного, я сделал, git fetchа git pullзатем понял, что восходящая ветвь не была главной ветвью, что приводило к нежелательным конфликтам.

git reset --merge 

Это вернулось назад без сброса локальных изменений.

naamadheya
источник
45

Комментарии предполагают, что git reset --mergeэто псевдоним для git merge --abort. Стоит отметить, что git merge --abortэто эквивалентно только тому, git reset --mergeчто MERGE_HEADприсутствует. Это можно прочитать в справке git для команды слияния.

git merge --abort эквивалентно git reset --merge, когда присутствует MERGE_HEAD.

После неудачного слияния, когда его нет MERGE_HEAD, неудачное слияние можно отменить git reset --merge, но не обязательно с помощью git merge --abort. Это не только старый и новый синтаксис для одного и того же .

Лично я нахожу git reset --mergeгораздо более мощным для сценариев, похожих на описанный, и неудачных слияний в целом.

Мартин Г
источник
2
что здесь на самом деле означает «неудачное слияние»? Слиться с конфликтами или что-то еще? Или перефразировать: когда MERGE_HEAD нет? Мой следующий вопрос заключается в том, чтобы лучше понять использование git reset --merge.
Эвокс,
@Ewoks git stash applyвызвал конфликт слияния для меня, но git merge --abortне помог, пока git reset --mergeсделал.
Ницель
27

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

git reset --hard HEAD
git pull --strategy=theirs remote_branch
git fetch origin
git reset --hard origin

Пожалуйста, удалите

.git \ index.lock

Файл [вырезать вставить в другое место в случае восстановления], а затем введите любую из следующих команд в зависимости от того, какую версию вы хотите.

git reset --hard HEAD
git reset --hard origin

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

Нирав Мехта
источник
19

Альтернатива, которая сохраняет состояние рабочей копии:

git stash
git merge --abort
git stash pop

Я обычно советую против этого, потому что это фактически похоже на слияние в Subversion, поскольку оно отбрасывает отношения ветвления в следующем коммите.

Ален О'Ди
источник
Этот подход оказался полезным, когда я случайно слился с веткой git-svn, которая не справляется с этим. Сквош слияния или выбор вишни лучше при работе с ветками отслеживания git-svn. По сути, мое решение превращает слияние в слияние в сквош по факту.
Ален О'Ди
Лучший ответ на вопрос
Фуад Букредин
18

Начиная с Git 1.6.1.3 git checkoutможно было оформить заказ с любой стороны слияния:

git checkout --theirs _widget.html.erb
Ален О'Ди
источник
3

Я обнаружил, что следующее работает для меня (вернуть один файл в состояние перед объединением):

git reset *currentBranchIntoWhichYouMerged* -- *fileToBeReset*
Малкольм Бекхофф
источник
-5

Sourcetree

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

Камил Келчевски
источник