Как я могу отменить удаленные изменения и пометить файл как «разрешенный»? - PullRequest
191 голосов
/ 15 января 2010

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

Ответы [ 2 ]

317 голосов
/ 15 января 2010

git checkout имеет опцию --ours, чтобы проверить версию файла, которая была у вас локально (в отличие от --theirs, которая является версией, которую вы загрузили). Вы можете передать . на git checkout, чтобы сказать ему проверить все в дереве. Затем вам нужно пометить конфликты как разрешенные, что вы можете сделать с помощью git add, и зафиксировать свою работу, когда закончите:

git checkout --ours .  # checkout our local version of all files
git add -u             # mark all conflicted files as merged
git commit             # commit the merge

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

Это также хорошая привычка иметь при передаче имени файла смещение --, например git checkout --ours -- <filename>. Если вы этого не сделаете, а имя файла совпадает с именем ветви или тега, Git подумает, что вы хотите проверить эту ревизию вместо того, чтобы проверить это имя файла, и, таким образом, использовать первую форму checkout команда.

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

Самое простое, что вы на одной ревизии. В этом случае вы «уже в курсе», и ничего не происходит.

Другая возможность состоит в том, что их ревизия является просто вашей потомкой, и в этом случае по умолчанию у вас будет «ускоренное слияние», при котором ваш HEAD просто обновляется до их коммита, слияния не происходит ( это можно отключить, если вы действительно хотите записать слияние, используя --no-ff).

Затем вы попадаете в ситуации, в которых вам действительно нужно объединить две ревизии. В этом случае есть два возможных результата. Во-первых, слияние происходит чисто; все изменения находятся в разных файлах или в одних и тех же файлах, но достаточно далеко друг от друга, чтобы оба набора изменений можно было применить без проблем. По умолчанию, когда происходит чистое слияние, оно автоматически фиксируется, хотя вы можете отключить это с помощью --no-commit, если вам нужно отредактировать его заранее (например, если вы переименуете функцию foo в bar, а кто-то еще добавит новый код, который вызывает foo, он будет сливаться аккуратно, но при этом получится сломанное дерево, так что вы можете захотеть очистить его как часть коммита слияния, чтобы избежать каких-либо прерванных коммитов).

Последняя возможность - это реальное слияние и конфликты. В этом случае Git выполнит столько слияния, сколько сможет, и создаст файлы с маркерами конфликта (<<<<<<<, ======= и >>>>>>>) в вашей рабочей копии. В индексе (также известном как «промежуточная область»; место, где файлы хранятся git add перед их фиксацией), у вас будет 3 версии каждого файла с конфликтами; есть исходная версия файла от предка двух ветвей, которые вы объединяете, версия от HEAD (ваша сторона слияния) и версия от удаленной ветки.

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

21 голосов
/ 21 сентября 2012

Убедитесь в возникновении конфликта: если он является результатом git merge, см. Брайан Кэмпбелл * ответ .

Но если это результат git rebase, чтобы отбросить удаленные (их) изменения и использовать локальные изменения, вам придется выполнить:

git checkout --theirs -- .

См. " Почему значение" ours "и" theirs "перевернуто"", чтобы увидеть, как ours и theirs меняются местами во время перебазировки (потому что вверх по течению ветвь извлечена).

...