Как установить origin / HEAD? - PullRequest
       6

Как установить origin / HEAD?

125 голосов
/ 12 января 2012

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

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

EDIT:

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

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

Ответы [ 6 ]

151 голосов
/ 12 января 2012

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

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

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


Редактировать : проблема, описанная ниже, была исправлена ​​в Git 1.8.4.3 ; см это обновление .


Однако есть крошечная оговорка. HEAD - это символьная ссылка, указывающая на ветку, а не непосредственно на коммит, но протоколы удаленной передачи git сообщают только о фиксациях для ссылок. Так что Git знает SHA1 коммита, на который указывает HEAD и все другие ссылки; Затем он должен определить значение HEAD, найдя ветку, которая указывает на тот же коммит. Это означает, что если две ветви указывают на это, это неоднозначно. (Я полагаю, что он выбирает master, если это возможно, затем возвращается к первому в алфавитном порядке.) Вы увидите это в выходных данных 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. Это может привести к действительно странным ситуациям. Скажем, что в приведенном выше примере origin / HEAD фактически указывает на foo, а ветка foo origin была затем удалена. Затем мы можем сделать это:

$ 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 становится висящим (указывая на несуществующую ветвь), и она все еще не обновляет ее, чтобы указывать на master. Если вы хотите это исправить, используйте git remote set-head origin -a, который автоматически определяет HEAD источника как указано выше, а затем фактически устанавливает origin / HEAD для указания на соответствующую удаленную ветвь.

62 голосов
/ 12 января 2012

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

git remote set-head origin some_branch

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

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

Редактировать: подчеркнуть: без вашего ведома, единственный способ, которым он "переместился бы", был бы, например, , переименовывающий основную ветвь , который я не считаю "органическим".Так что я бы сказал, что органически он не двигается.

20 голосов
/ 02 апреля 2015

Что движет оригами / ГОЛОВКОЙ "органически"?

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

Что представляет собой HEAD в начале координат?

  • в пустых репозиториях (часто в репозиториях «на серверах») он служит маркером для ветви по умолчанию, поскольку git clone использует его таким образом
  • в не-пустых хранилищах (локальных или удаленных) отражает текущую проверку хранилища

Что определяет происхождение / заголовок?

  • git clone выбирает и устанавливает
  • будет иметь смысл, если git fetch обновит его как любую другую ссылку, но это не
  • git remote set-head origin -a выбирает и устанавливает его
    • полезно для обновления локальных знаний о том, что удаленное устройство считает «веткой по умолчанию»

Пустяки

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

Отказ от ответственности : это обновление к ответу Джефроми , который я пишу, чтобы спасти любопытного некоторое время.

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

Редактировать (спасибо torek ):

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

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

8 голосов
/ 12 января 2012

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

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

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

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

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

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

git symbolic-ref HEAD refs / head / my_other_branch

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

1 голос
/ 16 июля 2019

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

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

# update remote
git push --force origin <branch-name> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...