Чи включає "git fetch --tags" "git fetch"?


270

Приємне і просте запитання - чи є функція "git fetch" суворою підмножиною git fetch --tags?

Тобто, якщо я біжу git fetch --tags, чи є колись причина негайно бігти git fetchвідразу після цього?

Що про git pullі git pull --tags? Та ж ситуація?


11
Починаючи з Git 1..9 / 2.0 (1 квартал 2014 року), відповідь буде " так" . Дивіться мою відповідь нижче
VonC

3
Редактору, який "виправив мій текст" редагуванням - не обов'язково вказувати великі літери після дефісу чи абревіатури, тому ваше редагування було граматично неправильним, тому я його відхилив.
davidA

Відповіді:


176

Примітка. Починаючи з git 1.9 / 2.0 (Q1 2014) , git fetch --tagsвитягує теги на додаток до того, що отримується тим самим командним рядком без параметра.

Див зробити c5a84e9 по Michael Хаггерті (mhagger) :

Раніше --tagsваріант " " fetch вважався еквівалентним заданню refspec

refs/tags/*:refs/tags/*

у командному рядку; зокрема, це спричинило remote.<name>.refspecігнорування конфігурації.

Але не дуже корисно вибирати теги, не отримуючи також інших посилань, тоді як цілком корисно мати можливість отримувати теги на додаток до інших посилань.
Тому змініть семантику цього варіанту, щоб зробити останнє.

Якщо користувач хоче отримати лише теги, то все одно можна вказати чіткий перегляд:

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

Зауважте, що документація до 1.8.0.3 була неоднозначною щодо цього аспекту fetch --tagsповедінки.
Команда f0cb2f1 (2012-12-14) fetch --tagsзробила документацію відповідно до старої поведінки.
Ця фіксація змінює документацію відповідно до нової поведінки (див. Documentation/fetch-options.txt).

Попросіть, щоб усі теги були вилучені з віддаленого пристрою, крім того, що ще отримується .


Оскільки Git 2.5 (Q2 2015) git pull --tagsє більш надійним:

Див. Команду 19d122b від Paul Tan ( pyokagan) , 13 травня 2015 р.
(Об’єднав Хуніо С Хамано - gitster- у комітеті 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перекривали б будь-які налаштовані рефлекси, і, таким чином, не було б злиття кандидатів. Таким чином, повідомлення про помилку було введено для запобігання плутанини.

Однак, оскільки c5a84e9 ( fetch --tags: теги для отримання, крім інших матеріалів, 2013-10-30, Git 1.9.0+), git fetch --tagsотримає теги на додаток до будь-яких налаштованих рефлексив.
Отже, якщо не виникає ситуація з кандидатами на об'єднання, це не тому, що --tagsбуло встановлено. Таким чином, це спеціальне повідомлення про помилку зараз не має значення.

Щоб уникнути плутанини, видаліть це повідомлення про помилку.


З Git 2.11+ (Q4 2016) git fetchшвидше.

Див. Запис 5827a03 (13 жовтня 2016 р.) Від Джеффа Кінга ( peff) .
(Об’єднав Хуніо С Хамано - 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) , здається, ввів регрес , коли конфігурація remote.origin.fetchє НЕ один за замовчуванням ( '+refs/heads/*:refs/remotes/origin/*')

fatal: multiple updates for ref 'refs/tags/v1.0.0' not allowed

Git 2.24 (Q4 2019) додає ще одну оптимізацію.

Дивіться команду b7e2d8b (15 вересня 2019 року) від Masaya Suzuki ( draftcode) .
(Об’єднано Хуніо С Хамано - gitster- у комітеті 1d8b0df , 07 жовтня 2019 р.)

fetch: використовувати, oidsetщоб утримати OID-адреси хотів для швидшого пошуку

Під git fetchчас клієнт перевіряє, чи є OID-адреси рекламованих тегів уже в наборі OID-запиту для отримання запиту.
Ця перевірка проводиться при лінійному скануванні.
Для сховища, в якому є багато записів, повтор цього сканування займає 15+ хвилин.

Щоб прискорити це, створіть oid_setOID для інших посилань.


Цей потік у git-list обговорює можливість змінити поведінку git fetch <remote> <branch>тегів для автоматичного слідування (оскільки він уже оновлює віддалене відстеження ПРОТИ початкові наміри): public-inbox.org/git/…
ankostis

@ankostis Цікаво: як згадує Хуніо в public-inbox.org/git/… , "повернення до старої поведінки може бути одним із варіантів вирішення проблеми, що обговорюється в цій темі". (але вони не будуть: public-inbox.org/git/… )
VonC

Чи вдалося б Git піддавати більшій зайвій складності кінцевому користувачеві, вимагаючи синтаксичних команд до точки, що нагадують хаки, для виконання звичайних операцій? Я не думаю, що для внутрішніх справ ще потрібні знання.
Джон Фантастико

1
@JohnFantastico Я можу зрозуміти цю точку зору. Я це бачив раніше: news.ycombinator.com/item?id=16587496 . Або hackernoon.com/… ("Команди Git - це просто хитра абстракція над сховищем даних")
VonC,

1
@Vadorequest Дякую Я оновив відповідь і буду стежити за списком розсилки: public-inbox.org/git/?q=fetch
VonC

131

Примітка: ця відповідь справедлива лише для git v1.8 та старших версій.

Більшість цього було сказано в інших відповідях та коментарях, але ось коротке пояснення:

  • git fetchвитягує всі голови філій (або всі вказані опцією config.fetch config), усі необхідні для них зобов'язання та всі теги, які доступні з цих гілок. У більшості випадків усі теги доступні таким чином.
  • git fetch --tagsотримує всі теги, усі необхідні для них зобов'язання. Він не оновлюватиме відділення філій, навіть якщо вони будуть доступні з отриманих тегів.

Короткий зміст: Якщо ви дійсно хочете бути в курсі останніх даних, використовуючи лише отримання даних, ви повинні зробити те й інше.

Це також не "вдвічі повільніше", якщо ви не маєте на увазі терміни введення в командному рядку, і в такому випадку псевдоніми вирішують вашу проблему. По суті, немає жодних накладних витрат при здійсненні двох запитів, оскільки вони просять різної інформації.


2
Дякуємо за ваш коментар Я запускаю git у Cygwin через мережу з високою затримкою - це вдвічі повільніше, коли немає для чого отримати (приблизно 5 секунд).
davidA

Ух ти. Чи працює git-remote краще? Коротко дивлячись на джерело, я думаю, що він може здійснити лише один дзвінок, але я не зовсім впевнений, чи він захопить теги, що не належать до гілки. Чесно кажучи, я не знаю, чи бачив я колись теги не на гілці. Що стосується речей, з яких я виймаюсь, єдиний спосіб, який би трапився, якби я так довго чекав, що я пропустив реліз технічного обслуговування, випуск функції та припинення обслуговування старого випуску.
Каскабель

Я думаю, що проблема полягає в тому, що "git fetch" вибирає лише теги на відстежуваних гілках. У нас є сценарій, який дозволяє користувачам вибрати робочу гілку, тому за замовчуванням існує багато гілок, які в даний час не відстежуються особою.
davidA

Я ще не пробував git-remote, але це у моєму постійно зростаючому списку справ :)
davidA

7
Зауважте, що git remote updateнасправді не є заміною git fetchта git fetch --tags. git remote updateне буде оновлювати існуючі теги, які були змінені, хоча вони додадуть нові теги. Тільки git fetch --tagsбуде оновлено вже наявні теги.
larsks

48

Я сам відповім на це.

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

Виявляється, потрібно зробити це повністю "в курсі", тобто тиражувати "git pull" без злиття:

$ git fetch --tags
$ git fetch

Це ганьба, бо це вдвічі повільніше. Якби тільки "git fetch" мав можливість робити те, що зазвичай робить, і вносити всі теги.


Цікаво, що я цього не відчував (ймовірно, тому, що моє репо було актуальним на момент мого тестування) +1
VonC

1
Як щодо ' git remote update myRemoteRepo': чи отримав би віддалений вміст і теги?
VonC

1
Я git fetchпостійно працюю, і він послідовно знімає будь-які нові коміти та будь-які нові теги. Яку версію Git ти працюєш?
Тім Вішер

4
FTR, "git віддалене оновлення myRemoteRepo" не працює добре - не здається, що робить те, що робить "git fetch && git fetch --tags", тим більше, що наступне злиття не впливає.
davidA

1
@TimVisher git fetchне захопить теги, які не знаходяться у журналі фіксування філії. jQuery UI робить це, наприклад, на тезі випуску. Ми робимо git checkout -b temp-branch, робимо свій реліз, додаємо файли, необхідні для випуску, оновлення версії тощо, потім git commit -m "1.10.x" ; git tag 1.10.x; git push --tagsвидаляємо нашу локальну тимчасову гілку. Немає віддаленої гілки, яка б досягла цього тега, і git fetchніколи його не завантажуватиме.
gnarf

31

Загальна проблема тут полягає в тому, що це 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/*"

І якщо ви хочете зробити це за замовчуванням для цього репо, ви можете додати другий респект до вибору за замовчуванням:

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

Це додасть другий fetch =рядок у .git/configдля цього пульта.


Я витратив деякий час на пошуки способу впоратися з цим для проекту. Це те, що я придумав.

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

У моєму випадку я хотів цих особливостей

  • Візьміть усі голови та теги з пульта, тому використовуйте refspec refs/*:refs/*
  • Перезапишіть локальні гілки та теги, якщо не перемотати вперед +до респекту
  • Запишіть поточну перевірену гілку за потреби -u
  • Видалити гілки та теги, відсутні у віддаленому -p
  • І змусити бути впевненим -f

Це має бути відповіддю.
повторна

+1 для " --tagsОпція перемикає респект на +refs/tags/*:refs/tags/*". Хоча, man git-fetchсхоже, вказується ця перспектива без провідного +( refs/tags/*:refs/tags/*).
Дмитро Міньковський

remote.origin.fetchза замовчуванням +refs/heads/*:refs/remotes/origin/*, тобто +версії, чи не так? (Це означає, що походження / гілка буде перезаписана, незалежно від того, де зараз походження / гілка знаходиться локально.)
Роберт Сімер

... і під час написання останнім часом git --tagsвидобували теги на додаток до всього іншого. Дивіться відповідь @VonC.
Роберт Сімер

10

У більшості ситуацій git fetchслід робити те, що ви хочете, а саме: "отримати щось нове з віддаленого сховища та помістити його у свою локальну копію без злиття з місцевими відділеннями". git fetch --tagsробить саме це, за винятком того, що він не отримує нічого, крім нових тегів.

У цьому сенсі git fetch --tagsце жодним чином не є сукупністю git fetch. Це насправді якраз навпаки.

git pullЗвичайно, це не що інше, як обгортка для a git fetch <thisrefspec>; git merge. Рекомендується перед тим, як скокнути, звикнути виконувати ручні роботи git fetchта git mergeперемоги, git pullтому що це допомагає зрозуміти, що git pullробиться в першу чергу.

За словами, відносини точно такі ж, як і з git fetch. git pullє надмножиною git pull --tags.


1
"git pull - це суперсеть git pull - тегів" - але ... "git fetch" - це не суперсет "git fetch --tags", тому відносини не зовсім однакові ...?
davidA

9
Просто знайшов це питання ... ну, мені здається , що git pullнічого НЕ отримати все тег , але тільки ті , досяжні з нинішніх керівників філій. Однак git pull --tagsотримує всі теги і, мабуть, еквівалентно git fetch --tags.
Архімедікс

2
git fetch upstream --tags

працює просто чудово, він отримуватиме лише нові теги і не отримає жодної іншої бази коду.


1
upstreamзазвичай називається origin. Я думаю upstream, що це ім’я, яке використовує GitHub. У будь-якому випадку ім'я, яке потрібно використовувати, є тим, що показано git remote.
Фабіо каже, що знову
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.