Что означает FETCH_HEAD в Git?

222

git pull --help говорит:

В режиме по умолчанию git pullэто сокращение от которого git fetchследует git merge FETCH_HEAD.

Что это такое FETCH_HEADи что на самом деле сливается во время git pull?

Миша Морошко
источник
3
Примечание: начиная с git 1.8.4 (август 2013 г.), на git fetch origin masterсамом деле будут обновляться origin/master, а не только FETCH_HEAD. См. Stackoverflow.com/a/20967347/6309
VonC
Подробнее о git merge FETCH_HEAD(начиная с Git 2.5, 2-го квартала 2015 г.) см. Stackoverflow.com/a/30425991/6309
VonC

Ответы:

219

FETCH_HEADнедолговечный реф, для отслеживания того, что только что было получено из удаленного репозитория. git pullсначала вызывает git fetch, в нормальных случаях выборку ветки с пульта; FETCH_HEADуказывает на верхушку этой ветви (она хранит SHA1 коммита, как это делают ветви). git pullзатем вызывает git merge, сливаясь FETCH_HEADс текущей веткой.

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

Это немного похоже на обход git fetchбез аргументов (или git remote update), обновление всех ваших удаленных веток, затем запуск git merge origin/<branch>, но FETCH_HEADвместо этого внутреннее использование для ссылки на какой-либо отдельный ссылочный номер, вместо того, чтобы называть вещи.

Cascabel
источник
9
@Jefromi: извините, я думаю , вы не правы: насколько я понимаю, git fetchобновление (Слияния) все данные объекта из удаленного хранилища, а не только на бранч. Так что я не понимаю из вашего ответа, как git решает, на какую ветку указывать FETCH_HEAD. Я также не могу найти FETCH_HEADв документации git (определение, а не примеры). Существование FETCH_HEADвыглядит для меня больше как обходной путь, чтобы заставить git pullработать как-то .
Алексей
14
Алексей: FETCH_HEADсоответствует кончику удаленной ветви, указанному branch.<BRANCH>.mergeв конфигурации локального репозитория. Таким образом, хотя fetchон действительно извлекает все данные объекта из удаленного хранилища, FETCH_HEADон используется для указания того, куда продвинулась удаленная ветвь, отслеживаемая локальной ветвью. Так что, если вы находитесь в локальной masterветке и запускаете git fetch, и branch.master.mergeуказываете refs/heads/master, то FETCH_HEADбудет иметь то же значение, что и origin/masterсразу после операции выборки.
Жаворонки
4
@alexy FETCH_HEAD описывается во втором абзаце описания git fetch на его man-странице. Мой ответ правильный. И git fetch без аргументов обновляет все удаленные ветви для удаленного по умолчанию ... но это определенно не то же самое, что слияние.
Каскабель
4
Что делать, FETCH_HEADесли вы выбираете все удаленные ветви через git fetch -a?
Стиги
2
@stigi Подсказка удаленной ветки отслеживания, на которую указывает ваша текущая ветка в конфиге git. Пожалуйста, смотрите ответ жаворонка в комментарии выше.
Анкур Агарвал
19

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

Так что если я выдаю:

git fetch https://github.com/ryanmaxwell/Fragaria

FETCH_HEAD может содержать

3cfda7cfdcf9fb78b44d991f8470df56723658d3        https://github.com/ryanmaxwell/Fragaria

Если у меня настроено удаленное репо в качестве удаленной ветви отслеживания, то я могу следить за извлечением с помощью объединения ветви отслеживания. Если я не смогу, я могу объединить кончик последней выборки напрямую, используя FETCH_HEAD.

git merge FETCH_HEAD
Джонатан Митчелл
источник
1
Чтобы добавить мои 5 центов. Что меня смутило, так это то, что мой FETCH_HEAD стоял за последними коммитами, даже если делал новый выбор, который возвращал «без изменений» (в затмении). Думаю, причина в том, что все изменения, произошедшие с момента моей последней загрузки, были сделаны мной и были отправлены на сервер мной. Поэтому последующая выборка не имела ничего общего и даже не обновляла FETCH_HEAD. Я не уверен, является ли это недостатком реализации GIT или Eclipse Git.
Torge
11

Как упоминалось в ответе Джонатана , FETCH_HEAD соответствует файлу .git/FETCH_HEAD. Как правило, файл будет выглядеть так:

71f026561ddb57063681109aadd0de5bac26ada9                        branch 'some-branch' of <remote URL>
669980e32769626587c5f3c45334fb81e5f44c34        not-for-merge   branch 'some-other-branch' of <remote URL>
b858c89278ab1469c71340eef8cf38cc4ef03fed        not-for-merge   branch 'yet-some-other-branch' of <remote URL>

Обратите внимание, как отмечены все ветви, кроме одной not-for-merge. Нечетным является ветвь, которая была извлечена до извлечения. В итоге: FETCH_HEAD по существу соответствует удаленной версии ветви, которая в настоящее время извлечена.

Карстен Фюрманн
источник
9

Я только что открыл и использовал FETCH_HEAD. Я хотел локальную копию программного обеспечения с сервера, и я сделал

git fetch gitserver release_1

gitserverэто имя моей машины, на которой хранятся git-репозитории. release_1тег для версии программного обеспечения К моему удивлению, release_1тогда нигде не было возможности найти мою локальную машину. Я должен был напечатать

 git tag release_1 FETCH_HEAD 

завершить копирование помеченной цепочки коммитов (release_1) из удаленного хранилища в локальное. Fetch нашел удаленный тег, скопировал коммит на мой локальный компьютер, не создал локальный тег, но установил FETCH_HEADзначение коммита, чтобы я мог найти и использовать его. Затем я использовал FETCH_HEADдля создания локального тега, который соответствует тегу на пульте. Это практическая иллюстрация того, чтоFETCH_HEAD и как можно использовать, и может быть полезно для кого-то еще, задающегося вопросом, почему git fetch не делает то, что вы наивно ожидаете.

На мой взгляд, лучше избегать этой цели, и лучший способ добиться того, что я пытался сделать, это

git fetch gitserver release_1:release_1

то есть, чтобы получить release_1 и вызвать его release_1 локально. (Это источник: dest, см. Https://git-scm.com/book/en/v2/Git-Internals-The-Refspec. ; на всякий случай, если вы хотите дать ему другое имя!)

Вы можете использовать FETCH_HEADвремя от времени, хотя: -

git fetch gitserver bugfix1234
git cherry-pick FETCH_HEAD

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

Иван
источник
Интересная обратная связь. +1
VonC
Спасибо. Я отредактировал свое оригинальное сообщение, написанное, когда я впервые обнаружил FETCH_HEAD пару лет назад, так как оно, похоже, поощряло копирование тега с использованием FETCH_HEAD, а не синтаксиса source: dest для refspecs. Надеюсь, я дал лучший пример того, как можно использовать FETCH_HEAD.
Иван
3

git pull - это комбинация выборки с последующим слиянием. Когда происходит git fetch, он записывает главный коммит того, что он выбрал в FETCH_HEAD (просто файл с таким именем в .git), и эти коммиты затем объединяются в ваш рабочий каталог.

manojlds
источник
3
@manjolds, что ты имеешь в виду под " коммитом того, что он извлек"? Git получает все с fetch.
Алексей
@ Алексей из руководства по git: git-scm.com/docs/git-fetch : Имена
PJ_Finnegan