Разрешить конфликты Git слияния в пользу их изменений во время вытягивания


1227

Как мне разрешить конфликт git merge в пользу внесенных изменений?

По сути, мне нужно удалить все конфликтующие изменения из рабочего дерева без необходимости проходить через все конфликты с git mergetoolсохранением всех бесконфликтных изменений. Желательно делать это во время вытягивания, а не после.


3
возможный дубликат git merge - наш, что насчет "их"


3
@DanDascalescu Принятый ответ там не отвечает на эти вопросы, поэтому ясно, что это не дубликат. Плюс, этот другой вопрос довольно двусмысленный: очень трудно сказать, что задают. В общем, я не могу с тобой согласиться. Что вы на это указываете?
Sanmai

2
@sanmai У вас есть два ответа - и вы приняли один из них. Можете ли вы лучше объяснить, что вы ожидаете в ответе и сколько подробностей вы хотите здесь?
Эдвард Томсон

2
@ EdwardThomson ну, на самом деле я думал дать эту репутацию за первый ответ, но если вы спросите, я мог бы подождать и посмотреть, появится ли лучший ответ
sanmai

Ответы:


1221
git pull -s recursive -X theirs <remoterepo or other repo>

Или просто для хранилища по умолчанию:

git pull -X theirs

Если вы уже в конфликтном состоянии ...

git checkout --theirs path/to/file

40
Обратите внимание, что -s recursiveздесь избыточно, так как это стратегия слияния по умолчанию. Таким образом, вы можете упростить это до git pull -X theirs, что в основном эквивалентно git pull --strategy-option theirs.

5
Если я сделаю это, я снова окажусь в MERGINGсостоянии. Я могу тогда git merge --abortи попытаться снова, но каждый раз, когда я заканчиваю слиянием. … Я знаю, что ребаз был перенесен в мой апстрим, так что, может быть, это вызвало это?
Бенджон

22
Будьте осторожны с git checkout --theirs path/to/file. Использовал его при ребазе и получил неожиданные результаты. Найдено объяснение в doc: обратите внимание, что во время git rebase и git pull --rebase наши и их могут показаться переставленными; --ours дает версию из ветки, на которую были перебазированы изменения, а --theirs дает версию из ветки, в которой хранится ваша работа, которая перебазируется.
Вук Джапич

10
Обратите внимание, что на git checkout --theirs/--ours pathстранице руководства говорится, что она работает для неотключенных путей . Таким образом, если в пути не было конфликта, он уже объединен, эта команда ничего не сделает. Это может вызвать проблемы, когда вы хотите, например, «их» версию целой подпапки. Так что в таком случае было бы безопаснее делать git checkout MERGE_HEAD pathили использовать хеш коммита.
ЖСБ

4
git pull -X theirsсоздает коммит слияния, если есть конфликты (например, если другой коммиттер бежал git push -fк удаленному). Если вы не хотите коммитов слияния, запустите вместо этого git fetch && git reset --hard origin/master.
Дан Даскалеску

986

Вы можете использовать рекурсивную опцию "их" стратегии :

git merge --strategy-option theirs

От мужчины :

ours
    This option forces conflicting hunks to be auto-resolved cleanly by 
    favoring our version. Changes from the other tree that do not 
    conflict with our side are reflected to the merge result.

    This should not be confused with the ours merge strategy, which does 
    not even look at what the other tree contains at all. It discards 
    everything the other tree did, declaring our history contains all that
    happened in it.

theirs
    This is opposite of ours.

Примечание. Как сказано в справочной странице, опция «наша» стратегия слияния сильно отличается от «нашей» стратегии слияния .


Вот более подробное объяснение: lostechies.com/joshuaflanagan/2010/01/29/…
mPrinC

227
Также git checkout --theirsдля работы с одним конфликтующим файлом
DVD

48
Это не работает, если вы уже находитесь в состоянии разрешения конфликта. В этом случае я считаю, что лучший способ решить это git checkout <ref to theirs> -- the/conflicted.file; а потомgit add их изменения.
ThorSummoner

54
@ThorSummoner В этом случае есть git checkout - их путь / of / file. Таким образом, вам не нужно вручную искать правильный хеш.
Икке,

8
@Ikke Это должен быть собственный ответ (и принятый ответ), если вы спросите меня.
ThorSummoner

475

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

git checkout --theirs .
git add .

Если вы хотите сделать наоборот:

git checkout --ours .
git add .

Это довольно радикально, поэтому убедитесь, что вы действительно хотите уничтожить все, как это, прежде чем делать это.


47
или не используйте .и укажите файл (ы) вместо точки, которую вы хотите оформить. менее "радикально" и именно то, что вы хотите сделать, по-видимому.
Манро

10
это не работает, если файл был удален из другой ветки: у '<file>' нет своей версии
Japster24

3
Если бы я мог, я бы сказал больше, продолжайте время от времени возвращаться к этому ответу.
tarikki

6
git add -uВместо этого используйте для пропуска файлов, которые не находятся под контролем версий.
Судипта Басак

3
Гипотетический случай: три изменения в файле, одно конфликтующее, два без конфликта, будет ли это решение применять не конфликтующие изменения и разрешать конфликтующие изменения с нашими? Или потребуется только наша версия, игнорирующая неконфликтные изменения?
Педромарс

222

Хорошо, представьте сценарий, в котором я только что был:

Вы пытаетесь merge, или, может быть cherry-pick, и вы остановились с

$ git cherry-pick 1023e24
error: could not apply 1023e24... [Commit Message]
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

Теперь вы просматриваете конфликтующий файл и действительно не хотите сохранять свои изменения. В моем случае выше, файл конфликтовал только на новой строке, которая была автоматически добавлена ​​в моей IDE. Чтобы отменить изменения и принять их, самый простой способ:

git checkout --theirs path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Обратное (перезаписать входящую версию вашей версией)

git checkout --ours path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Удивительно, но я не мог найти этот ответ очень легко в сети.


15
Обратите внимание, что если вы выполняете git statusмежду checkoutи add, файл по-прежнему отображается как «оба изменены».
епископ

Знаете ли вы, есть ли способ сделать это для всех файлов, которые находятся в конфликтном состоянии? Если так, то это будет хорошим продолжением вашего ответа.
Дрю Ноакс

2
Я делаю это: git reset --hard и затем git pull [remote server name] [branch name] -Xtheirs(отменяет слияние, затем тянет новые вещи поверх моих вещей) - не уверен, что это то, что вы хотите.
ssaltman

38

Эти git pull -X theirsответы могут создать уродливое слияние совершить, или выдать

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

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

git fetch && git reset --hard origin/master

Как это работает? git fetchделает , git pullно без слияния . Затем git reset --hardваше рабочее дерево совпадает с последним коммитом. Все ваши локальные изменения файлов в репо будут отброшены , но новые локальные файлы будут оставлены в покое.


1
+1 - git fetch && git reset --hard {remote}/{branch}это то, что решило мою проблему. Мне нужно было полностью отказаться от собственных изменений в пользу «их» состояния ветви, но git pull -X theirsнекоторые файлы были перемещены / переименованы. Спасибо!
Ивайло Славов

24

После git merge, если вы получаете конфликты и хотите либо свои, либо свои

git checkout --theirs .
git checkout --ours .

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

21

Чтобы разрешить все конфликты с версией в конкретной ветке:

git diff --name-only --diff-filter=U | xargs git checkout ${branchName}

Итак, если вы уже находитесь в состоянии слияния и хотите сохранить основную версию конфликтующих файлов:

git diff --name-only --diff-filter=U | xargs git checkout master

И для людей на окнах без доступа к трубе XARGS, как это переводится?
Цемер

Разве это не пропустит ваши изменения полностью? Даже те, которые не находятся в конфликтном состоянии?
Валентин Хайниц

Это то, что я в итоге сделал. К сожалению, в дальнейшем требует либо git cherry-pick --continue или в git commit --allow-emptyкоманде , чтобы совершить эти изменения, и , кажется , нет никакой системы , за которой требуется команда, которая делает автоматизации этого боль. В настоящее время я решаю эту проблему, проверяя наличие .git/COMMIT_EDITMSGфайла, но он кажется хакерским и хрупким, и я еще не уверен, что он всегда работает.
Конрад Рудольф

Это хорошо, это означает, что если вы вручную разрешите некоторые (и сделаете git add), то вы можете решить все остальное с помощью этого. git checkout --ours/ git checkout --theirsтоже полезно.
rcoup

18

Пожалуйста, не то, что иногда это не будет работать :

git checkout --our path / to / file

или

git checkout - их путь / к / файлу

Я сделал это вместо этого, предполагая, что HEAD наша, а MERGE_HEAD их

git checkout HEAD -- path/to/file

или:

git checkout MERGE_HEAD -- path/to/file

После того как мы это сделаем и у нас все хорошо

git add .

Если вы хотите понять больше, посмотрите замечательный пост torek здесь: git checkout --ours не удаляет файлы из списка непогруженных файлов


12

VS Code (интегрированный Git) IDE Пользователи:

Если вы хотите принять все входящие изменения в файле конфликта, выполните следующие действия.

1. Go to command palette - Ctrl + Shift + P
2. Select the option - Merge Conflict: Accept All Incoming

Точно так же вы можете сделать для других опций, таких как Принять все оба, Принять все текущие и т. Д.,


2
Это, кажется, работает только для одного файла, но не для всех файлов с конфликтами.
Yoryo

1

У меня была длинная next-versionветка с кучей удалений файлов, которые были изменены develop, файлы, которые были добавлены в разных местах в обеих ветвях и т. Д.

Я хотел взять все содержимое next-versionветки develop, все в одном коммитте слияния.

Комбинация вышеупомянутых команд, которые работали для меня, была:

git merge -X theirs next-version
# lots of files left that were modified on develop but deleted on next-version
git checkout next-version .
# files removed, now add the deletions to the commit
git add .
# still have files that were added on develop; in my case they are all in web/
git rm -r web

Не новый ответ, просто объединение битов из многих ответов, отчасти, чтобы заверить, что вам могут понадобиться все эти ответы.


1

Если вы уже находитесь в конфликтном состоянии и не хотите проверять путь один за другим. Вы можете попробовать

git merge --abort
git pull -X theirs

-1

от https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging

Это в основном сделает поддельное слияние. Он будет записывать новый коммит слияния с обеими ветвями как родителями, но он даже не будет смотреть на ветвь, в которую вы сливаетесь. В результате слияния он просто записывает точный код в вашей текущей ветке.

$ git merge -s ours mundo

Слияние, сделанное по «нашей» стратегии.

$ git diff HEAD HEAD~

Вы можете видеть, что нет разницы между ветвью, в которой мы были, и результатом слияния.

Часто это может быть полезно, чтобы обмануть Git, думая, что ветвь уже объединена при последующем слиянии. Например, допустим, что вы разветвили ветку релиза и выполнили некоторую работу над ней, чтобы в какой-то момент вам захотелось вернуться обратно в основную ветку. Тем временем некоторые исправления на master необходимо перенести в ветку релизов. Вы можете объединить ветку исправления ошибок с веткой выпуска, а также слить нашу ветку с той же веткой в ​​вашу основную ветку (даже если исправление уже есть), поэтому, когда вы позже снова объедините ветку выпуска, не возникнет конфликтов с исправлением ошибки.

Ситуация, которую я нашел полезной, если я хочу, чтобы master отражал изменения в новой ветке темы. Я заметил, что -Xtheirs не сливается без конфликтов в некоторых обстоятельствах ... например

$ git merge -Xtheirs topicFoo 

CONFLICT (modify/delete): js/search.js deleted in HEAD and modified in topicFoo. Version topicFoo of js/search.js left in tree.

В этом случае решение, которое я нашел, было

$ git checkout topicFoo

из topicFoo, первое слияние в master с использованием -s нашей стратегии, это создаст поддельный коммит, который является просто состоянием topicFoo. $ git merge - наш мастер

проверить созданный коммит слияния

$ git log

сейчас оформляю мастер ветку

$ git checkout master

объедините ветку темы обратно, но на этот раз используйте рекурсивную стратегию -Xtheirs, теперь вы увидите главную ветку с состоянием topicFoo.

$ git merge -X theirs topicFoo
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.