Каково точное значение "наших" и "их" в git?

Это может звучать как слишком простой вопрос, но я искал ответы, и теперь я в замешательстве, чем раньше.

Что означают "наши" и "их" в git при объединении моей ветви с другой веткой? Обе ветви "наши".

В конфликте слияний всегда отображается "наша" верхняя из двух версий?

Всегда ли наша относится к ветви, на которую указывал HEAD, когда началось слияние? Если так, то почему бы не использовать ясную притяжательную ссылку, такую ​​как "текущая ветвь", вместо использования притяжательного местоимения, такого как "наше", которое является неоднозначным (поскольку обе ветви технически являются нашими)?

Или просто использовать название ветви (вместо того, чтобы сказать "наш", просто сказать "местный мастер" или что-то подобное)?

Самая запутанная часть для меня, если я укажу в файле.gitattributes определенной ветви. Допустим, в тестовой ветке у меня есть следующий файл.gitattributes:

config.xml merge=ours

Теперь я проверяю и указываю HEAD, чтобы освоить, а затем слить в тесте. Поскольку мастер - наш, а тестовые.gitattributes не проверены, будет ли он иметь эффект? Если это действительно имеет эффект, так как мастер теперь "наш", то что произойдет?

10 ответов

Решение

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

В конечном счете, во время git merge ветвь "наш" относится к ветке, в которую вы сливаетесь:

git checkout merge-into-ours

и ветвь "их" относится к (единственной) ветке, которую вы объединяете:

git merge from-theirs

и здесь "наши" и "их" имеют некоторый смысл, поскольку, хотя "их", вероятно, в любом случае принадлежит вам, "их" не тот, на котором вы были, когда бежали git merge,

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

git checkout ours
git merge 1234567

где вы объединяетесь по необработанному коммит-идентификатору. Хуже того, вы можете даже сделать это:

git checkout 7777777    # detach HEAD
git merge 1234567       # do a test merge

в этом случае не используются имена веток!

Я думаю, что это мало поможет здесь, но на самом деле, в gitrevisions синтаксис, вы можете ссылаться на отдельный путь в индексе по номеру во время конфликтующего слияния

git show :1:README
git show :2:README
git show :3:README

Стадия № 1 является общим предком файлов, стадия № 2 - версия целевой ветви, а стадия № 3 - версия, с которой вы объединяетесь.


Причина, по которой понятия "наши" и "их" меняются местами во время rebase в том, что rebase работает, выполняя серию "черриков", в анонимную ветвь (режим отсоединенного HEAD). Целевая ветвь - это анонимная ветвь, а ветвь слияния - это ваша исходная ветвь (pre-rebase): так что "--ours" означает, что анонимный ребаз строит, а "--theirs" означает "наша ветвь перебазируется",


Что касается записи gitattributes: это может иметь эффект: "наш" действительно означает "использовать этап #2" внутри. Но, как вы заметили, в то время он на самом деле не был на месте, поэтому он не должен иметь здесь никакого эффекта... ну, если только вы не скопируете его в рабочее дерево перед началом работы.

Кроме того, кстати, это относится ко всем нашим и их использованию, но некоторые из них находятся на уровне всего файла (-s ours для стратегии слияния; git checkout --ours во время конфликта слияния), а некоторые - по частям (-X ours или же -X theirs во время -s recursive слияния). Что, вероятно, не поможет ни с какой путаницей.

Я никогда не придумал лучшего названия для них. И: см . Ответ VonC на другой вопрос, где git mergetool вводит еще больше имен для них, называя их "локальный" и "удаленный"!

Я знаю, что на этот вопрос уже дан ответ, но эта проблема смущала меня так много раз, что я создал небольшой справочный сайт, чтобы помочь мне вспомнить: https://nitaym.github.io/ourstheirs/

Вот основы:

Объединяет:

$ git checkout master 
$ git merge feature

Если вы хотите выбрать версию в master:

$ git checkout --ours codefile.js

Если вы хотите выбрать версию в feature:

$ git checkout --theirs codefile.js

Rebases:

$ git checkout feature 
$ git rebase master 

Если вы хотите выбрать версию в master:

$ git checkout --ours codefile.js

Если вы хотите выбрать версию в feature:

$ git checkout --theirs codefile.js

(Это для полных файлов, конечно)

" Наши " в Git относятся к оригинальной рабочей ветке, которая имеет авторитетную / каноническую часть истории Git.

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

Это может показаться заменой людям, которые не знают, что делают перебазирование (например, git rebase) фактически приостанавливает вашу работу (которая принадлежит им), чтобы воспроизвести каноническую / основную историю, которая принадлежит нам, потому что мы отклоняем наши изменения как стороннюю работу.

Документация для git-checkout было дополнительно разъяснено в Git >=2.5.1 согласно f303016 совершить:

--ours--theirs

При проверке путей из индекса, проверьте этап № 2 ("наш") или № 3 ("их") для необработанных путей.

Обратите внимание, что во время git rebase а также git pull --rebase "наши" и "их" могут выглядеть поменяно местами; --ours дает версию из ветки, на которую перебазируются изменения, а --theirs дает версию из ветки, которая содержит вашу работу, которая перебазируется.

Это потому что rebase используется в рабочем процессе, который обрабатывает историю на удаленном сервере как общую каноническую, а работу, выполняемую в ветви, которую вы перебазируете, - как стороннюю работу для интеграции, и вы временно принимаете на себя роль хранителя каноническая история во время перебазирования. Как хранитель канонической истории, вы должны просматривать историю с удаленного ours (то есть "наша общая каноническая история"), а то, что вы делали на своей боковой ветке, theirs (т. е. "работа одного участника поверх него").

За git-merge это объясняется следующим образом:

наш

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

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

их

Это противоположность нашей.

Более подробно, здесь объясняется, как их использовать:

Механизм слияния (git merge а также git pull команды) позволяет выбирать стратегии слияния с -s вариант. Некоторые стратегии также могут иметь свои собственные варианты, которые можно передать, дав -X<option> аргументы git merge и / или git pull,


Так что иногда это может сбивать с толку, например:

  • git pull origin master где -Xours наш местный, -Xtheirs это их (удаленная) ветка
  • git pull origin master -r где -Xours их (удаленный), -Xtheirs это наше

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

Аналогично для git merge стратегии (-X ours а также -X theirs).

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

Надеюсь, это поможет!

PS - Дайте чек также по ссылке в ответе Нитая

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

Так что, если вы используете ветку release/2.5 и объединяете в нее функцию / новые кнопки ветки, то контент, найденный в release/2.5, - это то, к чему относится наш, и контент, найденный в функции / новые кнопки, - то, к чему они относятся. к. Во время действия слияния это довольно просто.

Единственная проблема, к которой относится большинство людей - это случай перебазирования. Если вы сделаете повторную базу вместо обычного слияния, роли поменяются местами. Как это? Ну, это вызвано исключительно тем, как работает перебазировка. Подумайте о rebase, чтобы работать так:

  1. Все коммиты, которые вы сделали со времени последнего пулла, перемещены в собственную ветку, назовем ее BranchX.
  2. Вы извлекаете заголовок вашей текущей ветки, отбрасывая все локальные изменения, которые у вас были, но таким образом извлекаете все изменения, которые другие подтолкнули к этой ветке.
  3. Теперь каждый коммит в BranchX выбирается по порядку, от старого к новому в вашей текущей ветке.
  4. BranchX снова удаляется и, следовательно, никогда не будет отображаться ни в одной истории.

Конечно, это не совсем то, что происходит, но это хорошая модель для меня. И если вы посмотрите на 2 и 3, вы поймете, почему роли поменялись местами. Начиная с 2, ваша текущая ветка теперь является веткой с сервера без каких-либо ваших изменений, так что это наша (ветка, в которой вы находитесь). Внесенные вами изменения теперь относятся к другой ветви, отличной от вашей текущей (BranchX), и, таким образом, эти изменения (несмотря на то, что вы сделали изменения) принадлежат им (другая ветвь, используемая в вашем действии).

Это означает, что если вы объединяетесь и хотите, чтобы ваши изменения всегда побеждали, вы должны сказать git всегда выбирать "наши", но если вы сделаете ребаз и хотите, чтобы все ваши изменения всегда побеждали, вы скажете git всегда выбирать "их".

Я размещу здесь свою памятку, потому что мне нужно возвращаться сюда снова и снова.

СЦЕНАРИЙ 1. Обычный разработчик: вы разработчик, который не может слиться сmaster и играть с feature только ветки.

Случай 1: хозяин - король. Вы хотите освежить свойfeature ветка (= переустановить на master), потому как master содержит новые обновления зависимостей, и вы хотите перезаписать свои скромные изменения.

git checkout master
git pull

git checkout feature
git rebase -X ours master

Случай 2: вы король. Вы хотите переустановить свойfeature ветвь к masterизменения. Но вы сделали больше, чем ваши коллеги, и хотите использовать собственные изменения в приоритете.

git checkout master
git pull

git checkout feature
git rebase -X theirs master

ВАЖНО: Как видите, нормальные разработчики должны предпочесть rebase и повторяйте это каждое утро как зарядку / кофе.

СЦЕНАРИЙ 2. Сенсей-слияние: Вы руководитель группы и хотите объединить другие ветви и отправить объединенный результат непосредственно мастеру.master это ветка, которую вы измените.

Случай 1: мастер - король Вы хотите объединить стороннюю ветку, ноmaster является приоритетом. feature это ветка, которую сделал ваш старший.

git checkout feature
git pull

git checkout master
git merge -X ours master

Случай 2: новые изменения - король Когда ваш старший разработчик выпустил крутойfeature и вы хотите перезаписать старое дерьмо в master ветвь.

git checkout feature
git pull

git checkout master
git merge -X theirs master

ПОМНИТЕ: чтобы в полночь вспомнить, какой из них выбрать: master является oursВСЕГДА. А такжеtheirs это feature что их сделали.

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

      <<<<<<< HEAD
        foo = 12;
=======
        foo = 22;
>>>>>>> [your commit message]

Разрешить с помощью 'mine' -> foo = 12

Разрешить, используя 'их' -> foo = 22

--oursявляетсяHEADи--theirsявляетсяREBASE_HEAD,MERGE_HEAD, илиCHERRY_PICK_HEAD. Я считаю, что гораздо проще использовать ссылки на коммиты напрямую.

При перебазировании:

      git restore HEAD thing.js         # use what the current branch has
git restore REBASE_HEAD thing.js  # use what the other branch has

При слиянии:

      git restore HEAD thing.js        # use what the current branch has
git restore MERGE_HEAD thing.js  # use what the other branch has

При сборе вишни:

      git restore HEAD thing.js              # use what the current branch has
git restore CHERRY_PICK_HEAD thing.js  # use what the other branch has

От git checkoutиспользование:

-2, --ours            checkout our version for unmerged files
-3, --theirs          checkout their version for unmerged files
-m, --merge           perform a 3-way merge with the new branch

При разрешении конфликтов слияния вы можете сделать git checkout --theirs some_file, а также git checkout --ours some_file сбросить файл на текущую версию и входящие версии соответственно.

Если вы сделали git checkout --ours some_file или же git checkout --theirs some_file и хотел бы сбросить файл до 3-х сторонней версии файла слияния, вы можете сделать git checkout --merge some_file,

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

Другие вопросы по тегам