Как я могу отменить удаленные изменения и пометить файл как исправленный?

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


person Tom DeMille    schedule 15.01.2010    source источник
comment
Ответ ниже очень меня прояснил. Было сделано несколько тонких замечаний, которые действительно прояснили для меня ситуацию, я рекомендую всем неопытным пользователям GIT прочитать все комментарии под постом ниже, и спасибо, Брайан!   -  person Tom DeMille    schedule 15.01.2010


Ответы (2)


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.

person Brian Campbell    schedule 15.01.2010
comment
Вы, вероятно, должны заметить, что git add --all добавляет все файлы в репозиторий, поэтому это может добавить больше файлов, чем предполагалось, если только ваши .gitignore шаблоны не находятся в идеальном состоянии. git add -u, вероятно, больше подходит для этой ситуации, у вас меньше шансов внести изменения в отслеживаемые файлы, которые вы не хотите добавлять при разрешении слияния. - person CB Bailey; 15.01.2010
comment
Ой, извините. Это то, что я имел в виду. Исправил сейчас. - person Brian Campbell; 15.01.2010
comment
спасибо за подробный ответ. Я действительно попробовал git checkout --ours и получил сообщение об ошибке (которое я сейчас не помню). Речь идет о файлах dll (у нас есть несколько, которые мы ДЕЛАЕМ, в основном сторонние ссылки), и я хотел просто сказать: «Хорошо, моя копия - это те, которые я хочу, но ошибка была примерно такой:« Невозможно оформить заказ при слиянии ». ..... Я сохраню эту статью как справочную, и в следующий раз, когда это произойдет, попробуйте еще раз и посмотрю, сработает ли она или смогу ли я опубликовать это сообщение. Спасибо еще раз - person Tom DeMille; 15.01.2010
comment
но ваше объяснение многое проясняет для меня о процессе, еще раз спасибо ... Последующий вопрос: есть ли способ заставить git удалить файлы .orig после того, как слияние будет очищено? - person Tom DeMille; 15.01.2010
comment
Вам нужно сделать git checkout --ours .. . важен; передача имени файла (в данном случае всего каталога) позволяет выбрать один из двух различных режимов работы checkout, один из которых переключает ветви, а другой перемещает файлы из индекса в рабочую копию. Согласен, это очень запутанно. Вы также можете сделать git checkout --ours -- <filename>, чтобы извлекать отдельный файл за раз. - person Brian Campbell; 15.01.2010
comment
Общий способ git для очистки лишних файлов в рабочем дереве - это git clean -f kernel.org/pub/software/scm/git/docs/git-clean.html (будьте осторожны, это опасная команда). git clean удалит все файлы, о которых git не знает; -f необходимо, потому что git clean опасно, поэтому вам нужна опция force, чтобы сообщить ему, что вы действительно это имеете в виду. Если у вас есть файлы в вашем .gitignore, которые вы тоже хотите очистить (например, .o файлы), вы можете использовать git clean -xf. И если вы тоже хотите получить каталоги, git clean -fd или git clean -xfd. - person Brian Campbell; 15.01.2010
comment
(кстати, для последующего вопроса обычно лучше опубликовать новый вопрос; может быть сложно уместить ответ в комментариях, и ответ будет скрыт по умолчанию, поэтому другие люди не смогут его найти так же легко) - person Brian Campbell; 15.01.2010
comment
Чувак, ты должен быть «мерзавцем-консультантом», который моя компания наняла бы :) Еще раз спасибо, твое объяснение. после оформления заказа очень освещает - person Tom DeMille; 15.01.2010
comment
@Tom На самом деле, я доступен как консультант по Git, если вам все еще интересно. У меня довольно большой опыт работы с Git и Subversion в нескольких различных рабочих процессах, а также опыт автоматизации сборки и непрерывной интеграции с использованием BuildBot. Если вы хотите связаться со мной, мой адрес электронной почты - лямбда (в) продолжение (точка) org - person Brian Campbell; 20.01.2010
comment
Отличный ответ. Однако спрашивающий сказал: у меня есть несколько локальных файлов, я извлекаю их из удаленной ветки, и возникают конфликты. Это означает перебазирование, не так ли? что означает, что в конце достаточно добавить разрешенные файлы и просто - продолжить. Мы здесь не обязуемся. - person Martin Klosi; 20.07.2013
comment
That's very important, and easy to miss ‹- Ага. Я скучал по этому - person James Webster; 13.08.2013
comment
Обратите внимание, что для перебазирования ours и theirs противоположны тому, что вы могли подумать. - person ErikE; 23.09.2015
comment
Есть ли способ справиться с файлами, которые были deleted by us? При попытке выполнить git commit --ours . я получаю ошибку: путь 'file.ext' не имеет нашей версии, что понятно, но есть ли способ сделать commit и delete file.ext без использования git rm? - person Gabrielius; 24.11.2015
comment
Фу, я запустил git checkout --ours ., и он без предупреждения перезаписал все мои незафиксированные локальные изменения. Совершенно другое поведение, чем git checkout branchname. Пришлось восстанавливать изменения с трудом. Могу я предложить вам поставить предупреждение о таком поведении? См. Также: Вот безумная идея: если у вас есть безобидное действие и опасное действие, не помечайте их одной и той же командой. - person machine yearning; 30.11.2017
comment
@machineyearning Согласен. Некоторое время назад подобная проблема меня тоже обожгла, но я нашел простое решение: я просто всегда фиксирую все нетривиальное (то есть более нескольких минут работы). Тогда там git reflog есть все, что есть. Перед тем, как нажимать, мне нужно очистить свои коммиты, но я все равно просматриваю все изменения, так что накладных расходов практически нет. - person maaartinus; 02.05.2018
comment
@BrianCampbell, мой сэр, сделал мой день с этим - person user3753693; 15.05.2020

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

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

git checkout --theirs -- .

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

person VonC    schedule 21.09.2012