git description mit zwei Tags auf demselben Commit

Lesezeit: 6 Minuten

Gelegentlich haben wir zwei Tags auf demselben Commit. Wenn wir git description für diesen Commit verwenden, gibt git description immer das erste Tag zurück. Meine Lektüre der git-describe-Manpage scheint darauf hinzudeuten, dass das zweite Tag zurückgegeben werden sollte (was sinnvoller ist).

  SEARCH STRATEGY
     For each committish supplied, git describe will first look for a tag which tags
     exactly that commit. Annotated tags will always be preferred over lightweight tags, 
     and tags with newer dates will always be preferred over tags with older dates. 
     If an exact match is found, its name will be output and searching will stop.

Gibt es eine Möglichkeit zu haben git describe das zweite Tag zurückgeben?

Haben Sie eine der Optionen ausprobiert, die git beschreibt?

   --all
       Instead of using only the annotated tags, use any ref found in .git/refs/. This option enables
       matching any known branch, remote-tracking branch, or lightweight tag.

   --tags
       Instead of using only the annotated tags, use any tag found in .git/refs/tags. This option
       enables matching a lightweight (non-annotated) tag.

  • Leider nutzen wir diese Möglichkeiten bereits. Ich frage mich, ob das ein Bug ist?

    – Bill Door

    12. November 2011 um 20:58 Uhr

  • Ich habe das gerade ausprobiert – es funktioniert, solange das Tag kommentiert ist – wenn ich ein leichtes Tag hinzufüge, wird es ignoriert.

    – Adrian Kornisch

    12. November 2011 um 23:06 Uhr

  • Ein Test: $ git tag -a test-1 -m "Just a test" $ git describe test-1 $ git tag -a test-2 -m "Another test" $ git describe test-1 $ git --version git version 1.7.1

    – Bill Door

    13. November 2011 um 1:05 Uhr


  • Behoben in v1.7.1.1 – Das Tag-Datum wird auch im Falle eines Tie-Breaks überprüft.

    – cmbuckley

    26. Februar 2013 um 11:24 Uhr


  • Lightweight-Tags haben keine eigenen Datumsinformationen, sodass sie nicht nach Datum sortiert werden können, wenn sie sich im selben Commit befinden.

    – Zitrax

    27. September 2016 um 8:36 Uhr

Benutzer-Avatar
jgmjgm

Das Verhalten von Git in diesem Fall ist bizarr und verwirrend.

Wenn ich zwei Tags für denselben Commit mache, merke ich das in .git/refs/tags dass jedes der Tags seinen eigenen Commit hat, sodass es theoretisch möglich ist, ein genaues Tag eindeutig auszuchecken.

In der Praxis ist das nicht so.

Nehmen wir an, ich habe ABCD festgelegt. Ich mache zwei Tags (kommentiert), v1.0 und v2.0.

dann hab ich sowas..


master -> ABCD
hotfix -> ABCD
v1.0 (3423) -> ABCD
v1.0 (4234) -> ABCD

Wenn ich einen Zweig wie Master oder Hotfix auschecke, bemerke ich, dass Git einfach gespeichert wird .git/HEAD Der Verweis auf den Zweig, also ist alles gut, es ist nicht mehrdeutig, sondern ein bestimmter Zweig.

Wenn ich den Commit direkt auschecke, ist er von Natur aus mehrdeutig. HEAD enthält einfach den Hash des Commit, ABCD.

Wenn Sie ein Tag wie v1.0 oder v2.0 auschecken, enthält HEAD nicht die Tag-Ref oder das Tag-Commit, sondern die Commit-ID, als ob Sie das Commit direkt ausgecheckt hätten!

Wo dies verwirrend wird, ist, dass, wenn Sie einen Branch wie master auschecken und dann ein Tag auschecken, git status und description das richtige Tag anzeigen, dasjenige, das Sie ausgecheckt haben, auch wenn es mehrdeutig ist!

Wenn Sie dann jedoch ein anderes Tag auschecken, das auf dasselbe verweist, wird das ursprüngliche Tag angezeigt. Das Wechseln von Verzweigung zu Tag merkt sich das Tag, das Wechseln von Tag zu Tag nicht.

Ich weiß nicht, ob dies ein Fehler ist oder wie Git es überhaupt macht (ich vermute, es wiederholt sich (.git/logs/HEAD), aber da das Verhalten willkürlich erscheint, würde ich eine Vermutung riskieren, wenn Sie es einfach wollen Verwenden Sie einen Befehl, um zu dem zu gelangen, was der Benutzer von oben nach unten ausgewählt hat, sei es ein Tag, ein Zweig oder ein Commit, dann glaube ich nicht, dass dies zuverlässig unterstützt wird.

Wenn Sie versuchen, einen Befehl zu verwenden, um automatisch auf die Version zuzugreifen, müssen Sie entweder den Benutzer das Tag manuell eingeben lassen oder ein Verfahren zur Vermeidung von Kollisionen einrichten.

Lightweight-Tags (nicht kommentiert, haben selbst kein Commit, sind nur ein Zeiger direkt auf ein Commit) verhalten sich auf die gleiche seltsame Weise. Da es in einem Fall genau speichern kann, wo der Benutzer ausgecheckt hat, im anderen jedoch fehlschlägt, würde ich vorschlagen, dass es sich um einen Fehler handelt und gemeldet werden sollte.

Der Anwendungsfall dafür ist, dass der Benutzer nur eine Sache auscheckt, obwohl diese Kennung auf etwas mit vielen anderen Kennungen zeigen könnte. Der Einfachheit halber möchten Sie den Bezeichner erhalten, den der Benutzer eingegeben hat, um ihn beispielsweise als Bezeichner für einen Build zu verwenden. Die Fähigkeit von Git, sich diesen Bezeichner zu merken, ist unerklärlicherweise inkonsistent.

In diesem Fall müssen Ihre Skripte versuchen, eine einzelne beste Kennung abzuleiten, aber wenn die Kennung mehrdeutig ist, sollte sie einen Fehler erzeugen. Sie können sich nicht auf Dinge wie den Git-Status oder die Beschreibung verlassen, da sie manchmal nicht das produzieren, was zuletzt ausgecheckt wurde, wie es beim Wechseln von Tag zu Tag angezeigt wird, anstatt von Verzweigung zu Tag.

Dies ist in zu sehen .git/logs/HEAD die anscheinend Verzweigungs-zu-Tag-Berichte enthält, aber sobald Sie sich auf einem Tag befinden, wird nichts protokolliert.

Describe scheint immer das neueste annotierte (nicht leichte) Tag zurückzugeben. Wenn Sie Tag-Typen mischen, sollten Sie nicht von einem konsistenten Verhalten ausgehen. Leichtgewichtige Tags scheinen ebenfalls die neueste Version zu verwenden (vermutlich basierend auf dem Zeitstempel der Datei und nicht auf der Commit-Zeit), werden aber nicht ohne gesucht --all oder --tags. Selbst mit –all scheinen annotierte Tags Vorrang vor neueren Lightweight-Tags zu haben.

Die einzige bequeme Möglichkeit, alle Bezeichner für das aktuelle Tag zu erhalten, die ich finden kann, besteht darin, git show-ref mit Dereferenzierung auszuführen und nach Ihrem aktuellen Commit zu grep. Dies beinhaltet keine Zeitstempel für die Sortierung.

Zwei Methoden, je nach Bedarf.

Methode 1:

git tag -l | sort -V | tail -1

Wenn Sie nach einem bestimmten Format suchen möchten, z. B. semantische Version

git tag -l | grep "v[0-9]*.[0-9]*.[0-9]*$" | sort -V | tail -1

Methode 2:

git tag --sort=committerdate | tail -1

Wenn Sie nach einem bestimmten Format suchen möchten, z. B. semantische Version

git tag --sort=committerdate | grep "v[0-9]*.[0-9]*.[0-9]*$" | tail -1

Nach allem, was ich sagen kann, kann ‘git description’ leichte Tags nicht eindeutig machen und druckt daher das erste, auf das es stößt. Dieses Snippet geht davon aus, dass Tags einem Muster folgen, das durch „sort -R“ sortiert werden kann, und das „neueste“ Tag für einen bestimmten SHA zurückgibt:

git tag --contains SHA | sort -R | tail -1

Ich hatte zwei Tagging-Konventionen für denselben Commit und wollte die beibehalten git describe Funktionen wie Dirty, Sha und Commit zählt nach Tag usw. Also in git version 2.24.1 Da ich eine eindeutige Unterscheidungszeichenfolge in einem Tag gegenüber dem anderen hatte, habe ich einfach den Match-Operator verwendet. Sie können auch ausschließen verwenden

git describe --tags --match '*xXx*'

1014680cookie-checkgit description mit zwei Tags auf demselben Commit

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

Privacy policy