Включает ли "git fetch --tags" "git fetch"?
Хороший и простой вопрос - является ли функция "git fetch" строгим подмножеством git fetch --tags
?
Т.е. если я бегу git fetch --tags
есть ли причина немедленно бежать git fetch
сразу после?
Как насчет git pull
а также git pull --tags
? Такая же ситуация?
6 ответов
Примечание: начиная с git 1.9/2.0 (первый квартал 2014 года), git fetch --tags
извлекает теги в дополнение к тому, что выбирается той же командной строкой без опции.
Смотрите коммит c5a84e9 Майкла Хаггерти (mhagger):
Раньше "Фетч"
--tags
"опция считалась эквивалентной указанию refspecrefs/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 (2 квартал 2015 года) git pull --tags
является более надежным:
Смотрите коммит 19d122b Пола Тана ( pyokagan
), 13 мая 2015 г.
(Объединено Юнио С Хамано - gitster
- в комитете cc77b99, 22 мая 2015 г.)
pull
: Удалить--tags
ошибка в случае слияния кандидатовС 441ед41 (
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
)
(Объединено Юнио С Хамано - gitster
- в коммите 9fcd144, 26 октября 2016 г.)
fetch
: используйте "быстрый"has_sha1_file
для тега следованияПри выборке с пульта дистанционного управления, у которого есть много тегов, которые не имеют отношения к ветвям, за которыми мы следуем, мы использовали слишком много циклов, когда проверяли, существует ли объект, на который указывает тег (который мы не собираемся выбирать!), В нашем хранилище слишком осторожно
Этот патч учит fetch использовать HAS_SHA1_QUICK, чтобы пожертвовать точностью ради скорости, в случаях, когда мы можем быть сумасшедшими с одновременной перепаковкой.
Вот результаты из включенного сценария perf, который устанавливает ситуацию, аналогичную описанной выше:
Test HEAD^ HEAD
----------------------------------------------------------
5550.4: fetch 11.21(10.42+0.78) 0.08(0.04+0.02) -99.3%
Это относится только к ситуации, когда:
- У вас есть много пакетов на стороне клиента, чтобы сделать
reprepare_packed_git()
дорогой (самая дорогая часть - поиск дубликатов в несортированном списке, который в настоящее время является квадратичным).- Вам нужно большое количество ссылок на теги на стороне сервера, которые являются кандидатами для автоматического следования (то есть, что у клиента нет). Каждый из них запускает перечитывание каталога пакета.
- При нормальных обстоятельствах клиент будет автоматически следовать этим тегам, и после одной большой выборки (2) больше не будет истинным.
Но если эти теги указывают на историю, которая не связана с тем, что клиент извлекает иначе, то он никогда не будет автоматически следовать, и эти кандидаты будут влиять на нее при каждой выборке.
Примечание: этот ответ действителен только для git v1.8 и старше.
Большая часть этого была сказана в других ответах и комментариях, но вот краткое объяснение:
git fetch
извлекает все заголовки веток (или все указанные в параметре конфигурации remote.fetch), все необходимые коммиты и все теги, которые доступны из этих веток. В большинстве случаев все теги достижимы таким образом.git fetch --tags
извлекает все теги, все необходимые для них коммиты. Он не будет обновлять заголовки веток, даже если они достижимы из выбранных тегов.
Резюме: Если вы действительно хотите быть полностью в курсе, используя только выборку, вы должны сделать оба.
Это также не "вдвое медленнее", если только вы не имеете в виду ввод текста в командной строке, в этом случае псевдонимы решают вашу проблему. По сути, нет никаких накладных расходов при выполнении двух запросов, поскольку они запрашивают разную информацию.
Я собираюсь ответить на это сам.
Я определил, что есть разница. "git fetch --tags" может содержать все теги, но не вводить новые коммиты!
Оказывается, нужно сделать это, чтобы быть полностью "современным", то есть реплицировать "git pull" без слияния:
$ git fetch --tags
$ git fetch
Это позор, потому что это в два раза медленнее. Если бы только у "git fetch" была возможность сделать то, что он обычно делает, и ввести все теги.
Общая проблема здесь в том, что git fetch
принесет +refs/heads/*:refs/remotes/$remote/*
, Если какой-либо из этих коммитов имеет теги, эти теги также будут выбраны. Однако, если есть теги, недоступные для какой-либо ветви на удаленном компьютере, они не будут выбраны.
--tags
опция переключает refspec на +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
В большинстве ситуаций git fetch
должен делать то, что вы хотите, а именно: "получить что-то новое из удаленного репозитория и поместить его в локальную копию, не объединяя с локальными филиалами". git fetch --tags
делает именно это, за исключением того, что он не получает ничего, кроме новых тегов.
В этом смысле, git fetch --tags
ни в коем случае не является надмножеством git fetch
, На самом деле все с точностью до наоборот.
git pull
Конечно, это не что иное, как обертка для git fetch <thisrefspec>; git merge
, Рекомендуется привыкнуть к ручному git fetch
и git merge
прежде чем совершить прыжок в git pull
просто потому, что это помогает вам понять, что git pull
делает в первую очередь.
При этом отношения точно такие же, как с git fetch
, git pull
это надмножество git pull --tags
,
git fetch upstream --tags
работает просто отлично, он получит только новые теги и не получит никакой другой базы кода.