Что действительно делает git fetch?

Теперь я хочу объединить удаленную ветвь, назвав ее origin/branch1, с моей локальной ветвью branch1, так как мой партнер нажал новую фиксацию на ветку1 на пульте после нашего последнего слияния, и я не совершал его с момента его last commit и хотите получить обновление от этой фиксации. Я использовал следующие команды:

$ git fetch origin branch1
Compressing...
*branch branch1 ->FETCH_HEAD
$ git merge origin/branch1
Already up-to-date

Это не то, что я намеревался. На мой взгляд, прежде чем делать это, я использовал fetch, чтобы получить то, что добавил мой партнер, и обновил удаленную ветвь origin/branch1. Тем не менее, "Уже обновленный" означает, что я не смог получить обновления в моей локальной ветке1. Затем я проверил значение sha1 origin/branch1 на

$ git ls-remote origin

и обнаружил, что он сохранил устаревшее значение старого commit после того, как мы слились в прошлый раз. Он сообщает, что git fetch origin branch1 не может обновить origin/branch1. Я сделал еще один эксперимент, когда мой партнер создал в своей ветке другую ветку с именем "branch2" и нажал фиксацию в ветке2 на удаленное начало. Затем я все еще использовал

$ git fetch origin branch2
Compressing...
$ git merge origin/branch2
No branch named "origin/branch2"

"Сжатие" сказал мне, что первая команда загрузила что-то в branch2 по происхождению успешно, однако вторая команда сообщила мне, что не было ветки с именем origin/branch2! Таким образом, я пришел к выводу, что не может git fetch origin branchname обновлять origin/branchname локально и не создавать удаленную ветвь, если она не существует.

После того, как я заменил git fetch origin branch# на git fetch origin, все git merge работали так, как я ожидал.

Однако я часто вижу комбинацию

$ git fetch remote branch-name
$ git merge remote/branch-name

Итак, мой вопрос в чем разница между git fetch remote и git fetch remote branch-name? И в каких условиях мне удастся позволить ему работать по своему желанию этой комбинацией?

Ответ 1

Если вам нужно знать, что именно делает git fetch или какая-либо другая команда git, просто префикс его с помощью GIT_TRACE=1, поэтому он даст вам вывод трассировки с любыми другими командами, которые вызывают, например

$ GIT_TRACE=1 git fetch origin master
03:08:15.704945 git.c:348               trace: built-in: git 'fetch' 'origin' 'master'
03:08:15.706183 run-command.c:347       trace: run_command: 'ssh' '[email protected]' 'git-upload-pack '\''FOO/BAR.git'\'''
03:08:16.006394 run-command.c:347       trace: run_command: 'rev-list' '--objects' '--stdin' '--not' '--all' '--quiet'
03:08:16.013096 run-command.c:347       trace: run_command: 'rev-list' '--objects' '--stdin' '--not' '--all'
03:08:16.013625 exec_cmd.c:129          trace: exec: 'git' 'rev-list' '--objects' '--stdin' '--not' '--all'
03:08:16.016617 git.c:348               trace: built-in: git 'rev-list' '--objects' '--stdin' '--not' '--all'
From github.com:FOO/BAR
 * branch            master     -> FETCH_HEAD
03:08:16.153070 run-command.c:347       trace: run_command: 'gc' '--auto'
03:08:16.153748 exec_cmd.c:129          trace: exec: 'git' 'gc' '--auto'
03:08:16.157704 git.c:348               trace: built-in: git 'gc' '--auto'

который в основном делает ssh на удаленном хосте, запустив git-upload-pack, который отправляет объекты, упакованные обратно в git-fetch-pack, который получает отсутствующие объекты из другого репозитория.

В man git-upload-pack мы можем прочитать:

Вызывается git fetch-pack, узнает, какие объекты отсутствует в другой стороне, и отправляет их после упаковки.

И в man git-fetch-pack мы можем прочитать:

Вызывает git-upload-pack в возможно удаленном репозитории и просит передать объекты, отсутствующие в этом репозитории, для обновления названных глав. Список локаций, доступных локально, обнаруживается путем сканирования локальной refs/hierarchy и отправляется на git-upload-pack на другом конце.


Чтобы ответить на вопрос, разница между git fetch remote и git fetch remote branch-name заключается в том, что, когда вы не указываете параметр <refspec> (например, ветвь), он извлекает все ветки и/или теги (ссылки: см. git ls-refs) из одного или нескольких других репозиториев вместе с объектами, необходимыми для завершения их историй. По умолчанию загружаются только те теги, которые доступны доступным объектам (например, вы получаете только теги, которые указывают на интересующие вас ветки).

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

Ответ 2

запускающий git-upload-pack, который отправляет объекты, упакованные обратно в git-fetch-pack который получает отсутствующие объекты из другого репозитория.

Вы можете увидеть больше о git fetch-pack с Git 2.19 (Q3 2018), поскольку " git fetch-pack --all " используется для ненужного сбоя при просмотре аннотированного тега, который указывает на объект, отличный от коммита.

См. Commit c12c9df (13 июня 2018 года) Кирилла Смелкова (navytux).
Помощник: Юнио С Хамано (gitster).
См. Фиксацию e9502c0 (11 июня 2018 года) Джеффом Кингом (peff).
Помощник: Юнио С Хамано (gitster).
(Слияние Junio C Hamano - gitster - в совершении 0079732, 28 июня 2018 года)

Fetch-pack --all стал нарушен в отношении необычных тегов в 5f0fc64 (fetch-pack: исключить ложные сообщения об ошибках, 2012-09-09, Git v1.8.0) и был исправлен только недавно в e9502c0 (fetch-pack: don Не пытайтесь получить значения отслаивания с помощью --all, 2018-06-11).

fetch-pack: не пытайтесь извлекать значения отслаивания с помощью --all

Когда " fetch-pack --all " видит тег-к-blob на удаленном компьютере, он пытается извлечь сам тег ("refs/tags/foo") и очищенное значение, которое удаленные объявления (" refs/tags/foo^{} ").
Запрос объекта, на который указывает последний, может вызвать загрузку пакета, чтобы жаловаться на "не наш ref", поскольку он не помечен очищенными объектами OUR_REF (если они не были на вершине некоторого другого ref).

Возможно, upload-pack должен отмечать эти очищенные объекты. Но это никогда не было в прошлом, так как клиенты обычно просто запрашивали тег и ожидали получить очищенную стоимость вместе с ней.
И что работает " git fetch ", а также более старые версии " fetch-pack --all ".

Позвольте явно проверить все соответствующие случаи с 4 тегами объектов, указывающих на

  • 1) блоб,
  • 2) дерево,
  • 3) фиксация и
  • 4) другие объекты тегов.

Сами ссылки на объекты тега ссылаются из обычного пространства имен refs/tags/*.

До того, как e9502c0 (Git 2.19) fetch-pack --all потерпел неудачу, например, таким образом:

    .../git/t/trash directory.t5500-fetch-pack/fetchall$ git ls-remote ..
    44085874...        HEAD
    ...
    bc4e9e1f...        refs/tags/tag-to-blob
    038f48ad...        refs/tags/tag-to-blob^{} # peeled
    520db1f5...        refs/tags/tag-to-tree
    7395c100...        refs/tags/tag-to-tree^{} # peeled

    .../git/t/trash directory.t5500-fetch-pack/fetchall$ git fetch-pack --all ..
    fatal: A git upload-pack: not our ref 038f48ad...
    fatal: The remote end hung up unexpectedly