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

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

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

20 ответов

Решение

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

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.

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

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

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

git pull -X theirs

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

git checkout --theirs path/to/file

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

git checkout --theirs .
git add .

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

git checkout --ours .
git add .

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

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

Вы пытаетесь 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

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

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

git merge --abort
git pull -X theirs

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

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

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

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

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

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

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

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

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 не удаляет файлы из списка незакрытых файлов

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

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

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

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

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

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

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

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

Обновление 2023!

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

      git merge [branch] --strategy-option ours

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

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

      git merge [branch] --strategy-option theirs

git checkout --ours/theirsне разрешает конфликты исключительно. Он проверяет (берет весь файл) либо из ours/theirs.

Предположим, у нас есть файл с изменениями в двух коммитах / ветках / деревьях / чем угодно. Если был конфликт, внесенный ими, а также модификация, и мы хотим разрешить конфликт, используя ours - затем используя checkout --ours foo отбросит изменения, вызывающие конфликты, но также и модификации.

Использование SED

Разрешите, используя их:

sed -i -e '/<<<<<<</,/=======/d' -e '/>>>>>>>/d' foo

  • -i Измените файл на месте,
  • /<<<<<<</,/=======/d удалить все между включительно <<<<<<< и ======= (наш)
  • />>>>>>>/d удалить оставшийся маркер конфликта
  • -e указать несколько шаблонов для SED
  • foo файл

Разрешите с помощью наших:

sed -i -e '/<<<<<<</d' -e '/=======/,/>>>>>>>/d' foo

с 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

Начнем с примера: у нас есть ветка и ветка с некоторыми конфликтами.

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

      git checkout main
git pull
git checkout dev

Затем объедините:

  • если вы хотите принять входящие изменения из основного источника истины:
      git merge --strategy-option theirs main
  • если вы хотите принять текущие изменения в разработке как источник истины:
      git merge --strategy-option ours main

oursиtheirsздесь особые слова, они имеют значение и не являются привычными, ноmainилиdevэто могут быть любые другие две ветки, которые вы хотите объединить.

Принять удаленные изменения (theirs) и в случае конфликтов вы получите следующую ошибку:

      fatal: Not possible to fast-forward, aborting.

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

      $ git pull -X theirs --ff

У меня был давний 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

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

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

      (defun smerge-keep-mine-all ()
  ""
  (interactive)
  (beginning-of-buffer)
  (while (progn (smerge-next) t)
    (smerge-keep-mine)))

(defun smerge-keep-other-all ()
    ""
  (interactive)
  (beginning-of-buffer)
  (while (progn (smerge-next) t)
    (smerge-keep-other)))

Несмотря на то, что здесь уже есть отличные ответы, я хотел опубликовать этот ответ, чтобы задокументировать, как разрешать все конфликты слияния в Visual Studio (в качестве примера в пользу наших изменений).

Если вместо этого вы хотите принять входящие изменения ( их изменения), как указано в этом вопросе, просто заменитеoursна шаге 6 ниже сtheirs. Это так просто.


Краткое изложение того, что я здесь делаю:

Объедините dev в мою ветку и при этом, если возникнут какие-либо конфликты слияния, внесите изменения из моей ветки.

(После того, как это будет сделано, я создам PR, чтобы окончательно передать изменения из моей ветки в dev ).


Шаг 1

Проверьте ветку, в которую вы хотите объединиться, перейдя в « Управление ветками » и дважды щелкнув имя своей ветки. В моем случае этоfeature\InterimBranchToDev2-AshK.

Шаг 2:

Щелкните правой кнопкой мышиdevи нажмитеMerge 'dev' into 'feature/InterimBranchToDev2-AshK'

Шаг 3:

Вы увидите массу конфликтов слияния!

Теперь очень утомительно щелкать правой кнопкой мыши каждый из этих файлов и нажиматьKeep Current (feature/InterimBranchToDev2-AshK), так что давайте позаботимся об этом с помощью командной строки.

Шаг 4:

УдарятьAbort

Шаг 5:

Открытьcmd

Шаг 6:

Типgit merge --strategy-option ours --no-commit devи нажмите ввод

Что это в основном означает: «Объединить dev в текущую ветку и, если есть какие-либо конфликты слияния, взять версию из текущей ветки, а также пока не выполнять слияние».

Это будет вывод:Automatic merge went well; stopped before committing as requested

Шаг 7:

Теперь перейдите в Visual Studio, конфликты хорошо улажены, и вы можете ввести свое сообщение и зафиксировать:

Я обнаружил, что мне нужно указать origin main как ветку, в которую я сливался.

      git merge **origin main** --strategy-option theirs

Это решено.Чтобы разрешить все конфликты, выполните следующие простые шаги.

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

git pull -X theirs

git pull origin master
Другие вопросы по тегам