Включает ли "git fetch --tags" "git fetch"? - PullRequest
244 голосов
/ 30 июля 2009

Хороший и простой вопрос - является ли функция git fetch строгим подмножеством git fetch --tags?

т.е. если я запускаю git fetch --tags, есть ли причина немедленно запустить git fetch сразу после этого?

А как насчет git pull и git pull --tags? Та же ситуация?

Ответы [ 6 ]

158 голосов
/ 16 декабря 2013

Примечание: начиная с git 1.9 / 2.0 (1 квартал 2014 года) , git fetch --tags выбирает теги в дополнение к , которые выбираются той же командной строкой без опции.

См. коммит c5a84e9 от Майкл Хаггерти (mhagger) :

Ранее параметр fetch "--tags" считался эквивалентным указанию refspec

refs/tags/*:refs/tags/*

в командной строке; в частности, это привело к игнорированию конфигурации remote.<name>.refspec.

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

Если пользователь хочет получить только тегов, тогда все еще возможно указать явный refspec:

git fetch <remote> 'refs/tags/*:refs/tags/*'

Обратите внимание, что документация до 1.8.0.3 была неоднозначной в отношении этого аспекта поведения "fetch --tags".
Commit f0cb2f1 (2012-12-14) fetch --tags сделал документацию соответствующей старому поведению.
Этот коммит изменяет документацию, чтобы соответствовать новому поведению (см. Documentation/fetch-options.txt).

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


Начиная с Git 2.5 (второй квартал 2015 года) git pull --tags более устойчив:

См. коммит 19d122b от Пол Тан (pyokagan) , 13 мая 2015 г.
(Объединено с Junio ​​C Hamano - gitster - в commit cc77b99 , 22 мая 2015 г.)

pull: удалить --tags ошибка в случае отсутствия кандидатов на слияние

С тех пор 441ed41 ("git pull --tags": ошибка с более качественным сообщением., 2007-12-28, Git 1.5.4+), git pull --tags выведет другое сообщение об ошибке, если git-fetch не вернул ни одного кандидата на слияние:

It doesn't make sense to pull all tags; you probably meant:
       git fetch --tags

Это потому, что в то время git-fetch --tags переопределяет любой настроил refspecs, и, следовательно, не было бы кандидатов на слияние. Таким образом, было введено сообщение об ошибке, чтобы избежать путаницы.

Однако с c5a84e9 (fetch --tags: извлечение тегов в дополнение к прочее, 2013-10-30, Git 1.9.0+), git fetch --tags дополнительно получит теги на любой настроенный refspecs.
Следовательно, если не возникает ситуация с кандидатами на слияние, это не потому, что было установлено --tags. Таким образом, это специальное сообщение об ошибке теперь не имеет значения.

Чтобы избежать путаницы, удалите это сообщение об ошибке.


С Git 2.11+ (4 квартал 2016 г.) git fetch быстрее.

См. коммит 5827a03 (13 октября 2016 г.) Джефф Кинг (peff) .
(Объединено с Junio ​​C Hamano - gitster - в коммит 9fcd144 , 26 октября 2016 г.)

fetch: используйте «быстрый» has_sha1_file для следования тега

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

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

Вот результаты из включенного сценария perf, который устанавливает ситуацию, аналогичную описанной выше:

Test            HEAD^               HEAD
----------------------------------------------------------
5550.4: fetch   11.21(10.42+0.78)   0.08(0.04+0.02) -99.3%

Это относится только к ситуации, когда:

  1. У вас много пакетов на стороне клиента, что делает reprepare_packed_git() дорогим (самая дорогая часть - поиск дубликатов в несортированном списке, который в настоящее время является квадратичным).
  2. Вам необходимо большое количество ссылок на теги на стороне сервера, которые являются кандидатами для автоматического следования (т. Е. У клиента нет). Каждый из них запускает перечитывание каталога пакета.
  3. При нормальных обстоятельствах клиент будет автоматически следовать этим тегам, и после одной большой выборки (2) больше не будет истинным.
    Но если эти теги указывают на историю, которая не связана с тем, что клиент извлекает, то она никогда не будет автоматически следовать, и эти кандидаты будут влиять на нее при каждом извлечении.

Git 2.21 (февраль 2019), кажется, ввел регрессию, когда config remote.origin.fetch равен , а не по умолчанию ('+refs/heads/*:refs/remotes/origin/*')

fatal: multiple updates for ref 'refs/tags/v1.0.0' not allowed
130 голосов
/ 30 июля 2009

Примечание: этот ответ действителен только для git v1.8 и старше.

Большая часть этого была сказана в других ответах и ​​комментариях, но вот краткое объяснение:

  • git fetch извлекает все заголовки веток (или все, указанные параметром конфигурации remote.fetch), все необходимые для них коммиты и все теги, которые доступны из этих веток. В большинстве случаев все теги доступны таким образом.
  • git fetch --tags извлекает все теги, все необходимые для них коммиты. Он не обновит заголовки веток, даже если они достижимы из выбранных тегов.

Резюме: Если вы действительно хотите быть в курсе всех событий, используя только выборку, вы должны сделать оба.

Это также не «вдвое медленнее», если только вы не имеете в виду ввод текста в командной строке, и в этом случае псевдонимы решают вашу проблему. По сути, нет никаких накладных расходов при выполнении этих двух запросов, поскольку они запрашивают разную информацию.

48 голосов
/ 30 июля 2009

Я собираюсь ответить на это сам.

Я определил, что есть разница. "git fetch --tags" может содержать все теги, но не вводить новые коммиты!

Оказалось, что это нужно сделать, чтобы быть полностью "современным", то есть реплицировать "git pull" без слияния:

$ git fetch --tags
$ git fetch

Это позор, потому что он в два раза медленнее. Если бы только «git fetch» ​​имел возможность делать то, что обычно делает, и вводят все теги.

31 голосов
/ 19 февраля 2013

Общая проблема здесь в том, что git fetch получит +refs/heads/*:refs/remotes/$remote/*. Если какой-либо из этих коммитов имеет теги, эти теги также будут выбраны. Однако, если есть теги, недоступные для какой-либо ветви на удаленном компьютере, они не будут выбраны.

Опция --tags переключает ссылку на +refs/tags/*:refs/tags/*. Вы могли бы попросить git fetch захватить оба. Я уверен, что просто сделаю git fetch && git fetch -t, вы бы использовали следующую команду:

git fetch origin "+refs/heads/*:refs/remotes/origin/*" "+refs/tags/*:refs/tags/*"

И если вы хотите сделать это по умолчанию для этого репо, вы можете добавить второй refspec к выборке по умолчанию:

git config --local --add remote.origin.fetch "+refs/tags/*:refs/tags/*"

Это добавит вторую fetch = строку в .git/config для этого пульта.


Я потратил некоторое время на поиски способа справиться с этим для проекта. Это то, что я придумал.

git fetch -fup origin "+refs/*:refs/*"

В моем случае я хотел эти функции

  • Возьмите все головы и метки с пульта, поэтому используйте refspec refs/*:refs/*
  • Перезаписывать локальные ветки и теги без ускоренной перемотки вперед + до refspec
  • При необходимости перезаписать текущую извлеченную ветку -u
  • Удалить ветки и метки, отсутствующие в удаленном -p
  • И заставь быть уверенным -f
10 голосов
/ 30 июля 2009

В большинстве случаев git fetch должен делать то, что вы хотите, а именно: «получить что-то новое из удаленного репозитория и поместить его в локальную копию без слияния с локальными филиалами». git fetch --tags делает именно это, за исключением того, что он не получает ничего, кроме новых тегов.

В этом смысле git fetch --tags никоим образом не является надмножеством git fetch. На самом деле все с точностью до наоборот.

git pull, конечно, не что иное, как обертка для git fetch <thisrefspec>; git merge. Рекомендуется привыкнуть к ручному git fetch ing и git merge ing до перехода к git pull просто потому, что это помогает вам понять, что в первую очередь делает git pull.

При этом отношения точно такие же, как и у git fetch. git pull это расширенный набор git pull --tags.

1 голос
/ 16 января 2018
git fetch upstream --tags

работает просто отлично, он получает только новые теги и не получает никакой другой базы кода.

...