git – Tags mit dem gleichen Namen mit einer Verzweigung

Lesezeit: 5 Minuten

Ich war irgendwie ausgeflippt, warum um alles in der Welt git diff branch1 branch2 zeigt irrelevante Dinge (es war, als würde branch1 mit einer ÄLTEREN Version von branch2 verglichen)

Bis ich herausfand, dass wir einige Tags mit dem gleichen Namen mit einem Zweig haben!

Abgesehen von diff macht das Probleme beim Pull/Push (mehrdeutiger Ref-Name-Fehler …) und möglicherweise beim Auschecken …

Ich möchte also alle diese Tags finden, damit ich sie löschen kann

  • Der einfache Befehl dafür lautet git for-each-ref --format='%(refname:short)' | sort | uniq -d, um alle Wortspiel-Kurznamen anzuzeigen. Wenn Sie alle Punned-Tags löschen möchten, git tag -d $(that pipeline).

    – jthill

    23. September 2018 um 3:07 Uhr


  • In Git-Befehlen (diff, push usw.) können Sie disambiguieren, z git diff refs/heads/branchname refs/tags/branchname (aber es ist trotzdem ratsam, diese Mehrdeutigkeit zu vermeiden)

    – benjimin

    28. Mai 2019 um 5:18 Uhr

  • Sie sollten einem Tag und einem Zweig niemals den gleichen Namen geben! Verweisen: geedew.com/fixing-git-branch-and-tag-name-collision

    – Erich

    21. März 2022 um 4:01 Uhr

Zuerst extrahieren wir alle Tags:

git tag | sort > tags

Und Niederlassungen, wenn Sie dies mit lokalen Niederlassungen überprüfen möchten:

git branch | sed -e 's/^[ \t]*//' | sort > branches

Oder Zweige einer bestimmten Fernbedienung, wie z origin

git branch -r | grep origin/  | sed -e 's:^[ \t]*origin/::' | sort > branches

Nach dem Extrahieren von Tags und Zweigen (in sortierter Reihenfolge) finden wir die gemeinsamen Zeilen in diesen 2 Dateien:

comm -1 -2 tags branches > bad-tags

Und sehen Sie sich die Datei an bad-tags

Dann können wir alle löschen:

cat bad-tags | xargs git tag -d

Die Antwort von saeedgnu ist auf dem richtigen Weg, verwendet aber viele zusätzliche Shell-Befehle.

Anstatt zu verwenden | sortbeide git tag Und git branch habe einen --sort=<key> Möglichkeit, mit <key> bezogen auf git for-each-ref Feldnamen und mit einem Muster.

Standardmäßig ist die Standardsortierreihenfolge sowohl für Zweige als auch für Tags bereits nach Referenzname.

Und seit Git 2.19 (Q3 2018), git branch unterstützt eine Konfig branch.sortwie git tag hatte schon eine Konfig tag.sort.
Sehen Commit 560ae1c (16. August 2018) von Samuel Maftul (“).
(Zusammengeführt von Junio ​​C. Hamano — gitster In d89db6f übergeben27.08.2018)

So:

  • keine Notwendigkeit zu sortieren git tag: Sie sind bereits standardmäßig nach Refname sortiert, es sei denn, a tag.sort config eingestellt wurde.
    Aber um auf der sicheren Seite zu sein, verwenden Sie mindestens git tag --sort="refname" (NEIN | sort erforderlich)
  • kein Notwendigkeit für grep origin, sed oder sort (außer a branch.sort config gesetzt wurde): Verwenden Sie ein Muster und ein Format:

    git branch -r --list 'origin/*' --format="%(refname:lstrip=3)"
    

Das Format transformiert a remotes/origin/aBranchName hinein aBranchName.
Das Muster ‘origin/*‘ stellt sicher, dass wir die entfernten Branches des richtigen entfernten Repos auswählen.

Das gibt Ihnen reine Git-Befehle:

git tag --sort="refname" > tags
git branch -r --list 'origin/*' --format="%(refname:lstrip=3)"
comm -1 -2 tags branches > bad-tags

Benutzeravatar von VonC
VonC

Neben dem Scripting (mit reinen Git-Befehlen) zur Anzahl schlechter Tags bietet Git 2.20 (Q4 2018) eine Alternative dazu vermeiden Tags mit dem gleichen Namen mit einer Verzweigung erhalten müssen.

Die Regeln, die von “git push” Und “git fetch” um festzustellen, ob ein Verweis aktualisiert werden kann oder nicht, waren inkonsistent; insbesondere war das Abrufen zum Aktualisieren vorhandener Tags zulässig, obwohl Tags unveränderliche Ankerpunkte sein sollten.
git fetch” wurde gelehrt, Aktualisierungen bestehender Tags ohne das “--force” Möglichkeit.

Sehen übertrage 0bc8d71, ae6a470 übergeben, fe802bd begehen, Commit 8da6128, Commit d931455, übertrage 6b0b067, begehen 253b3d4, f08fb8d übergeben, Übertrage 8cd4b7c (31. August 2018) von Ævar Arnfjörð Bjarmason (avar).
(Zusammengeführt von Junio ​​C. Hamano — gitster In d39cab3 übergeben17.09.2018)

fetch: Beenden Sie das Überschreiben vorhandener Tags ohne --force

Ändern “fetch” behandeln “+” in Refspecs (aka --force) bedeutet, dass wir ein lokales Tag mit demselben Namen schlagen sollten.

Dies ändert das langjährige Verhalten von “fetch“ hinzugefügt 853a369 (“[PATCH] Multi-Head-Fetch.”, 2005-08-20, Git 0.99.5).
Vor dieser Änderung waren alle Tag-Abrufe effektiv --force ermöglicht.
Siehe die git-fetch-script Code ein fast_forward_local() mit dem Kommentar:

Tags müssen nicht auf Commits zeigen, daher gibt es sowieso keine Möglichkeit, einen “Schnellvorlauf” zu garantieren.

Dieses Commit und der Rest der Geschichte von “fetch” zeigt, dass die “+” (--force) war ein Teil von refpecs nur für Zweigaktualisierungen konzipiert, während Tags alle Änderungen von Upstream bedingungslos akzeptiert und das lokale Tag-Objekt verprügelt haben. Dieses Verhalten ändern wurde bereits 2011 diskutiert.

Das aktuelle Verhalten ergibt für mich keinen Sinn, es führt leicht dazu, dass lokale Tags versehentlich überschrieben werden.
Wir könnten unsere Tags per Remote benennen und nicht lokal auffüllen refs/tags/*aber wie bei meiner 97716d2 (“fetch: füge hinzu ein --prune-tags Möglichkeit und fetch.pruneTags config”, 09.02.2018, Git 2.17) ist es einfacher, die aktuelle Implementierung zu umgehen, als die Ursache zu beheben.

(Siehe „Wie synchronisiere ich meine Tags in Git mit einem Remote-Server?“)

Diese Änderung wird also implementiert Vorschlag Nr. 1 aus Jeffs E-Mail 2011fetch” verstopft das Tag jetzt nur noch, wenn entweder “+” als Teil der Referenzspezifikation bereitgestellt wird, oder wenn “--force“ wird in der Befehlszeile bereitgestellt.

Das macht es auch schön symmetrisch dazu, wie “tag” selbst funktioniert beim Erstellen von Tags.
Das heißt, wir weigern uns, vorhandene Tags zu überschreiben, es sei denn “--force” ist versorgt.
Jetzt können wir all solches Clobbering ablehnen, egal ob es durch Clobbering eines lokalen Tags mit “tag“, oder durch Abrufen von der Fernbedienung mit “fetch“.

Ref-Updates außerhalb refs/{tags,heads/* sind immer noch nicht symmetrisch mit wie “git push„funktioniert, wie in den kürzlich geänderten besprochen pull-fetch-param.txt Dokumentation.
Diese Änderung bringt die beiden unterschiedlichen Verhaltensweisen mehr in Einklang. Ich glaube nicht, dass es einen Grund gibt, warum “fetch” nicht vollständig mit dem Verhalten von “push“, aber das ist ein Thema für einen anderen Wechsel.

1445810cookie-checkgit – Tags mit dem gleichen Namen mit einer Verzweigung

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy