Вопрос: Как разрешить конфликты слияния в Git


Есть ли хороший способ объяснить, как разрешать конфликты слияния в Git?


4083


источник


Ответы:


Пытаться: git mergetool

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

Согласно комментарию @JoshGlover:

Команда не обязательно открывает графический интерфейс, если вы не установите его. Бег git mergetoolдля меня результат vimdiffбыть использованным. Вы можете установить один из следующих инструментов, чтобы использовать его: meld, opendiff, kdiff3, tkdiff, xxdiff, tortoisemerge, gvimdiff, diffuse, ecmerge, p4merge, araxis, vimdiff, emerge,

Ниже приведен пример процедуры использования vimdiffдля разрешения конфликтов слияния. Основано на эта ссылка

Шаг 1 : Запустите следующие команды в терминале

git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false

Это установит vimdiff как инструмент объединения по умолчанию.

Шаг 2 : Выполнить следующую команду в терминале

git mergetool

Шаг 3 : Вы увидите дисплей vimdiff в следующем формате

  +----------------------+
  |       |      |       |
  |LOCAL  |BASE  |REMOTE |
  |       |      |       |
  +----------------------+
  |      MERGED          |
  |                      |
  +----------------------+

Эти 4 представления

LOCAL - это файл из текущей ветви

BASE - общий предок, как файл выглядел перед обоими изменениями

REMOTE - файл, который вы объединяете в свою ветку

MERGED - результат слияния, это то, что сохраняется в репо

Вы можете перемещаться между этими видами, используя ctrl+w, Вы можете напрямую просматривать MERGED, используя ctrl+wс последующим j,

Узнать больше о навигации vimdiff Вот а также Вот

Шаг 4 , Вы можете отредактировать представление MERGED следующим образом

Если вы хотите получить изменения от REMOTE

:diffg RE  

Если вы хотите получить изменения с BASE

:diffg BA  

Если вы хотите получить изменения из LOCAL

:diffg LO 

Шаг 5 , Сохранить, выйти, зафиксировать и очистить

:wqaсохранить и выйти из vi

git commit -m "message"

git cleanУдалите дополнительные файлы (например. * .orig), созданные с помощью инструмента diff.


2374



Вот вероятный прецедент, сверху:

Вы собираетесь внести некоторые изменения, но, к сожалению, вы не в курсе:

git fetch origin
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.

Таким образом, вы обновляетесь и снова пытаетесь, но имеете конфликт:

git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.

Поэтому вы решили взглянуть на изменения:

git mergetool

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

git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"

И затем мы попробуем последний раз

git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Already up-to-date.

Та-да!


1598



Я считаю, что инструменты слияния редко помогают мне понять конфликт или резолюцию. Я обычно более успешно смотрю маркеры конфликтов в текстовом редакторе и использует git log в качестве дополнения.

Вот несколько советов:

Совет один

Лучшее, что я нашел, это использовать стиль конфликта слияния «diff3»:

git config merge.conflictstyle diff3

Это создает такие маркеры конфликтов:

<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a 
feature/topic branch.
>>>>>>>

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

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

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

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

diff common mine
diff common theirs

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

Совет два

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

git log --merge -p <name of file>

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

Совет три

Проверьте свои изменения с помощью автоматизированных инструментов.

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

Совет четыре

Планировать заранее; общаться с коллегами.

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

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

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

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

Совет пять

Если вы не уверены в слиянии, не заставляйте его.

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

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


677



  1. Определите, какие файлы находятся в конфликте (Git должен сказать вам это).

  2. Откройте каждый файл и изучите различия; Гит демаркирует их. Надеюсь, будет очевидно, какую версию каждого блока сохранить. Возможно, вам придется обсудить это с другими разработчиками, которые совершили этот код.

  3. Как только вы разрешите конфликт в файле git add the_file,

  4. После того как вы разрешили все конфликты, git rebase --continueили любую команду Гит сказал сделать, когда закончишь.


318



Проверьте ответы в вопросе «Переполнение стека» Прерывание слияния в Git , особенно Ответ Чарльза Бейли который показывает, как просматривать различные версии файла с проблемами, например,

# Common base version of the file.
git show :1:some_file.cpp

# 'Ours' version of the file.
git show :2:some_file.cpp

# 'Theirs' version of the file.
git show :3:some_file.cpp

95



Merge conflicts happens when changes are made to a file at the same time. Here is how to solve it.

git CLI

Here are simple steps what to do when you get into conflicted state:

  1. Note the list of conflicted files with: git status (under Unmerged paths section).
  2. Solve the conflicts separately for each file by one of the following approaches:

    • Use GUI to solve the conflicts: git mergetool (the easiest way).

    • To accept remote/other version, use: git checkout --theirs path/file. This will reject any local changes you did for that file.

    • To accept local/our version, use: git checkout --ours path/file

      However you've to be careful, as remote changes that conflicts were done for some reason.

      Related: What is the precise meaning of "ours" and "theirs" in git?

    • Edit the conflicted files manually and look for the code block between <<<<</>>>>> then choose the version either from above or below =====. See: How conflicts are presented.

    • Path and filename conflicts can be solved by git add/git rm.

  3. Finally, review the files ready for commit using: git status.

    If you still have any files under Unmerged paths, and you did solve the conflict manually, then let Git know that you solved it by: git add path/file.

  4. If all conflicts were solved successfully, commit the changes by: git commit -a and push to remote as usual.

See also: Resolving a merge conflict from the command line at GitHub

DiffMerge

I've successfully used DiffMerge which can visually compare and merge files on Windows, macOS and Linux/Unix.

It graphically can show the changes between 3 files and it allows automatic merging (when safe to do so) and full control over editing the resulting file.

DiffMerge

Image source: DiffMerge (Linux screenshot)

Simply download it and run in repo as:

git mergetool -t diffmerge .

macOS

On macOS you can install via:

brew install caskroom/cask/brew-cask
brew cask install diffmerge

And probably (if not provided) you need the following extra simple wrapper placed in your PATH (e.g. /usr/bin):

#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"

Then you can use the following keyboard shortcuts:

  • -Alt-Up/Down to jump to previous/next changes.
  • -Alt-Left/Right to accept change from left or right

Alternatively you can use opendiff (part of Xcode Tools) which lets you merge two files or directories together to create a third file or directory.


87



If you're making frequent small commits, then start by looking at the commit comments with git log --merge. Then git diff will show you the conflicts.

For conflicts that involve more than a few lines, it's easier to see what's going on in an external GUI tool. I like opendiff -- Git also supports vimdiff, gvimdiff, kdiff3, tkdiff, meld, xxdiff, emerge out of the box and you can install others: git config merge.tool "your.tool" will set your chosen tool and then git mergetool after a failed merge will show you the diffs in context.

Each time you edit a file to resolve a conflict, git add filename will update the index and your diff will no longer show it. When all the conflicts are handled and their files have been git add-ed, git commit will complete your merge.


73



See How Conflicts Are Presented or, in Git, the git merge documentation to understand what merge conflict markers are.

Also, the How to Resolve Conflicts section explains how to resolve the conflicts:

After seeing a conflict, you can do two things:

  • Decide not to merge. The only clean-ups you need are to reset the index file to the HEAD commit to reverse 2. and to clean up working tree changes made by 2. and 3.; git merge --abort can be used for this.

  • Resolve the conflicts. Git will mark the conflicts in the working tree. Edit the files into shape and git add them to the index. Use git commit to seal the deal.

You can work through the conflict with a number of tools:

  • Use a mergetool. git mergetool to launch a graphical mergetool which will work you through the merge.

  • Look at the diffs. git diff will show a three-way diff, highlighting changes from both the HEAD and MERGE_HEAD versions.

  • Look at the diffs from each branch. git log --merge -p <path> will show diffs first for the HEAD version and then the MERGE_HEAD version.

  • Look at the originals. git show :1:filename shows the common ancestor, git show :2:filename shows the HEAD version, and git show :3:filename shows the MERGE_HEAD version.

You can also read about merge conflict markers and how to resolve them in the Pro Git book section Basic Merge Conflicts.


43