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.
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*'