Enthält "git fetch --tags" "git fetch"?

270

Eine schöne und einfache Frage - ist die Funktion von "git fetch" eine strikte Teilmenge von git fetch --tags?

Dh wenn ich renne git fetch --tags, gibt es jemals einen Grund, sofort git fetchdanach zu rennen ?

Was ist mit git pullund git pull --tags? Gleiche Situation?

davidA
quelle
11
Ab Git 1..9 / 2.0 (Q1 2014) lautet die Antwort Ja . Siehe meine Antwort unten
VonC
3
Für den Herausgeber, der meinen Text mit einer Bearbeitung "korrigiert" hat - man muss nicht unbedingt nach einem Bindestrich oder einem Akronym groß schreiben, daher war Ihre Bearbeitung grammatikalisch falsch, weshalb ich sie abgelehnt habe.
DavidA

Antworten:

176

Hinweis: Ab Git 1.9 / 2.0 (Q1 2014) werden git fetch --tagsTags zusätzlich zu dem abgerufen , was von derselben Befehlszeile ohne die Option abgerufen wird.

Siehe Commit c5a84e9 von Michael Haggerty (mhagger) :

Bisher wurde die --tagsOption " " von fetch als gleichwertig mit der Angabe der Referenzspezifikation angesehen

refs/tags/*:refs/tags/*

in der Kommandozeile; Insbesondere wurde die remote.<name>.refspecKonfiguration ignoriert.

Aber es ist nicht sehr nützlich , um Tags zu holen , ohne auch andere Referenzen zu holen, während es ist sehr nützlich , die Lage sein , um Tags zu holen , um zusätzlich andere Referenzen.
Ändern Sie also die Semantik dieser Option, um Letzteres zu tun.

Wenn ein Benutzer nur Tags abrufen möchte , kann weiterhin eine explizite Referenz angegeben werden:

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

Bitte beachten Sie, dass die Dokumentation vor 1.8.0.3 in Bezug auf diesen Aspekt des " fetch --tags" Verhaltens nicht eindeutig war .
Mit Commit f0cb2f1 (14.12.2012) fetch --tagswurde die Dokumentation an das alte Verhalten angepasst .
Durch dieses Festschreiben wird die Dokumentation an das neue Verhalten angepasst (siehe Documentation/fetch-options.txt).

Fordern Sie an, dass alle Tags zusätzlich zu den anderen abgerufenen Tags von der Fernbedienung abgerufen werden .


Seit Git 2.5 (Q2 2015) git pull --tagsist robuster:

Siehe Commit 19d122b von Paul Tan ( pyokagan) , 13. Mai 2015.
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit cc77b99 , 22. Mai 2015)

pull: --tagsFehler in keinem Fall von Zusammenführungskandidaten entfernen

Da 441ed41 (" git pull --tags": Fehler mit einer besseren Nachricht., 2007-12-28, Git 1.5.4+) git pull --tagseine andere Fehlermeldung drucken würde, wenn git-fetchkeine Zusammenführungskandidaten zurückgegeben würden:

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

Dies liegt daran, dass zu diesem Zeitpunkt git-fetch --tagsalle konfigurierten Referenzspezifikationen überschrieben würden und daher keine Zusammenführungskandidaten vorhanden wären. Die Fehlermeldung wurde daher eingeführt, um Verwirrung zu vermeiden.

Da c5a84e9 ( fetch --tags: Tags zusätzlich zu anderen Dingen abrufen, 30.10.2013, Git 1.9.0+) git fetch --tagsTags zusätzlich zu konfigurierten Referenzspezifikationen abrufen würde.
Wenn also keine Situation für Zusammenführungskandidaten auftritt, liegt dies nicht daran, dass diese --tagsfestgelegt wurde. Daher ist diese spezielle Fehlermeldung jetzt irrelevant.

Entfernen Sie diese Fehlermeldung, um Verwirrung zu vermeiden.


Mit Git 2.11+ (Q4 2016) git fetchgeht es schneller.

Siehe Commit 5827a03 (13. Oktober 2016) von Jeff King ( peff) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 9fcd144 , 26. Oktober 2016)

fetch: Verwenden Sie "quick" has_sha1_filefür das Folgen von Tags

Beim Abrufen von einer Fernbedienung mit vielen Tags, die für die von uns verfolgten Zweige nicht relevant sind, haben wir viel zu viele Zyklen verschwendet, um zu überprüfen, ob das Objekt, auf das ein Tag zeigt (das wir nicht abrufen werden!), In unserem Repository vorhanden ist zu vorsichtig.

Dieser Patch lehrt Fetch, HAS_SHA1_QUICK zu verwenden, um die Genauigkeit für die Geschwindigkeit zu opfern, in Fällen, in denen wir bei gleichzeitigem Umpacken möglicherweise rassig sind.

Hier sind die Ergebnisse des enthaltenen Perf-Skripts, das eine ähnliche Situation wie die oben beschriebene herstellt:

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

Dies gilt nur für eine Situation, in der:

  1. Auf der Client-Seite müssen viele Pakete reprepare_packed_git()teuer gemacht werden (der teuerste Teil besteht darin, Duplikate in einer unsortierten Liste zu finden, die derzeit quadratisch ist).
  2. Sie benötigen eine große Anzahl von Tag-Refs auf der Serverseite, die Kandidaten für die automatische Verfolgung sind (dh die der Client nicht hat). Jeder löst ein erneutes Lesen des Packverzeichnisses aus.
  3. Unter normalen Umständen würde der Client diesen Tags automatisch folgen und nach einem großen Abruf wäre (2) nicht mehr wahr.
    Wenn diese Tags jedoch auf den Verlauf verweisen, der von dem, was der Client sonst abruft, getrennt ist, folgt er niemals automatisch, und diese Kandidaten wirken sich bei jedem Abruf darauf aus.

Git 2,21 (Februar 2019) scheint eine Regression eingeführt zu haben , wenn die Konfiguration remote.origin.fetchist nicht der Standard ein ( '+refs/heads/*:refs/remotes/origin/*')

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

Git 2.24 (Q4 2019) fügt eine weitere Optimierung hinzu.

Siehe Commit b7e2d8b (15. September 2019) von Masaya Suzuki ( draftcode) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 1d8b0df , 07. Oktober 2019)

fetch: Verwenden Sie oidsetdiese Option, um die gewünschten OIDs für eine schnellere Suche beizubehalten

Währenddessen git fetchprüft der Client, ob die OIDs der angekündigten Tags bereits in der gewünschten OID der Abrufanforderung enthalten sind.
Diese Überprüfung erfolgt in einem linearen Scan.
Bei einem Repository mit vielen Refs dauert das Wiederholen dieses Scans mehr als 15 Minuten.

Um dies zu beschleunigen, erstellen Sie eine oid_setOID für andere Refs.

VonC
quelle
Dieser Thread in der Git-Liste beschreibt die Möglichkeit, das Verhalten von git fetch <remote> <branch>Tags mit automatischer Verfolgung zu ändern (da Remote-Tracking bereits GEGEN die ursprünglichen Absichten aktualisiert wird): public-inbox.org/git/…
ankostis
@ankostis Interessant: Wie Junio ​​in public-inbox.org/git/… erwähnt , kann die Rückkehr zum alten Verhalten eine Option sein, um das in diesem Thread diskutierte Problem zu beheben . (aber sie werden nicht: public-inbox.org/git/… )
VonC
Wäre es Git möglich gewesen, dem Endbenutzer eine unnötigere Komplexität aufzuerlegen, die syntaxintensive Befehle erfordert, die Hacks ähneln, um allgemeine Operationen auszuführen? Ich denke nicht, dass die Interna noch Kenntnisse erfordern.
John Fantastico
1
@ JohnFantastico Ich kann diesen Standpunkt verstehen. Ich habe das schon einmal gesehen: news.ycombinator.com/item?id=16587496 . Oder hackernoon.com/… ("Die Git-Befehle sind nur eine undichte Abstraktion über den Datenspeicher.")
VonC
1
@Vadorequest Vielen Dank. Ich habe die Antwort aktualisiert und werde auf die Mailingliste achten
VonC
131

Hinweis: Diese Antwort gilt nur für Git v1.8 und älter.

Das meiste davon wurde in den anderen Antworten und Kommentaren gesagt, aber hier ist eine kurze Erklärung:

  • git fetchRuft alle Verzweigungsköpfe (oder alle von der Konfigurationsoption remote.fetch angegebenen), alle für sie erforderlichen Commits und alle Tags ab, die von diesen Zweigen aus erreichbar sind. In den meisten Fällen sind alle Tags auf diese Weise erreichbar.
  • git fetch --tagsRuft alle Tags ab, alle für sie erforderlichen Commits. Zweigköpfe werden nicht aktualisiert, selbst wenn sie über die abgerufenen Tags erreichbar sind.

Zusammenfassung: Wenn Sie wirklich auf dem neuesten Stand sein möchten und nur Fetch verwenden möchten, müssen Sie beides tun.

Es ist auch nicht "doppelt so langsam", es sei denn, Sie meinen in Bezug auf die Eingabe in der Befehlszeile. In diesem Fall lösen Aliase Ihr Problem. Es ist im Wesentlichen kein Aufwand, die beiden Anfragen zu stellen, da sie nach unterschiedlichen Informationen fragen.

Cascabel
quelle
2
Vielen Dank für Ihren Kommentar. Ich verwende git in Cygwin über ein Netzwerk mit hoher Latenz - es ist doppelt so langsam, wenn für beide nichts abgerufen werden muss (ca. 5 Sekunden).
DavidA
Oh wow. Funktioniert Git-Remote besser? Wenn ich kurz auf die Quelle schaue, denke ich, dass es möglicherweise nur einen einzigen Anruf gibt - aber ich bin mir nicht ganz sicher, ob es die nicht in der Verzweigung befindlichen Tags erfasst. Ehrlich gesagt weiß ich nicht, ob ich jemals Tags gesehen habe, die sich nicht in einem Zweig befinden. Mit den Dingen, aus denen ich ziehe, wäre der einzige Weg, der passieren würde, wenn ich so lange warten würde, dass ich eine Wartungsversion, eine Funktionsversion und die Einstellung der Wartung der alten Version verpasst hätte.
Cascabel
Ich denke, das Problem ist, dass 'git fetch' nur Tags auf verfolgten Zweigen abruft . Wir haben ein Skript, mit dem Benutzer einen funktionierenden Zweig auswählen können. Standardmäßig gibt es also viele Zweige, die derzeit nicht von einer Person verfolgt werden.
DavidA
Ich habe git-remote noch nicht ausprobiert, aber es steht auf meiner ständig wachsenden
To
7
Beachten Sie, dass dies git remote updatekein Ersatz für git fetchund ist git fetch --tags. git remote updateAktualisiert keine vorhandenen Tags, die geändert wurden, obwohl neue Tags eingefügt werden. Nur git fetch --tagswerden bereits vorhandene Tags aktualisiert.
Larsks
48

Ich werde das selbst beantworten.

Ich habe festgestellt, dass es einen Unterschied gibt. "git fetch --tags" bringt zwar alle Tags ein, aber keine neuen Commits!

Es stellt sich heraus, dass man dies tun muss, um vollständig "auf dem neuesten Stand" zu sein, dh einen "Git Pull" ohne die Zusammenführung zu replizieren:

$ git fetch --tags
$ git fetch

Das ist eine Schande, weil es doppelt so langsam ist. Wenn nur "git fetch" die Option hätte, das zu tun, was es normalerweise tut, und alle Tags einzubringen.

davidA
quelle
Interessanterweise habe ich das nicht erlebt (wahrscheinlich, weil mein Repo zum Zeitpunkt meines Tests auf dem neuesten Stand war). +1
VonC
1
Wie wäre es mit einem ' git remote update myRemoteRepo': Würde das entfernte Inhalte und Tags abrufen?
VonC
1
Ich mache das die git fetchganze Zeit und es werden ständig neue Commits und neue Tags entfernt. Welche Version von Git verwenden Sie?
Tim Visher
4
FTR, 'git remote update myRemoteRepo' funktioniert nicht gut - scheint nicht das zu tun, was 'git fetch && git fetch --tags' tut, zumal eine nachfolgende Zusammenführung keine Auswirkungen hat.
DavidA
1
@TimVisher git fetchgreift nicht auf Tags zu, die nicht im Festschreibungsprotokoll eines Zweigs enthalten sind. Die jQuery-Benutzeroberfläche führt dies beispielsweise für ein Release-Tag aus. Wir machen eine git checkout -b temp-branch, machen unsere Veröffentlichung, fügen Dateien hinzu, die für die Veröffentlichung benötigt werden, aktualisieren die Version usw., dann git commit -m "1.10.x" ; git tag 1.10.x; git push --tagslöschen wir unseren lokalen temporären Zweig. Es gibt keinen Remote-Zweig, der dieses Tag erreicht und git fetches niemals herunterladen wird.
Gnarf
31

Das allgemeine Problem hier ist, dass git fetchholen wird +refs/heads/*:refs/remotes/$remote/*. Wenn eines dieser Commits Tags enthält, werden diese Tags ebenfalls abgerufen. Wenn jedoch Tags vorhanden sind, die von keinem Zweig auf der Fernbedienung erreicht werden können, werden sie nicht abgerufen.

Die --tagsOption schaltet die Referenz auf +refs/tags/*:refs/tags/*. Sie könnten darum bitten git fetch, sich beide zu schnappen. Ich bin mir ziemlich sicher, dass Sie nur git fetch && git fetch -tden folgenden Befehl verwenden würden:

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

Und wenn Sie dies zum Standard für dieses Repo machen möchten, können Sie dem Standardabruf eine zweite Referenz hinzufügen:

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

Dadurch wird eine zweite fetch =Zeile in der .git/configfür diese Fernbedienung hinzugefügt .


Ich habe eine Weile nach einer Möglichkeit gesucht, dies für ein Projekt zu handhaben. Das habe ich mir ausgedacht.

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

In meinem Fall wollte ich diese Funktionen

  • Nehmen Sie alle Köpfe und Tags von der Fernbedienung, verwenden Sie also refspec refs/*:refs/*
  • Überschreiben Sie lokale Zweige und Tags mit nicht schnellem Vorlauf +vor der Referenz
  • Überschreiben Sie den aktuell ausgecheckten Zweig bei Bedarf -u
  • Löschen Sie Zweige und Tags, die in der Fernbedienung nicht vorhanden sind -p
  • Und zwingen, um sicher zu sein -f
Zwerg
quelle
Dies sollte die Antwort sein.
duftend
+1 für "Die --tagsOption schaltet die Referenz auf +refs/tags/*:refs/tags/*". Obwohl, man git-fetchscheint diese refspec ohne die führende +( refs/tags/*:refs/tags/*) zu spezifizieren .
Dmitry Minkovsky
remote.origin.fetchDer Standardwert +refs/heads/*:refs/remotes/origin/*ist die +Version, nicht wahr? (Das heißt, Ursprung / Zweig wird überschrieben, egal wo Ursprung / Zweig gerade lokal ist.)
Robert Siemer
... und zum Zeitpunkt des Schreibens wurden in letzter git --tagsZeit neben allem anderen bereits Tags abgerufen . Siehe die Antwort von @VonC.
Robert Siemer
10

In den meisten Situationen git fetchsollten Sie das tun, was Sie möchten: "Holen Sie sich etwas Neues aus dem Remote-Repository und fügen Sie es in Ihre lokale Kopie ein, ohne es mit Ihren lokalen Niederlassungen zusammenzuführen". git fetch --tagsmacht genau das, außer dass es nichts außer neuen Tags bekommt.

In diesem Sinne git fetch --tagsist in keiner Weise eine Obermenge von git fetch. Es ist genau das Gegenteil.

git pullist natürlich nichts anderes als ein Wrapper für a git fetch <thisrefspec>; git merge. Es wird empfohlen , dass Sie manuell zu tun gewöhnen git fetching und git mergeing , bevor Sie den Sprung zu machen , git pullnur weil es hilft Ihnen zu verstehen , was git pullin erster Linie tut.

Davon abgesehen ist die Beziehung genau die gleiche wie bei git fetch. git pullist die Obermenge von git pull --tags.

Tim Visher
quelle
1
"git pull ist die Obermenge von git pull --tags" - aber ... 'git fetch' ist nicht die Obermenge von 'git fetch --tags', daher ist die Beziehung nicht genau dieselbe ...?
DavidA
9
Nur fand diese Frage ... na ja, es scheint mir , dass git pullsich nicht bekommen alle Tags , sondern nur diejenigen , erreichbar von den aktuellen Zweig Köpfe. Jedoch git pull --tagsholt alle Tags und ist offenbar äquivalent git fetch --tags.
Archimedix
2
git fetch upstream --tags

funktioniert einwandfrei, es werden nur neue Tags und keine andere Codebasis angezeigt.

PAnand
quelle
1
upstreamwird normalerweise genannt origin. Ich denke, upstreamist ein Name, der von GitHub verwendet wird. In jedem Fall ist der zu verwendende Name der von git remote.
Fabio sagt Reinstate Monica