Як встановлюється походження / HEAD?


144

У мене створено відділення для відстеження посилання на походження. git checkout <branchname>переходить на цю гілку, і git statusпокаже мені, як далеко попереду чи позаду моєї гілки є походження, але я здивований, що origin/HEADвсе ще вказує на origin/master, а неorigin/<branchname>

Отже, моє питання полягає в тому, за яких обставин рухається походження / HEAD?

Редагувати:

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

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


Зауважте, що це питання стосується локальних символічних посилань на пульти, наприклад refs/origin/HEAD. Йдеться не про те, як встановлюється власне символічне посилання сховища HEAD.
clacke

Відповіді:


173

Спочатку зауважте, що у вашому запитанні є трохи непорозумінь. origin / HEAD представляє гілку за замовчуванням на віддаленому пристрої , тобто HEAD, який знаходиться у тому віддаленому сховищі, яке ви викликаєте походженням. Коли ви перемикаєте гілки в репо, ви на це не впливаєте. Те саме стосується віддалених відділень; у вас може бути masterі origin/masterу вашому репо, де origin/masterпредставлена ​​локальна копія masterгілки у віддаленому сховищі.

origin HEAD зміниться лише в тому випадку, якщо ви або хтось інший насправді змінить його у віддаленому сховищі , що в основному ніколи не трапиться - ви хочете, щоб гілка за замовчуванням публічна репо залишалася постійною, на стабільній гілці (можливо, майстер). origin / HEAD - локальний номер, що представляє локальну копію HEAD у віддаленому сховищі. (Повна його назва - refs / remotes / origin / HEAD.)

Я думаю, що вище відповідає на те, що ви насправді хотіли знати, але продовжувати і відповідати на запитання, яке ви прямо задали ... походження / HEAD встановлюється автоматично, коли ви клонуєте сховище, і це стосується цього. Як не дивно, що він не встановлений такими командами, git remote update- я вважаю, що єдиний спосіб зміниться - це якщо ви вручну зміните його. (Під зміною я маю на увазі іншу гілку; очевидно, що вона вказує на зміни, якщо ця гілка зміниться, що може статися під час отримання / потягу / віддаленого оновлення.)


Редагувати : Проблема, обговорена нижче, була виправлена ​​в Git 1.8.4.3 ; переглянути це оновлення .


Хоча є крихітний застереження. HEAD - це символічний перегляд, який вказує на гілку замість безпосередньо на фіксацію, але протоколи віддаленої передачі git передають лише звіт про відкликання. Таким чином, Git знає SHA1 зобов’язання, на яке вказує HEAD, та всіх інших посилань; Потім він повинен вивести значення HEAD, знайшовши гілку, яка вказує на ту саму комісію. Це означає, що якщо трапляються дві гілки, то це неоднозначно. (Я вважаю, що він забирає майстер, якщо це можливо, потім повертається до першого алфавіту.) Ви побачите це, про що повідомляється у висновку git remote show origin:

$ git remote show origin
* remote origin
  Fetch URL: ...
  Push  URL: ...
  HEAD branch (remote HEAD is ambiguous, may be one of the following):
    foo
    master

Як не дивно, хоча поняття HEAD, надруковане таким чином, зміниться, якщо все зміниться на пульті дистанційного управління (наприклад, якщо foo буде видалено), воно фактично не оновиться refs/remotes/origin/HEAD. Це може призвести до дійсно дивних ситуацій. Скажіть, що у наведеному вище прикладі походження / HEAD насправді вказувало на foo, а відділення foo початку було видалено. Тоді ми можемо зробити це:

$ git remote show origin
...
HEAD branch: master
$ git symbolic-ref refs/remotes/origin/HEAD
refs/remotes/origin/foo
$ git remote update --prune origin
Fetching origin
 x [deleted]         (none)     -> origin/foo
   (refs/remotes/origin/HEAD has become dangling)

Тож хоча віддалене шоу знає, що HEAD є господарем, воно нічого не оновлює. Відстояну гілку foo правильно обрізають, і HEAD стає звисаючим (вказує на неіснуючу гілку), і вона все ще не оновлює її, щоб вказати на майстер. Якщо ви хочете виправити це, використовуйте git remote set-head origin -a, що автоматично визначає HEAD начала як вище, а потім фактично встановлює origin / HEAD, щоб вказати на відповідну віддалену гілку.


@jefromi Чудова відповідь! Лише зауваження: ви пишете, що HEAD є символічним відривом, вказуючи на гілку, а не безпосередньо на [[]] , але, можливо, варто згадати "відокремлений стан HEAD" для повноти.
jub0bs

2
@Jubobs Дякую! Якщо моя відповідь потребує оновлення, будь ласка, не соромтесь просто її відредагувати - це, безумовно, заощадить людям час прочитати короткий підсумок того, як все насправді працює, а не розбиратись у тому, що було правдою два роки тому та що справжнє зараз .
Каскабель

прочитав це принаймні 5 разів і досі не розумієш цього
krb686

7
git remote set-head origin -aзробив роботу для мене
Shujito

75

Це ваше налаштування як власника місцевого репо. Змініть його так:

git remote set-head origin some_branch

І походження / HEAD вкаже на вашу гілку замість господаря. Це стосується лише вашого репо, а не для інших. За замовчуванням він вказуватиме на майстер, якщо інше не було налаштовано на віддаленому репо.

Ручний вхід для віддаленої установки встановлює хорошу інформацію про це.

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


1
Наголос редагування тут не зовсім правильний. Це також може змінитися, якщо ви клонуєтесь з локальної копії, яка не знаходиться на головній гілці.
mphair

Я не вважаю , клон «переміщення», але я думаю , ми можемо погодитися на це :)
EIS

24

Що рухає походження / ГОЛОВА "органічно"?

  • git clone встановлює його один раз на місце, де знаходиться HEAD
    • він служить гілкою за замовчуванням для оформлення замовлення після клонування git clone

Що представляє HEAD за походженням?

  • у голих сховищах (часто сховищах "на серверах") він служить маркером для гілки за замовчуванням, оскільки git cloneвикористовує її таким чином
  • у неочищених сховищах (локальних або віддалених) це відображає поточну касу сховища

Що визначає походження / HEAD?

  • git clone виймає і встановлює його
  • Було б сенс, якщо git fetchоновлення буде як будь-яка інша довідка, але це не так
  • git remote set-head origin -a виймає і встановлює його
    • корисно оновити місцеві знання про те, що віддалений вважає "гілкою за замовчуванням"

Дрібниці

  • origin/HEAD також можна встановити будь-яке інше значення, не зв’язуючись з пультом: git remote set-head origin <branch>
    • Я не бачу жодного корисного випадку для цього, крім тестування
  • на жаль, нічого не в змозі встановити HEAD на пульті
  • старіші версії git не знали, на яку гілку HEAD вказує на пульті дистанційного керування, лише яка фішка хеша вона, нарешті, є: тож вона просто сподівається обрати назву гілки, що вказує на той самий хеш

Я втратив посилання origin/HEADі ваше рішення допомогло. Дякую!
java_dude

Я не згоден з git fetchйого оновленням, оскільки це дозволяє налаштувати (локальний) ярлик. Цитуючи документ: "Мати гілку за замовчуванням для віддаленого не потрібно, але дозволяє вказати ім'я віддаленого замість конкретної гілки". Було б дивно, якби віддалена зміна оновила б локально налаштовані ярлики.
Micha Wiedenmann

@MichaWiedenmann Чому це буде локально налаштований ярлик? Для локально налаштованого ярлика origin/HEADце неправильне ім’я. І це git cloneвикористовує віддалене ім'я як за замовчуванням для "локально налаштованої гілки", і це суперечить. У неочищених сховищах навіть не має сенсу використовувати струм віддаленого HEAD.
Роберт Сімер

10

Відмова : це оновлення відповіді Джефромі , яку я пишу, щоб зберегти цікавих на деякий час.

Я марно намагався повторити (в Git 2.0.1) remote HEAD is ambiguousповідомлення, яке Єфромі згадує у своїй відповіді; тому я трохи копав (клонувавши https://github.com/git/git та шукаючи журнал). Раніше це було

Determining HEAD is ambiguous since it is done by comparing SHA1s.

In the case of multiple matches we return refs/heads/master if it
matches, else we return the first match we encounter. builtin-remote
needs all matches returned to it, so add a flag for it to request such.

(Комітет 4229f1fa325870d6b24fe2a4c7d2ed5f14c6f771, від 27 лютого 2009 р., Знайдено в git log --reverse --grep="HEAD is ambiguous")

Однак неясність, про яку йдеться, з тих пір була скасована :

One long-standing flaw in the pack transfer protocol used by "git
clone" was that there was no way to tell the other end which branch
"HEAD" points at, and the receiving end needed to guess.  A new
capability has been defined in the pack protocol to convey this
information so that cloning from a repository with more than one
branches pointing at the same commit where the HEAD is at now
reliably sets the initial branch in the resulting repository.

(Комітет 9196a2f8bd46d36a285bdfa03b4540ed3f01f671, від 8 листопада 2013 р., Знайдено в git log --grep="ambiguous" --grep="HEAD" --all-match)

Редагувати (спасибі Торека ):

$ git name-rev --name-only 9196a2f8bd46d36a285bdfa03b4540ed3f01f671
tags/v1.8.4.3~3

Це означає, що якщо ви використовуєте Git v1.8.4.3 або пізнішої версії , вам не слід стикатися з жодною неоднозначною проблемою віддаленого HEAD.


1
Виходячи з тегів у джерелі git, це виправлення застосовується до git версії 1.8.4.3 та пізнішої версії.
torek

@RobertSiemer Я не впевнений, але я думаю, що так.
jub0bs

8

Пам'ятайте, про це ми говоримо два незалежних репортажі. Ваше місцеве репо з кодом та пульт дистанційного керування десь в іншому місці.

Ви маєте рацію, змінюючи гілку, HEAD вказує на вашу поточну гілку. Все це відбувається на вашій місцевій гіт-репо. Не віддалене репо, яке могло бути власником іншого розробника, або розташовувалося на вашому офісі, або github, або іншому каталозі файлової системи, і т. Д. ...

На вашому комп'ютері (місцевий репо) немає жодної справи, яка змінює вказівник HEAD на віддаленому git repo. Наприклад, може належати інший розробник.

Ще одне - те, що ваш комп'ютер називає походженням / XXX, - це розуміння комп'ютером стану віддаленого пристрою під час останнього вибору.

То що б "органічно" оновило походження / HEAD? Це була б діяльність на віддаленому git repo. Не ваше місцеве репо.

Люди згадували

git символічно-ref HEAD refs / head / my_other_branch

Зазвичай це використовується, коли на сервері є спільна центральна програма git repo для використання командою розробників. Це була б команда, виконана на віддаленому комп'ютері. Ви б бачили це як діяльність на віддаленому git repo.


1
Вибачте, якщо я трохи повторююся. Я просто хочу зазначити той факт, що git - це система управління розподіленою версією, і тому два репозитори незалежні.
Пабло Морін

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