Если я получу "git rm <file>", когда получу конфликт "оба добавлены", удалит ли это файл из моей ветви или всего репо? - PullRequest
0 голосов
/ 07 июня 2018

Вот ситуация:

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

Я хочу отказаться от своей версии файлов - я не хочу выдвигать их вверх.

Будетиспользуя git rm <file>, удалите мою версию файлов или вообще удалите файлы из репозитория / проекта?

Как лучше всего справиться с этим (я читал о наших / их, но это не даетсмысл для меня)?

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

TL; DR

Поскольку вы хотите отказаться от своей версии файла, вы хотите:

git checkout --theirs <file>
git add <file>

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

Long, но, пожалуйста, прочитайте его

Учитывая, что терминология Git представляет собой проблему (и она существует для многих людей), вам, вероятно, следует изучить терминологию.Итак, давайте посмотрим на это.

Во-первых, не думайте, что ваш репозиторий содержит files .Это так, но если думать об этом таким образом, вы никуда не денетесь - это все равно, что пытаться думать о своем доме как о розетках, дверных ручках и так далее.Это неправильный уровень, чтобы думать об этом.В вашем доме есть комнат , а в комнатах с дверями есть дверные ручки, розетки, в которые вы подключаете приборы, зарядное устройство и т. Д.Так же, как интересный уровень «дома» - это «комнаты», интересный уровень хранилища равен коммитов .(В отличие от дома - ну, в любом случае, любого практического дома - вы просто продолжаете добавлять новые коммиты в хранилище, более или менее навсегда, не выбрасывая любых старых. Ну, в основном! Трудно по-настоящему избавиться от коммитов, но это можно сделать.)

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

Большинство коммитов довольно просты: у них есть коллекция файлов - снимок дерева источника -и некоторые метаданные, такие как «этот коммит был сделан AU Thor". Одним из ключевых элементов метаданных, которые есть почти у каждого коммита, является хеш-идентификатор его родительского коммита. Это коммит, который был там до того, как г-н Тор (или кто бы то ни было) сделалновый. (Например, представьте, что это дверь в предыдущую комнату.) Итак, коммит:

  • содержит некоторые метаданные - некоторую дополнительную информацию, которая не является частью файлов в коммит, плюс
  • полный снимок каждого файла.

Git находит коммит по его хеш-идентификатору , которыйэто такая большая, на первый взгляд случайная вещь, которую печатает git log:

$ git log
commit 3e5524907b43337e82a24afbc822078daf7a868f
Author: Junio C Hamano <...

Эти хэш-идентификаторы являются истинными именами каждого коммита. Каждый коммит получает уникальный. Они совершенно бесполезны для большинства людей,но Git использует их, чтобы найти все данные, которые идут с каждым коммитом. Родитель этого конкретного коммита e66e8f9be8af90671b85a758b62610bd1162de2d, так что этот коммит - этот 3e5524907... говорит, в частности, my parent is e668ef9be8....на эти большие уродливые идентификаторы. К счастью, как люди, мы можем в основном игнорируйте их.)

Когда вы запускаете git checkout <em>somebranch</em>, Git превращает имя ветви в хэш-идентификатор, а затем извлекает все файлы из этого коммита, чтобы вы могли использовать их илиработать над ними.Он также устанавливает свою идею текущего коммита на то, чем является этот хэш-идентификатор, и устанавливает текущее имя ветки на имя, которое вы ему дали.Выполнение git status скажет вам on branch <em>somebranch</em>, так что теперь вы «включили» эту ветвь, что отчасти означает, что у вас есть определенный хеш-идентификатор фиксации.

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

Git makeэти снимки из его промежуточной области , которую он также называет index или иногда cache .Это всего лишь три названия для одной и той же вещи: либо потому, что это так важно (что это такое), либо потому, что первое имя, которое использовал Линус, «index», было таким плохим именем (на мой взгляд, это не здорово, но на самом деле это не так)это плохо).Эта площадка обычно почти невидима: вы даже не смотрите на нее напрямую.Вместо этого вы выполняете свою работу в том, что Git называет ваше рабочее дерево или рабочее дерево или рабочий каталог .В этой области файлы - это просто файлы - это не странные специальные объекты Git.

В области index / staging и в коммитах файлы странные и особенные: в основном, они сжаты для сохраненияпространство.В коммитах они также доступны только для чтения: вы не можете изменить ни один из существующих коммитов, даже один бит.Вы можете перезаписать файл, который находится в индексе, используя git add, чтобы скопировать обычный файл из области рабочего дерева.Вот как вы выполняете свои изменения: вы работаете с файлом в рабочем дереве, затем запускаете git add <em>file</em>.

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

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

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

Вторая особая вещь, которая происходит во время этогоконфликтное слияние заключается в том, что индекс - помните, это промежуточная область, место, где вы строите свой следующий коммит слияния, - расширяется!Обычно ваш индекс содержит только одну копию каждого файла.Но когда вы объединяетесь, ваш индекс содержит до трех копий каждого конфликтующего файла!Вы можете иметь три README.md файла одновременно.(Я предполагаю, что конфликт имеет отношение README.md. Возможно, файл имеет другое имя, но все работает одинаково.)

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

Ваше рабочее дерево не может выполнить этот трюк "несколько версий одного файла", и ваш возможный Коммит может содержать только один README.md.Таким образом, это специальное состояние индекса, в котором содержится более одного файла, , которое вам нужно исправить.Когда вы закончите слияние README.md, у вас будет выбор: один README.md в индексе или no README.md в индексе.Какой бы выбор вы ни сделали, когда вы запустите git commit, Git зафиксирует это в новом коммите.

Вот о чем связан вопрос и ответ.Индекс содержит обе версии файла: ваши и их.Вы можете:

  • Используйте рабочее дерево для создания правильного или объединенного файла и git add результат.Это перезаписывает все конфликтующие множественные версии README.md, так что в индексе есть только одна README.md.

  • Используйте git checkout --ours для извлечения вашей версии README.md из индексав дерево работы.В индексе все еще есть все версии, но теперь файл рабочего дерева - ваша версия.

  • Используйте git checkout --theirs, чтобы извлечь их версию формы README.mdиндекс в рабочем дереве.Как и прежде, в индексе по-прежнему есть все версии, но теперь файл рабочего дерева их версия.

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

  • или, вы можете запустить git rm на файл.Это удаляет все версии из индекса, поэтому теперь индекс имеет нет README.md.Если вы закончили разрешать все конфликты, теперь вы можете git commit;этот новый коммит не имеет README.md.Как мы уже видели, это не влияет на любой предыдущий коммит, но это означает, что вы объявили, что правильный способ объединить ваши README.md и их README.md должен был полностью удалить файл.

    Если это неправильный ответ - если вы хотите сохранить их версию, например - не делайте этого.

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

...--o--o--o   <-- yourfix (HEAD)
      \
       o--o--o   <-- origin/theirfix

, и вы запустили git merge origin/theirfix, получили конфликт слияния, разрешили его и зафиксировали, вы получите:

...--o--o--o---M   <-- yourfix (HEAD)
      \       /
       o--o--o   <-- origin/theirfix

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

И, поскольку M запоминает тот же самый идентификатор хеша коммита как origin/theirfix, теперь безопасно для вас git push коммит M в Git overв origin и попросите origin изменить свой собственный theirfix (который ваш Git вызывает origin/theirfix), чтобы он указывал на M, так как M также запоминает их предыдущий коммит.Git называет это операцией fast-forward , когда вы запускаете git push, но давайте оставим эту терминологию для других вопросов.

0 голосов
/ 07 июня 2018

Этот ответ можно составить, прочитав здесь и здесь .В Git-слиянии ветвь ours обычно относится к целевой ветви, в которую происходит слияние.И theirs обычно относится к единственной ветви, которая сливается с целью.В зависимости от того, является ли ваша ветвь с версиями вновь добавленных файлов, которые вы хотите сохранить, целевой или отдельной веткой, вы можете выполнить одно из следующих действий после возникновения конфликта слияния:

git checkout --ours path/to/some/file
git checkout --theirs path/to/some/file

Как вы правильно указали, если вы сделаете git rm <file>, вы удалите обе версии файла, возможно, не то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...