Яке точне значення "наших" та "їхніх" в git?


323

Це може здатися занадто елементарним питанням, але я шукав відповіді, і зараз я більше заплутався, ніж раніше.

Що означає "наше" та "їхнє" в git, коли об'єднують мою гілку в іншу гілку? Обидві гілки - "наші".

У конфлікті злиття чи "наше" завжди відображається у верхній частині двох версій?

Чи завжди "наші" посилаються на галузь, на яку вказував HEAD, коли почалося злиття? Якщо так, то чому б не використати чітке присвійне посилання на зразок "поточна галузь" замість використання присвійного займенника типу "наш", який є відносно неоднозначним (оскільки обидві гілки технічно наші)?

Або просто використовувати назву філії (замість того, щоб сказати "наша", просто скажіть "місцевий господар" чи таке)?

Найбільш заплутаною для мене частиною є те, якщо я вказую у файлі .gitattributes певної гілки. Скажімо, у тестовій галузі я маю такий .gitattributes файл:

config.xml merge=ours

Тепер я перевіряю і вказую HEAD на оволодіння, а потім зливаюся в тесті . Так як господар наш, а тест на «S .gitattributes не перевірив, буде чи він навіть мати ефект? Якщо це матиме ефект, оскільки господар зараз "наш", то що буде?

Відповіді:


374

Я підозрюю, що вас тут плутають, оскільки це принципово заплутано. Щоб зробити щось гірше, весь наш / їхній матеріал перемикає ролі (стає назад), коли ви робите ребауз.

В кінцевому рахунку, під час 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полягає в тому, що робота по ребайзі здійснюється, роблячи серію вишеньки, в анонімну гілку (режим окремої HEAD). Цільова гілка - це анонімна гілка, і гілка злиття з вашою є оригінальною гілкою (попередньою реструктуризацією): тому "--ours" означає, що анонімне одне ребауз будується, тоді як "- їх" означає ", щоб наша гілка була відновлена" .


Щодо запису gitattributes: він може мати ефект: "наш" насправді означає "використовувати етап №2" внутрішньо. Але, як ви зазначаєте, він фактично не встановлений на той час, тому він не повинен мати ефекту тут ... ну, хіба що, якщо ви не скопіюєте його до робочого дерева перед початком роботи.

Також, до речі, це стосується всіх наших та їхніх цілей використання, але деякі знаходяться на цілому рівні файлів ( -s oursдля стратегії злиття; git checkout --oursпід час конфлікту злиття), а деякі - по деталях ( -X oursабо -X theirsпід час -s recursiveзлиття). Що, мабуть, не допомагає жодної плутанини.

Я ніколи не придумав кращого імені для цих, хоча. І: див . Відповідь VonC на інше питання, де git mergetoolпредставлено ще більше назв для них, називаючи їх "локальними" та "віддаленими"!


28
+1. Про наших , і тому суть назад під час перебазування, дивіться також: stackoverflow.com/a/2960751/6309 і stackoverflow.com/a/3052118/6309
VonC

1
Дві речі "зливаються" один з одним. Коли відбувається злиття, обидві сторони зливаються "один у одного". Я вважаю, що було б некоректно сказати, що одна з двох сторін "не зливається ні в що". Якщо немає імен гілок (як ви вказуєте), то тут включаються імена фіксації (ви можете сказати "7777777" та "1234567's" замість "our" та "njihovo"). Я розумію, що відбувається під час перезавантаження, і не вважаю, що це зовсім заплутано. Я думаю, що "ГОЛАД" та "Вхід" працюватимуть краще, ніж "наші" та "їхні", тому що завжди є "ГОЛОВА" (незалежно від того, буде вона відокремлена чи ні).
CommaToast

15
Я здогадуюсь, оскільки голова - це місце розуму, яке є джерелом ідентичності, яке є джерелом "я", то має сенс думати про те, що вказує HEAD на "моє" ("наше"), оскільки Я здогадуюсь, що я і ГОЛОВА робить два). Якщо нічого більше, це буде просто хорошим мнемічним приладом.
CommaToast

1
Попри це, я все ще люблю робити фізичну копію всього репо, перш ніж робити щось, як перезавантаження ...: D
CommaToast

3
"в такому випадку немає ніяких імен гілок!" ... Тому він повинен використовувати замість цього коментар / хеш. Що б воно не могло дістати. Практично все було б краще, ніж "наше" та "їхнє". Цікаво, скільки тисяч чорт-годин випарувалася ця плутанина. відповідь git на "найпокутніший розбір" C ++;)
Jarrod Smith

49

" Наше " в 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- наше

Отже, другий приклад протилежний 1-му, тому що ми випускаємо свою гілку поверх віддаленої, тому наша початкова точка є віддаленою, і наші зміни трактуються як зовнішні.

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


2
ця відповідь здається застарілою => "git merge --ours" не є правильним варіантом
Олександр Міллз

@AlexanderMills Відповідь не говорити про git merge, але git pullі в git checkoutякості прикладу. Якщо ви хочете використовувати цей параметр git merge, ви повинні використовувати -X ours. Ви все ще можете використовувати --oursсинтаксис для git checkout. Відповідь я уточнив далі.
kenorb

46

Я знаю, що на це відповіли, але це питання мене бентежило стільки разів, коли я створив невеликий довідковий веб-сайт, щоб допомогти мені запам'ятати: https://nitaym.github.io/ourstheirs/

Ось основи:

Злиття:

$ git checkout master 
$ git merge feature

Якщо ви хочете вибрати версію в master:

$ git checkout --ours codefile.js

Якщо ви хочете вибрати версію в feature:

$ git checkout --theirs codefile.js

Відшкодування:

$ git checkout feature 
$ git rebase master 

Якщо ви хочете вибрати версію в master:

$ git checkout --ours codefile.js

Якщо ви хочете вибрати версію в feature:

$ git checkout --theirs codefile.js

(Це, звичайно, для повних файлів)


1
Цей веб-сайт дуже корисний. Стиль діаграми та кольорові слова роблять веб-сайт набагато простішим для розуміння, ніж відповіді ТА. Дякую.
Рон

10
  • Наше : Це галузь, на якій Ви зараз перебуваєте.
  • Їх : Це інша галузь, яка використовується у вашій дії.

Отже, якщо ви перебуваєте у випуску гілки / 2.5 та об’єднуєте в неї функцію гілки / нові кнопки , то вміст, як знайдено у випуску / 2.5, - це те, на що посилається наш, а вміст, знайдений у функції / нові кнопки, - це те, що стосується їх до. Під час дії злиття це досить прямо.

Єдина проблема, з якою стикається більшість людей, - це випадок перегляду даних . Якщо ви робите повторну базу замість звичайного злиття, ролі поміняються. Як це? Ну, це спричинено виключно тим, як працює перезавантаження. Подумайте, як така база може працювати так:

  1. Усі зобов’язання, які ви зробили з моменту останнього перетягування, переміщені у власну гілку, назвемо її BranchX .
  2. Ви оформили замовлення голови своєї поточної філії, відкинувши будь-які місцеві зміни, але ви отримали всі зміни, які інші підштовхнули до цієї гілки.
  3. Тепер кожен випуск на BranchX вибирається вишневим для того, щоб він був новим для вашої поточної галузі.
  4. BranchX знову видаляється, і тому ніколи не з’явиться в історії.

Звичайно, це насправді не те, що відбувається, але це приємна модель розуму для мене. І якщо ви подивитесь на 2 і 3, то зрозумієте, чому зараз поміняються ролі. Станом на 2, ваша поточна гілка зараз є гілкою з сервера без будь-яких змін, тому це наше (гілка, на якій ви перебуваєте). Зміни, які ви внесли, тепер є в іншій гілці, яка не є вашою поточною ( BranchX ), і ці зміни (незважаючи на зміни, які ви внесли), є їхніми (інша гілка, яка використовується у вашій дії).

Це означає, що якщо ви зливаєтесь і хочете, щоб ваші зміни завжди перемагали, ви б сказали git завжди вибирати "наше", але якщо ви перезавантажуєтесь і хочете, щоб усі ваші зміни завжди вигравали, ви скажете git завжди обирати "їх".


3

Я знаю, що це не пояснює значення, але я створив собі маленьке зображення, як посилання, щоб нагадати, який з них використовувати:

введіть тут опис зображення

Сподіваюся, це допомагає!

PS - Вкажіть перевірку також за посиланням у відповіді Нітей 🙂


3

Я викладу тут свою пам’ятку, бо мені доведеться повертатися сюди знову і знову.

СЦЕНАРІЯ 1. Нормальний розробник: Ви розробник, який не може злитися masterі повинен грати featureлише з гілками.

Випадок 1: господар - король. Ви хочете оновити свою featureгілку (= rebase to 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і ви хочете замінити старий s ** t у masterгілці.

git checkout feature
git pull

git checkout master
git merge -X theirs master

ПАМ'ЯТАЙТЕ: Для того, щоб пам'ятати , опівночі , який один на вибір: masterє oursЗАВЖДИ. І theirsце featureте, що їх зробили.


2

З 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хочете відновити файл до тривимірної версії файлу злиття, ви можете це зробити git checkout --merge some_file.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.