Как разрешить конфликты слияния в Git - PullRequest
4421 голосов
/ 02 октября 2008

Как мне разрешить конфликты слияния в Git?

Ответы [ 34 ]

28 голосов
/ 26 января 2016

Проще говоря, если вы хорошо знаете, что изменения в одном из репозиториев не важны, и хотите разрешить все изменения в пользу другого, используйте:

git checkout . --ours

для разрешения изменений в пользу вашего хранилища или

git checkout . --theirs

для разрешения изменений в пользу другого или основного хранилища .

Или же вам придется использовать инструмент слияния с графическим интерфейсом для пошагового просмотра файлов, скажем, инструмент слияния p4merge, или написать имя, которое вы уже установили

git mergetool -t p4merge

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

28 голосов
/ 16 апреля 2015

Пожалуйста, выполните следующие шаги для исправления конфликтов слияния в Git:

  1. Проверьте статус Git: git status

  2. Получить набор патчей: git fetch (извлечение правильного патча из вашего коммита Git)

  3. Оформить заказ в локальной ветке (в моем примере это temp1): git checkout -b temp1

  4. Извлечь недавнее содержимое из мастера: git pull - мастер происхождения базы

  5. Запустите mergetool, проверьте конфликты и исправьте их ... и проверьте изменения в удаленной ветке с вашей текущей веткой: git mergetool

  6. Проверьте статус еще раз: git status

  7. Удалите ненужные файлы, локально созданные с помощью mergetool, обычно mergetool создает дополнительный файл с расширением * .orig. Пожалуйста, удалите этот файл, так как это просто дубликат, исправьте изменения локально и добавьте правильную версию своих файлов. git add # your_changed_correct_files

  8. Проверьте статус еще раз: git status

  9. Передайте изменения в один и тот же идентификатор фиксации (это позволяет избежать нового отдельного набора патчей): git commit --amend

  10. Нажмите на главную ветку: git push (в ваш репозиторий Git)

27 голосов
/ 25 декабря 2015

Бонус:

Говоря о pull / fetch / merge в приведенных выше ответах, я хотел бы поделиться интересным и продуктивным трюком,

git pull --rebase

Эта команда является самой полезной в моей жизни в git, которая сэкономила много времени.

Перед отправкой только что принятого изменения на удаленный сервер, попробуйте git pull --rebase, а не git pull и вручную merge, и он автоматически синхронизирует последние изменения удаленного сервера (с извлечением + объединением) и поместит ваш локальный последний коммит вершина в git log. Не нужно беспокоиться о ручном вытягивании / слиянии.

В случае конфликта просто используйте

git mergetool
git add conflict_file
git rebase --continue

Найти подробности можно по адресу: http://gitolite.com/git-pull--rebase

25 голосов
/ 23 июня 2017

Есть 3 шага:

  1. Найдите, какие файлы вызывают конфликты командой

    git status
    
  2. Проверьте файлы, в которых вы найдете конфликты, помеченные как

    <<<<<<<<head
    blablabla
    
  3. Измените его так, как вы хотите, затем подтвердите его командами

    git add solved_conflicts_files
    git commit -m 'merge msg'
    
25 голосов
/ 19 апреля 2013

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

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

У меня лично есть привычка 2 вещей, чтобы избежать этого.

Вместо:

git add .
git commit -m"some msg"

Который имеет два недостатка -

a) Все новые / измененные файлы добавляются, что может включать некоторые нежелательные изменения.
б) Вы не можете сначала просмотреть список файлов.

Так что вместо этого я делаю:

git add file,file2,file3...
git commit # Then type the files in the editor and save-quit.

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

[Обновление - со временем я переключился на:

git status # Make sure I know whats going on
git add .
git commit # Then use the editor

]

Также (и более актуально для вашей ситуации) я стараюсь избегать:

git pull

или

git pull origin master.

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

Вместо этого я пытаюсь сделать

git checkout master
git fetch   
git rebase --hard origin/master # or whatever branch I want.

Вы также можете найти это полезным:

git branch, fork, fetch, merge, rebase и clone, в чем различия?

22 голосов
/ 25 января 2014

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

(Code not in Conflict)
>>>>>>>>>>>
(first alternative for conflict starts here)
Multiple code lines here
===========
(second alternative for conflict starts here)
Multiple code lines here too    
<<<<<<<<<<<
(Code not in conflict here)

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

git commit -a -m "commit message"
git push origin master
15 голосов
/ 11 декабря 2014
git log --merge -p [[--] path]

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

Что мне делать, чтобы обойти эту проблему, так это открыть две командные строки и за один запуск

git log ..$MERGED_IN_BRANCH --pretty=full -p [path]

а в другом

git log $MERGED_IN_BRANCH.. --pretty=full -p [path]

Замена $MERGED_IN_BRANCH веткой, в которую я влился, и [path] файлом, который конфликтует. Эта команда будет регистрировать все коммиты в форме патча между (..) двумя коммитами. Если вы оставите одну сторону пустой, как в приведенных выше командах, git будет автоматически использовать HEAD (в данном случае ветвь, с которой вы объединяетесь).

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

15 голосов
/ 30 ноября 2016

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

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

Если вы, например, измените отступ вашей программы, стратегия слияния Git по умолчанию иногда соответствует одиночным скобкам {, которые принадлежат разным функциям. Этого можно избежать с помощью patience:

git merge -s recursive -X patience other-branch

Из документации:

With this option, merge-recursive spends a little extra time to avoid 
mismerges that sometimes occur due to unimportant matching lines 
(e.g., braces from distinct functions). Use this when the branches to 
be merged have diverged wildly.

Сравнение с общим предком

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

git diff $(git merge-base <our-branch> <their-branch>) <their-branch>

Обычно вы хотите видеть изменения только для определенного файла:

git diff $(git merge-base <our-branch> <their-branch>) <their-branch> <file>
15 голосов
/ 09 января 2017

С 12 декабря 2016 года вы можете объединять филиалы и разрешать конфликты на github.com

Таким образом, если вы не хотите использовать командную строку или любые сторонние инструменты, предлагаемые здесь из более старых ответов , используйте родной инструмент GitHub.

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

enter image description here

12 голосов
/ 12 февраля 2015

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

  • git checkout master (зайдите в ветку master)
  • git pull (Обновите ваш мастер, чтобы получить последний код)
  • git checkout -b mybranch (Извлеките новую ветку и начните работать над этой веткой, чтобы ваш мастер всегда оставался вершиной ствола.)
  • git add. И git commit & git push (в вашей локальной ветке после ваших изменений)
  • git checkout master (вернись к своему хозяину.)

Теперь вы можете делать то же самое и поддерживать столько локальных веток, сколько вам нужно, и работать одновременно, я просто делаю git checkout в вашу ветку, когда это необходимо.

...