Как устанавливается начало/HEAD?

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

Итак, мой вопрос заключается в том, при каких обстоятельствах происходит перемещение origin/HEAD?

EDIT:

Я ценю ответы о том, как перемещать начало /HEAD, но меня интересует то, что "органично" перемещает его, вне меня явно говорит ему об этом.

Например, когда я переключаю ветки, git делает HEAD точкой в ​​ветке, которую я проверяю, поэтому я удивлен, что origin/HEAD не перемещается таким же образом.

Ответ 1

Обратите внимание, что ваш вопрос показывает немного недоразумения. origin/HEAD представляет собой ветвь по умолчанию на удаленном, то есть HEAD, которая в этом удаленном репозитории вы вызываете. Когда вы переключаете ветки в свое репо, вы не влияете на это. То же самое верно для удаленных веток; вы можете иметь master и origin/master в своем репо, где origin/master представляет локальную копию ветки master в удаленном репозитории.

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

Я думаю, что приведенное выше ответы на то, что вы на самом деле хотели узнать, но чтобы продолжить и ответить на заданный вами вопрос... origin/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, как указано выше, а затем на самом деле устанавливает начало /HEAD, чтобы указать на соответствующую удаленную ветвь.

Ответ 2

Это ваша настройка как владельца вашего локального репо. Измените его так:

git remote set-head origin some_branch

И origin/HEAD укажет на вашу ветку вместо мастера. Это применимо только к вашему репо, а не к другим. По умолчанию он укажет на мастер, если только что-то еще не было настроено на дистанционном репо.

Ручная запись для удаленной настройки предоставляет некоторую хорошую информацию об этом.

Изменить: подчеркнуть: без вашего объяснения, единственный способ "переместить" - это случай, например переименование главной ветки, Думаю, это считается "органическим". Итак, я бы сказал, органично, что он не двигается.

Ответ 3

Что перемещает начало /HEAD "органично"?

  • 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 указывает на удаленный компьютер, только в том, что он делает hash, который он, наконец, имеет: поэтому он просто надеется, что выбрал имя ветки, указывающее на тот же хэш

Ответ 4

Отказ от ответственности: это обновление ответа Jefromi, которое я пишу, чтобы сохранить любопытное некоторое время.

Я тщетно пытался воспроизвести (в 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.

(Commit 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.

(Commit 9196a2f8bd46d36a285bdfa03b4540ed3f01f671 от 8 ноября 2013 года, найденный с git log --grep="ambiguous" --grep="HEAD" --all-match)

Изменить (спасибо torek):

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

Это означает, что если вы используете Git v1.8.4.3 или новее, вы не должны сталкиваться с какой-либо проблемой двусмысленно-удаленного HEAD.

Ответ 5

Помните, что существуют два независимых git repos, о которых мы говорим. Ваше местное репо с вашим кодом и удаленным запуском в другом месте.

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

На вашем компьютере (локальном репо) нет бизнеса, изменяющего указатель HEAD на удаленном репозитории git. Например, он может принадлежать другому разработчику.

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

Итак, что бы "органично" обновить происхождение /HEAD? Это будет активность на удаленном репозитории git. Не ваше местное репо.

Люди упомянули

git symbolic-ref HEAD refs/head/my_other_branch

Обычно это используется, когда на сервере используется общий центральный репозиторий git для использования командой разработчиков. Это будет команда, выполняемая на удаленном компьютере. Вы увидите это как активность на удаленном репозитории git.

Ответ 6

Запустите следующие команды из git CLI:

# move to the wanted commit
git reset --hard <commit-hash> 

# update remote
git push --force origin <branch-name>