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

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

В режиме по умолчанию git pull является сокращением для git fetch, за которым следует git merge FETCH_HEAD.

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

8 ответов

Решение

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 вместо того, чтобы ссылаться на какую-либо одну ссылку, вместо того, чтобы называть вещи.

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

Как уже упоминалось в ответе Джонатана, 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 по существу соответствует удаленной версии ветви, которая в настоящее время извлечена.

Я только что обнаружил и использовал 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 для удаления копии с сервера после того, как исправление было выбрано в текущей ветке. (Я предполагаю, что на сервере есть хороший чистый тэг с фиксацией, содержащий все исправления ошибок!)

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

На самом деле... не всегда учитывая, что с Git 2.29 (4 квартал 2020 г.) " git fetch"(человек) узнал--no-write-fetch-head возможность избежать написания FETCH_HEAD файл.

См. Commit 887952b (18 августа 2020 г.), автор Junio ​​C Hamano (gitster).
(Слияние Junio ​​C Hamano -gitster- в коммите b556050, 24 августа 2020 г.)

fetch: опционально разрешить отключение FETCH_HEAD Обновить

Подписано: Деррик Столи

Если вы запускаете выборку, но записываете результат в ветвях удаленного отслеживания, и либо если вы ничего не делаете с полученными ссылками (например, вы просто зеркалируете), либо если вы всегда работаете из ссылок удаленного отслеживания (например, вы извлекаете, а затем объединяете origin/branchname отдельно), вы можете обойтись без FETCH_HEAD совсем.

Учить " git fetch"(человек) параметр командной строки"--[no-]write-fetch-head".

  • По умолчанию нужно писать FETCH_HEAD, и этот параметр в первую очередь предназначен для использования с "--no-"префикс, чтобы переопределить это значение по умолчанию, потому что нет соответствия fetch.writeFetchHEAD переменная конфигурации, чтобы отключить значение по умолчанию (в этом случае может потребоваться положительная форма, чтобы победить его).

Обратите внимание, что в разделе "--dry-run" Режим, FETCH_HEADникогда не пишется; в противном случае вы увидите список объектов в файле, которых у вас на самом деле нет.

Проходящий --write-fetch-head не заставляет [git fetch](https://github.com/git/git/blob/887952b8c680626f4721cb5fa57704478801aca4/Documentation/git-fetch.txt)<sup>([man](https://git-scm.com/docs/git-fetch))</sup> записать файл.

fetch-optionsтеперь включает в свою справочную страницу:

--[no-]write-fetch-head

Напишите список удаленных ссылок, полученных в FETCH_HEAD файл прямо под $GIT_DIR.
Это значение по умолчанию.

Проходящий --no-write-fetch-headиз командной строки указывает Git не записывать файл.
Под--dry-run вариант, файл никогда не записывается.


Также обратите внимание на Git 2.29 (4 квартал 2020 г.), FETCH_HEAD теперь всегда считывается из файловой системы независимо от используемого бэкэнда ref, так как его формат намного богаче, чем у обычных ссылок, и записывается непосредственно " git fetch"(мужчина) простым файлом..

См. Фиксацию e811530, фиксацию 5085aef, фиксацию 4877c6c, фиксацию e39620f (19 августа 2020 г.) от Han-Wen Nienhuys (hanwen).
(Слияние Junio ​​C Hamano -gitster- в коммите 98df75b, 27 августа 2020 г.)

refs: читать FETCH_HEAD а также MERGE_HEAD в целом

Подписано: Хан-Вен Ниенхуйс

В FETCH_HEAD а также MERGE_HEADссылки должны храниться в файле, независимо от типа бэкэнда ref. Это потому, что они могут содержать больше, чем один реф.

Чтобы разместить их для альтернативных бэкэндов ссылок, прочтите их из файла в общем случае в refs_read_raw_ref().


В Git 2.29 (четвертый квартал 2020 г.) обновления для получения кода по требованию в лениво клонированных репозиториях.

См. Commit db3c293 (2 сентября 2020 г.) и commit 9dfa8db, commit 7ca3c0a, commit 5c3b801, commit abcb7ee, commit e5b9421, commit 2b713c2, commit cbe566a (17 августа 2020 г.) Джонатан Тан (jhowtan).
(Слияние Junio ​​C Hamano -gitster- в коммите b4100f3, 03 сен 2020)

fetch: нет FETCH_HEAD отображать, если --no-write-fetch-head

Подписано: Джонатан Тан

887952b8c6 ("fetch: опционально разрешить отключение FETCH_HEADupdate", 2020-08-18, Git v2.29.0 - слияние, указанное в пакете № 10), добавлена возможность отключения записи вFETCH_HEAD во время выборки, но не подавил "<source> -> FETCH_HEAD" сообщение при использовании этой способности.

В данном случае это сообщение вводит в заблуждение, потому что FETCH_HEAD не написано.

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

Поэтому подавите это сообщение, когда --no-write-fetch-head пройден (но не когда --dry-run установлено).

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

Я просто пытался вытащить ветку (исправление), которую я создал путем внесения изменений непосредственно из GitHub. Ветка появилась только на GH. Когда я попытался выполнить ag pull, ветка не появилась.

Я смог проверить ветку, используя:

      git fetch origin pull/2/head
git checkout -b <desired-branch-name> FETCH_HEAD

Позвольте мне внести свой вклад в это, если это возможно.

  1. На изображении я попросил УДАЛИТЬ, есть ли какие-то изменения в ФИЛИАЛЕ, над которым я работаю. FETCH сказал мне * ветка back_end -> FETCH_HEAD

  2. ТОГДА я попросил PULL, пытаясь перенести все НОВОЕ на REMOTE (GITHUB) в свою локальную ветку (у нее такое же имя back_end)

GIT сказал мне --->> FETCH_HEAD, что означает, что все уже было обновлено, и было что обновить из REMOTE BRANCH, та же информация, которую мне сообщила инструкция FETCH ранее.

Другие вопросы по тегам