Was ist das Git-Äquivalent für die Revisionsnummer?


244

Wir verwenden SVN bei der Arbeit, aber für meine persönlichen Projekte habe ich mich für Git entschieden. Also installierte ich Git gestern, und ich frage mich , was das ist Revisionsnummer Äquivalent in Git .

Angenommen, wir arbeiten an Version 3.0.8 und jede Fehlerbehebung hat ihre eigene Versionsnummer, die wir verwenden können, wenn wir über diese Fehlerbehebung sprechen. Wenn ich also den Code in Git mit 3.0.8 tagge, was kann ich dann als Revisionsnummer oder eine andere detailliertere Art der Identifizierung verwenden? Ich finde den Hash nicht so benutzerfreundlich für Menschen.



Es gibt einen Artikel für eine der möglichen Lösungen. Es könnte etwas schwer aussehen, ist aber in die Ausgabe von "git log" integriert und erfordert keine zusätzlichen Befehle außer "git push / pull / fetch".
Dmitry Pavlenko

Leider befindet sich der verlinkte Artikel von @DmitryPavlenko in einer toten Domain: gitsvn.x10.mx. Ohne Angabe des Themas wird es für niemanden schwierig sein, es anderswo zu finden.
Michael Donohue

Hinweis: Keine Abkürzung mehr erforderlich mit git beschreiben: siehe stackoverflow.com/a/41308073/6309
VonC

1
Nein, Laurence Gonsalves, dies ist kein Duplikat von "Wie bekomme ich die Anzahl der Git-Commits?" - Hier geht es um die Versionsnummer, und obwohl die Anzahl der Festschreibungen ein wenig gleich aussehen kann, unterscheidet sich die Hash-Version stark von der Anzahl der Festschreibungen :-)
David Svarrer

Antworten:


149

Gute oder schlechte Nachrichten für Sie, dieser Hash ist die Revisionsnummer. Ich hatte auch Probleme damit, als ich von SVN zu Git wechselte.

Sie können "tagging" in git verwenden, um eine bestimmte Revision als "release" für eine bestimmte Version zu kennzeichnen, sodass Sie leicht auf diese Revision verweisen können. Schauen Sie sich diesen Blog-Beitrag an .

Das Wichtigste zu verstehen ist, dass Git keine Revisionsnummern haben kann - denken Sie an die Dezentralität. Wenn Benutzer A und B sich beide auf ihre lokalen Repositorys festlegen, wie kann git eine fortlaufende Revisionsnummer sinnvoll zuweisen? A hat keine Kenntnis von B, bevor sie die Änderungen des anderen drücken / ziehen.

Eine andere zu betrachtende Sache ist die vereinfachte Verzweigung für Bugfix-Verzweigungen:

Beginnen Sie mit einer Version: 3.0.8. Führen Sie dann nach dieser Veröffentlichung Folgendes aus:

git branch bugfixes308

Dadurch wird eine Verzweigung für Bugfixes erstellt. Kasse der Filiale:

git checkout bugfixes308

Nehmen Sie nun die gewünschten Bugfix-Änderungen vor.

git commit -a

Übernehmen Sie sie und wechseln Sie zurück zum Hauptzweig:

git checkout master

Ziehen Sie dann diese Änderungen aus dem anderen Zweig ein:

git merge bugfixes308

Auf diese Weise haben Sie einen separaten Release-spezifischen Bugfix-Zweig, aber Sie ziehen die Bugfix-Änderungen immer noch in Ihren Hauptentwicklungs-Trunk.


11
Ich habe verstanden, dass Hash die Revisionsnummer ist, aber ich hoffte, dass dies nicht der Fall ist :-))) Vielen Dank für die sehr nette Erklärung und den Vorschlag, sich jetzt damit zu befassen.
Radek

3
Bitte. Ich war sehr frustriert mit Git, als ich es zum ersten Mal von SVN abgeholt habe, aber jetzt schwinge ich in die andere Richtung ...
Makdad

4
AUCH es ist eine Weile her, seit ich dies gepostet habe, aber denken Sie daran, dass Sie auch "git checkout -b new_branch_name" ausführen können, um "git branch foo" und "git checkout foo" als Einzeiler auszuführen.
Makdad

1
Stimmt es, dass Hashes "echte" Hashes sind und nicht einmal remote sequentiell? Wenn also in der Fehlerdatenbank angegeben fixed in 547cc3e..c4b2ebaist und Sie eine andere Revision haben, haben Sie keine Ahnung, ob Ihr Code das Update enthalten soll oder nicht?! Sicher haben die Git bei git-central eine Lösung dafür?!?!
Olie

3
In SVN sagt Ihnen die Tatsache, dass ein Fehler in r42 behoben ist, nicht aus, ob er auch in r43 behoben ist, sobald Sie tatsächlich Zweige verwenden.
Matthieu Moy

186

Mit modernem Git (in meinem Fall 1.8.3.4) und ohne Verwendung von Zweigen können Sie Folgendes tun:

$ git rev-list --count HEAD
68

22
Erwägen Sie die Verwendung vongit rev-list --count --first-parent HEAD
Flimm

8
Gibt es angesichts dieser Informationen (Nummer 68) eine Möglichkeit, die Revision für die erneute Erfassung des Codes zu bestimmen? Angenommen, "Revision 68" wird für eine Testumgebung freigegeben, die Entwicklung wird fortgesetzt, und später muss ein Entwickler "Revision 68" von der Quellcodeverwaltung erneut erwerben. Wie würde er die spezifische Version zum Klonen auswählen? Oder fehlt mir etwas an Git, das dies unnötig macht?
David

9
Beachten Sie, dass diese Lösung für verschiedene Entwickler unterschiedliche Ergebnisse liefert. Außerdem würde eine Rückwärtsberechnung von der "Anzahl" bis zum Commit unterschiedliche Commits für verschiedene Entwickler ergeben !! Dies liegt an der verteilten Natur von Git und daran, dass Commits in verschiedenen Repositorys während des gleichen Zeitabschnitts stattfinden, jedoch möglicherweise nicht berücksichtigt werden, git rev-list --count HEADje nachdem, wann die letzten Pushs und Pulls ausgeführt wurden.
Jason

2
@ Jason, hat Davids Kommentar zum Hinzufügen von --first-parentAdresse Ihr Anliegen? Ich würde es hassen, eine scheinbar einfachste Lösung aufgrund eines seltenen Randfalls zu vermeiden, wenn es eine ebenso einfache Problemumgehung oder einen Weg gibt, sie robuster zu machen.
MarkHu

4
@ MarkHu, --first-parenthilft. Solange keine Neubasierung durchgeführt wird und immer derselbe Zweig für die Erstellung von Releases verwendet wird (und natürlich für die Berechnung dieser Release-Nummer), könnte dies verwendet werden. Ich bin mir jedoch immer noch nicht sicher, ob das Commit, von dem die Veröffentlichung stammt, immer eindeutig identifiziert werden kann. Es gibt so viele Dinge, die hier schief gehen können ... aber im Moment kann ich mir nichts vorstellen, was dies definitiv brechen würde (angesichts meiner obigen "solange" Aussagen). Die git describein einer anderen Antwort erwähnte Methode ist der richtige Weg. Erstellen Sie ein Tag, wenn Sie etwas lesbares möchten.
Jason

104

Der git describeBefehl erstellt einen etwas besser lesbaren Namen, der sich auf ein bestimmtes Commit bezieht. Zum Beispiel aus der Dokumentation:

Mit so etwas wie git.git aktueller Baum bekomme ich:

[torvalds@g5 git]$ git describe parent
v1.0.4-14-g2414721

Das heißt, der aktuelle Kopf meines "übergeordneten" Zweigs basiert auf Version 1.0.4. Da er jedoch einige Commits enthält, hat description die Anzahl der zusätzlichen Commits ("14") und einen abgekürzten Objektnamen für das Commit hinzugefügt selbst ("2414721") am Ende.

Solange Sie vernünftig benannte Tags verwenden, um bestimmte Releases zu kennzeichnen, kann dies als ungefähr gleichwertig mit einer SVN- "Revisionsnummer" angesehen werden.


7
Ich möchte nur darauf hinweisen, dass dies nur funktioniert , wenn Ihr gitRepository bereits Tags enthält. Wenn dies nicht der Fall ist , schlägt git description möglicherweise mit "fatal: Keine Namen gefunden, kann nichts beschreiben" fehl. - Stapelüberlauf ; Dies bedeutet, dass Sie Tags selbst einrichten müssen.
Sdaau

14
@sdaau: Wenn Sie dies in einem Skript oder etwas anderem verwenden und git describeniemals versagen möchten , verwenden Sie die git describe --alwaysOption.
Greg Hewgill

Kann die Ausgabe von git describeirgendwie verwendet werden, um das Quell-Commit zu finden? Ich meine, ohne die Commits im Protokoll manuell zu zählen.
Lii

@Lii: Was meinst du mit "Source Commit"? Sowohl das nächste Tag ( v1.0.4) als auch die letzte Commit-ID ( 2414721) sind bereits Teil der Ausgabe von git description.
Greg Hewgill

@ GregHewgill: Ja, danke, als ich die Frage stellte, wurde mir nicht klar, dass der "abgekürzte Objektname" ein Wert ist, mit dem das Commit identifiziert werden kann. Das ist hervorragend!
Lii

67

Die anderen Plakate sind richtig, es gibt keine "Revisionsnummer".

Ich denke, der beste Weg ist, Tags für "Releases" zu verwenden!

Aber ich habe das Folgende verwendet, um Revisionsnummern zu fälschen (nur damit Kunden Revisionen und den Fortschritt sehen können, da sie die gleichen zunehmenden Revisionen von Git haben wollten, wie sie es durch Subversion gewohnt waren).

Zeigen Sie an, dass die "aktuelle Version" von "HEAD" folgendermaßen simuliert wird:

git rev-list HEAD | wc -l

Aber was ist, wenn der Client mir sagt, dass es einen Fehler in "Revision" 1302 gibt?

Zu diesem Zweck habe ich dem Abschnitt [alias] meiner ~ / .gitconfig Folgendes hinzugefügt:

show-rev-number = !sh -c 'git rev-list --reverse HEAD | nl | awk \"{ if(\\$1 == "$0") { print \\$2 }}\"'

using git show-rev-number 1302wird dann den Hash für die "Revision" drucken :)

Ich habe vor einiger Zeit einen Blog-Beitrag über diese "Technik" verfasst.


@Radek - "muss manchmal wissen, was 'Codeänderung = Festschreiben' etwas behoben hat" - dann ist git bisect(Link) das geeignete Werkzeug, um zu identifizieren, was sich wann von wem geändert hat.
Michael

@Radek Ja, es ist eine immer größere Zahl. Es werden nur die Revisionen gezählt, die Sie im HEAD eingecheckt haben. Jedes Commit ist also eine neue Revision. Dies funktioniert nicht für verschiedene Branchen.
OderWat

1
Ich mag deine Lösung. Bitte beachten Sie, dass Sie es vereinfachen können: show-rev-number =! Sh -c 'git rev-list --reverse HEAD | awk NR == $ 0 '
avner

@avner Danke! Ich habe offensichtlich nicht viel awk in meinem Leben benutzt :)
OderWat

3
Ich musstegit rev-list --reverse HEAD | awk "{ print NR }" | tail -n 1
Gerry

27

Git hat nicht das gleiche Konzept von Revisionsnummern wie Subversion. Stattdessen wird jeder mit einem Commit erstellte Snapshot durch eine SHA1-Prüfsumme gekennzeichnet. Warum? Es gibt verschiedene Probleme mit einem laufenden Revno in einem verteilten Versionskontrollsystem:

Erstens, da die Entwicklung überhaupt nicht linear ist, ist das Anhängen einer Zahl als Problem ziemlich schwierig zu lösen, so dass Ihre Anforderungen als Programmierer erfüllt werden. Der Versuch, dies durch Hinzufügen einer Nummer zu beheben, kann schnell problematisch werden, wenn sich die Nummer nicht wie erwartet verhält.

Zweitens können Revisionsnummern auf verschiedenen Computern generiert werden. Dies erschwert die Synchronisation von Zahlen erheblich - insbesondere, da die Konnektivität nur in eine Richtung erfolgt. Möglicherweise haben Sie nicht einmal Zugriff auf alle Computer mit dem Repository.

Drittens entspricht die Identität eines Commits (was das Commit ist) in git, etwas Pionierarbeit durch das inzwischen nicht mehr existierende OpenCM-System, seinem Namen (der SHA-ID). Dieses Namens- / Identitätskonzept ist sehr stark. Wenn Sie mit einem Commit-Namen in der Hand sitzen, wird das Commit auch auf nicht fälschbare Weise identifiziert. Auf diese Weise können Sie alle Ihre Commits mit dem git fsckBefehl auf Beschädigung zurück überprüfen .

Da wir nun eine DAG (Directed Acyclic Graph) mit Revisionen haben und diese den aktuellen Baum bilden, benötigen wir einige Tools, um Ihr Problem zu lösen : Wie unterscheiden wir verschiedene Versionen? Erstens können Sie einen Teil des Hashs weglassen, wenn ein bestimmtes Präfix, beispielsweise 1516bd , Ihr Commit eindeutig identifiziert. Das ist aber auch eher erfunden. Stattdessen besteht der Trick darin, Tags und / oder Zweige zu verwenden. Ein Tag oder Zweig ähnelt einem "gelben Stick it Note", den Sie an eine bestimmte Commit-SHA1-ID anhängen. Tags sollen sich im Wesentlichen nicht bewegen, während sich ein Zweig bewegt, wenn neue Festschreibungen an seinem HEAD vorgenommen werden. Es gibt Möglichkeiten, auf ein Commit um ein Tag oder einen Zweig zu verweisen. Weitere Informationen finden Sie in der Manpage von git-rev-parse.

Wenn Sie an einem bestimmten Code arbeiten müssen, wird dieser normalerweise geändert und sollte daher ein Zweig mit einem sprichwörtlichen Themennamen sein. Das Erstellen vieler Zweige (20 bis 30 pro Programmierer sind keine Seltenheit, einige 4 bis 5 werden veröffentlicht, damit andere daran arbeiten können) ist der Trick für effektives Git. Jedes Werk sollte als eigener Zweig beginnen und dann beim Testen zusammengeführt werden. Unveröffentlichte Zweige können komplett umgeschrieben werden, und dieser Teil der Zerstörung der Geschichte ist eine Kraft des Schwachsinns.

Wenn die Änderung in den Meister aufgenommen wird , friert sie etwas ein und wird zur Archäologie. An diesem Punkt können Sie es markieren, aber häufiger wird in einem Bug-Tracker oder Issue-Tracker über die sha1-Summe auf das bestimmte Commit verwiesen. Tags sind in der Regel für Versionsfehler und Verzweigungspunkte für Wartungszweige (für alte Versionen) reserviert.


18

Wenn Sie interessiert sind, habe ich Versionsnummern automatisch aus Git-Infos hier im Format verwaltet

<major>.<minor>.<patch>-b<build>

Dabei ist build die Gesamtzahl der Commits. Sie sehen den interessanten Code in der Makefile. Hier ist der relevante Teil, um auf den anderen Teil der Versionsnummer zuzugreifen:

LAST_TAG_COMMIT = $(shell git rev-list --tags --max-count=1)
LAST_TAG = $(shell git describe --tags $(LAST_TAG_COMMIT) )
TAG_PREFIX = "latex-tutorial-v"

VERSION  = $(shell head VERSION)
# OR try to guess directly from the last git tag
#VERSION    = $(shell  git describe --tags $(LAST_TAG_COMMIT) | sed "s/^$(TAG_PREFIX)//")
MAJOR      = $(shell echo $(VERSION) | sed "s/^\([0-9]*\).*/\1/")
MINOR      = $(shell echo $(VERSION) | sed "s/[0-9]*\.\([0-9]*\).*/\1/")
PATCH      = $(shell echo $(VERSION) | sed "s/[0-9]*\.[0-9]*\.\([0-9]*\).*/\1/")
# total number of commits       
BUILD      = $(shell git log --oneline | wc -l | sed -e "s/[ \t]*//g")

#REVISION   = $(shell git rev-list $(LAST_TAG).. --count)
#ROOTDIR    = $(shell git rev-parse --show-toplevel)
NEXT_MAJOR_VERSION = $(shell expr $(MAJOR) + 1).0.0-b$(BUILD)
NEXT_MINOR_VERSION = $(MAJOR).$(shell expr $(MINOR) + 1).0-b$(BUILD)
NEXT_PATCH_VERSION = $(MAJOR).$(MINOR).$(shell expr $(PATCH) + 1)-b$(BUILD)

9

Eine Bash-Funktion:

git_rev ()
{
    d=`date +%Y%m%d`
    c=`git rev-list --full-history --all --abbrev-commit | wc -l | sed -e 's/^ *//'`
    h=`git rev-list --full-history --all --abbrev-commit | head -1`
    echo ${c}:${h}:${d}
}

gibt so etwas wie aus

$ git_rev
2:0f8e14e:20130220

Das ist

commit_count:last_abbrev_commit:date_YYmmdd

So etwas könnte nützlich sein, aber wenn man an inkrementellen Versionsnummern interessiert ist, würde man die Feldpositionen vertauschen, so dass der (nicht inkrementelle) Hash der letzte ist.
MarkHu

8

Der SHA1-Hash des Commits entspricht einer Subversion-Revisionsnummer.


7
Leider hat es ganz andere Eigenschaften als eine Revisionsnummer. Es ist ziemlich lang und nimmt nicht monoton zu.
Vermutlich ist

1
@CodeInChaos: Ich weiß, worauf Sie hinaus wollen, aber es ist im Allgemeinen möglich, auf Git-Commits mit nur den ersten 6 oder 8 Zeichen des Hash-Codes zu verweisen.
Chris Pitman

5
@Radek: Sie sind nicht garantiert einzigartig (wenn Sie jedoch eine Kollision finden, können Sie eine kleine Menge an Prominenten gewinnen).
Slartibartfast

8
@Radek Laut en.wikipedia.org/wiki/Collision_attack haben Sie mit 4 Zeichen des Hash eine 16- Bit-ID , was bedeutet, dass in einem Repo mit 256 (= 2 ^ (16/2)) Commits eine 50 vorhanden ist % Wahrscheinlichkeit, dass zwei Commits dasselbe Präfix mit vier Zeichen haben (und bei 65536 Commits ist es sicher, da der Bereich der 4-Zeichen-IDs seitdem erschöpft ist). Wenn Sie ein Zeichen hinzufügen, haben Sie eine 20-Bit-ID, was bedeutet, dass der 50% -Schwellenwert bei 1024 Commits liegt. Da dies jedoch ein statistischer Parameter ist, garantiert nichts, dass solche Kollisionen nicht früher auftreten.
Rudi

2
Da der Hash auf dem Inhalt basiert, ist es immer noch eine Wahrscheinlichkeit, ob zwei Commits dasselbe Hash-Präfix haben, keine Gewissheit. Bei 65536 Commits ist es sehr wahrscheinlich, dass zwei das gleiche Präfix mit vier Zeichen haben, aber es ist immer noch nicht sicher. Abgesehen davon hat der vollständige Hash noch keine Kollision, aber Git arbeitet daran :) stackoverflow.com/questions/3475648/…
goodeye

6

Dies habe ich in meinem Makefile basierend auf anderen Lösungen getan. Beachten Sie, dass Ihr Code dadurch nicht nur eine Revisionsnummer erhält, sondern auch der Hash angehängt wird, mit dem Sie die Version neu erstellen können.

# Set the source control revision similar to subversion to use in 'c'
# files as a define.
# You must build in the master branch otherwise the build branch will
# be prepended to the revision and/or "dirty" appended. This is to
# clearly ID developer builds.
REPO_REVISION_:=$(shell git rev-list HEAD --count)
BUILD_BRANCH:=$(shell git rev-parse --abbrev-ref HEAD)
BUILD_REV_ID:=$(shell git rev-parse HEAD)
BUILD_REV_ID_SHORT:=$(shell git describe --long --tags --dirty --always)
ifeq ($(BUILD_BRANCH), master)
REPO_REVISION:=$(REPO_REVISION_)_g$(BUILD_REV_ID_SHORT)
else
REPO_REVISION:=$(BUILD_BRANCH)_$(REPO_REVISION_)_r$(BUILD_REV_ID_SHORT)
endif
export REPO_REVISION
export BUILD_BRANCH
export BUILD_REV_ID

3
Es scheint der sicherste Weg zu sein git-describe, um Fehler zu vermeiden, mit git describe --always --dirty --long --tagsdem in allen Fällen funktioniert, die ich mir vorstellen kann.
MarkHu

5

Das Problem bei der Verwendung des Git-Hash als Build-Nummer ist, dass er nicht monoton ansteigt. OSGi schlägt vor, einen Zeitstempel für die Build-Nummer zu verwenden. Es sieht so aus, als ob die Anzahl der Commits für den Zweig anstelle der Subversion- oder Perforce-Änderungsnummer verwendet werden könnte.


5

Ich habe einige PowerShell-Dienstprogramme geschrieben, um Versionsinformationen von Git abzurufen und das Taggen zu vereinfachen

Funktionen: Get-LastVersion, Get-Revision, Get-NextMajorVersion, Get-NextMinorVersion, TagNextMajorVersion, TagNextMinorVersion:

# Returns the last version by analysing existing tags,
# assumes an initial tag is present, and
# assumes tags are named v{major}.{minor}.[{revision}]
#
function Get-LastVersion(){
  $lastTagCommit = git rev-list --tags --max-count=1
  $lastTag = git describe --tags $lastTagCommit
  $tagPrefix = "v"
  $versionString = $lastTag -replace "$tagPrefix", ""
  Write-Host -NoNewline "last tagged commit "
  Write-Host -NoNewline -ForegroundColor "yellow" $lastTag
  Write-Host -NoNewline " revision "
  Write-Host -ForegroundColor "yellow" "$lastTagCommit"
  [reflection.assembly]::LoadWithPartialName("System.Version")

  $version = New-Object System.Version($versionString)
  return $version;
}

# Returns current revision by counting the number of commits to HEAD
function Get-Revision(){
   $lastTagCommit = git rev-list HEAD
   $revs  = git rev-list $lastTagCommit |  Measure-Object -Line
   return $revs.Lines
}

# Returns the next major version {major}.{minor}.{revision}
function Get-NextMajorVersion(){
    $version = Get-LastVersion;
    [reflection.assembly]::LoadWithPartialName("System.Version")
    [int] $major = $version.Major+1;
    $rev = Get-Revision
    $nextMajor = New-Object System.Version($major, 0, $rev);
    return $nextMajor;
}

# Returns the next minor version {major}.{minor}.{revision}
function Get-NextMinorVersion(){
    $version = Get-LastVersion;
    [reflection.assembly]::LoadWithPartialName("System.Version")
    [int] $minor = $version.Minor+1;
    $rev = Get-Revision
    $next = New-Object System.Version($version.Major, $minor, $rev);
    return $next;
}

# Creates a tag with the next minor version
function TagNextMinorVersion($tagMessage){
    $version = Get-NextMinorVersion;
    $tagName = "v{0}" -f "$version".Trim();
    Write-Host -NoNewline "Tagging next minor version to ";
    Write-Host -ForegroundColor DarkYellow "$tagName";
    git tag -a $tagName -m $tagMessage
}

# Creates a tag with the next major version (minor version starts again at 0)
function TagNextMajorVersion($tagMessage){
    $version = Get-NextMajorVersion;
    $tagName = "v{0}" -f "$version".Trim();
    Write-Host -NoNewline "Tagging next majo version to ";
    Write-Host -ForegroundColor DarkYellow "$tagName";
    git tag -a $tagName -m $tagMessage
}

4

Jedes Commit hat einen eindeutigen Hash. Ansonsten gibt es in git keine Revisionsnummern. Sie müssen Commits selbst markieren, wenn Sie mehr Benutzerfreundlichkeit wünschen.


3

Ich möchte nur einen anderen möglichen Ansatz erwähnen - und zwar unter Verwendung von git Git-Notes (1) , die seit Version 1.6.6 ( Note to Self - Git ) existieren (ich verwende gitVersion 1.7.9.5).

Grundsätzlich habe ich git svnein SVN-Repository mit linearem Verlauf geklont (kein Standardlayout, keine Verzweigungen, keine Tags) und wollte die Revisionsnummern im geklonten gitRepository vergleichen. Dieser Git-Klon hat standardmäßig keine Tags, daher kann ich ihn nicht verwenden git describe. Die Strategie hier würde wahrscheinlich nur für die lineare Historie funktionieren - nicht sicher, wie sie sich bei Zusammenführungen usw. entwickeln würde; aber hier ist die grundlegende Strategie:

  • Fragen Sie git rev-listnach einer Liste aller Commit-Historien
    • Da dies rev-liststandardmäßig in "umgekehrter chronologischer Reihenfolge" erfolgt, verwenden wir den --reverseSchalter, um eine Liste der Commits zu erhalten, die zuerst nach den ältesten sortiert sind
  • Verwenden Sie bashShell, um
    • Erhöhen Sie eine Zählervariable bei jedem Commit als Revisionszähler.
    • Generieren und fügen Sie für jedes Commit eine "temporäre" Git-Notiz hinzu
  • Durchsuchen Sie dann das Protokoll mit git logwith --notes, wodurch auch die Notiz eines Commits ausgegeben wird, in diesem Fall die "Revisionsnummer".
  • Wenn Sie fertig sind, löschen Sie die temporären Notizen ( Hinweis: Ich bin nicht sicher, ob diese Notizen festgeschrieben sind oder nicht; sie werden nicht wirklich angezeigtgit status ).

Beachten Sie zunächst, dass gitNotizen einen Standardspeicherort haben. Sie können jedoch auch einen ref(Erence) für Notizen angeben , der sie in einem anderen Verzeichnis unter speichert .git. In einem gitRepo-Ordner können Sie beispielsweise anrufen, um git notes get-refzu sehen, welches Verzeichnis dies sein wird:

$ git notes get-ref
refs/notes/commits
$ git notes --ref=whatever get-ref
refs/notes/whatever

Zu beachten ist, dass Sie, wenn Sie notes addmit a arbeiten --ref, diese Referenz auch danach erneut verwenden müssen. Andernfalls werden möglicherweise Fehler wie " Keine Notiz für Objekt XXX gefunden ... " angezeigt .

In diesem Beispiel habe ich beschlossen, refdie Notizen "linrev" (für lineare Überarbeitung) zu nennen. Dies bedeutet auch, dass es unwahrscheinlich ist, dass die Prozedur bereits vorhandene Notizen stört. Ich benutze den --git-dirSchalter auch, da ich als gitNeuling einige Probleme hatte, ihn zu verstehen - also möchte ich mich "für später erinnern" :); und ich benutze auch --no-pagerzur Unterdrückung Laichen von lessbei der Verwendung git log.

Angenommen, Sie befinden sich in einem Verzeichnis mit einem Unterordner, myrepo_gitder ein gitRepository ist. man könnte tun:

### check for already existing notes:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.

### iterate through rev-list three, oldest first,
### create a cmdline adding a revision count as note to each revision

$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
  TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
  TCMD="$TCMD add $ih -m \"(r$((++ix)))\""; \
  echo "$TCMD"; \
  eval "$TCMD"; \
done

# git --git-dir=./myrepo_git/.git notes --ref linrev add 6886bbb7be18e63fc4be68ba41917b48f02e09d7 -m "(r1)"
# git --git-dir=./myrepo_git/.git notes --ref linrev add f34910dbeeee33a40806d29dd956062d6ab3ad97 -m "(r2)"
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev add 04051f98ece25cff67e62d13c548dacbee6c1e33 -m "(r15)"

### check status - adding notes seem to not affect it:

$ cd myrepo_git/
$ git status
# # On branch master
# nothing to commit (working directory clean)
$ cd ../

### check notes again:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# (r15)

### note is saved - now let's issue a `git log` command, using a format string and notes:

$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)
# 77f3902: _user_: Sun Apr 21 18:29:00 2013 +0000:  >>test message 14<< (r14)
# ...
# 6886bbb: _user_: Sun Apr 21 17:11:52 2013 +0000:  >>initial test message 1<< (r1)

### test git log with range:

$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)

### erase notes - again must iterate through rev-list

$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
  TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
  TCMD="$TCMD remove $ih"; \
  echo "$TCMD"; \
  eval "$TCMD"; \
done
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# Removing note for object 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# git --git-dir=./myrepo_git/.git notes --ref linrev remove f34910dbeeee33a40806d29dd956062d6ab3ad97
# Removing note for object f34910dbeeee33a40806d29dd956062d6ab3ad97
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 04051f98ece25cff67e62d13c548dacbee6c1e33
# Removing note for object 04051f98ece25cff67e62d13c548dacbee6c1e33

### check notes again:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.

Zumindest in meinem speziellen Fall einer vollständig linearen Historie ohne Verzweigungen scheinen die Revisionsnummern mit diesem Ansatz git logübereinzustimmen - und außerdem scheint es, dass dieser Ansatz die Verwendung mit Revisionsbereichen ermöglicht, während immer noch die richtigen Revisionsnummern erhalten werden - YMMV mit einem anderen Kontext, obwohl ...

Hoffe das hilft jemandem,
Prost!


EDIT: Ok, hier ist es ein bisschen einfacher, mit gitAliasnamen für die obigen Schleifen, genannt setlinrevund unsetlinrev; Wenn Sie sich in Ihrem Git-Repository-Ordner befinden, tun Siebash dies ( Beachten Sie das böse Entkommen, siehe auch # 16136745 - Hinzufügen eines Git-Alias ​​mit einem Semikolon ):

cat >> .git/config <<"EOF"
[alias]
  setlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
      TCMD=\"git notes --ref linrev\"; \n\
      TCMD=\"$TCMD add $ih -m \\\"(r\\$((++ix)))\\\"\"; \n\
      #echo \"$TCMD\"; \n\
      eval \"$TCMD\"; \n\
    done; \n\
    echo \"Linear revision notes are set.\" '"

  unsetlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
      TCMD=\"git notes --ref linrev\"; \n\
      TCMD=\"$TCMD remove $ih\"; \n\
      #echo \"$TCMD\"; \n\
      eval \"$TCMD 2>/dev/null\"; \n\
    done; \n\
    echo \"Linear revision notes are unset.\" '"
EOF

... damit Sie einfach aufrufen können, git setlinrevbevor Sie versuchen, ein Protokoll mit linearen Revisionsnotizen zu erstellen; und git unsetlinrevdiese Notizen zu löschen, wenn Sie fertig sind; Ein Beispiel aus dem Git-Repo-Verzeichnis:

$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 <<

$ git setlinrev
Linear revision notes are set.
$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)
$ git unsetlinrev
Linear revision notes are unset.

$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 <<

Die Zeit, die die Shell benötigt, um diese Aliase zu vervollständigen, hängt von der Größe des Repository-Verlaufs ab.


2

Für Personen mit einem Ant- Build-Prozess können Sie eine Versionsnummer für ein Projekt auf Git mit diesem Ziel generieren:

<target name="generate-version">

    <exec executable="git" outputproperty="version.revisions">
        <arg value="log"/>
        <arg value="--oneline"/>
    </exec>

    <resourcecount property="version.revision" count="0" when="eq">
        <tokens>
            <concat>
                <filterchain>
                    <tokenfilter>
                        <stringtokenizer delims="\r" />
                    </tokenfilter>
                </filterchain>
            <propertyresource name="version.revisions" />
            </concat>
        </tokens>
    </resourcecount>
    <echo>Revision : ${version.revision}</echo>

    <exec executable="git" outputproperty="version.hash">
        <arg value="rev-parse"/>
        <arg value="--short"/>
        <arg value="HEAD"/>
    </exec>
    <echo>Hash : ${version.hash}</echo>


    <exec executable="git" outputproperty="version.branch">
        <arg value="rev-parse"/>
        <arg value="--abbrev-ref"/>
        <arg value="HEAD"/>
    </exec>
    <echo>Branch : ${version.branch}</echo>

    <exec executable="git" outputproperty="version.diff">
        <arg value="diff"/>
    </exec>

    <condition property="version.dirty" value="" else="-dirty">
        <equals arg1="${version.diff}" arg2=""/>
    </condition>

    <tstamp>
        <format property="version.date" pattern="yyyy-mm-dd.HH:mm:ss" locale="en,US"/>
    </tstamp>
    <echo>Date : ${version.date}</echo>

    <property name="version" value="${version.revision}.${version.hash}.${version.branch}${version.dirty}.${version.date}" />

    <echo>Version : ${version}</echo>

    <echo file="version.properties" append="false">version = ${version}</echo>

</target>

Das Ergebnis sieht folgendermaßen aus:

generate-version:
    [echo] Generate version
    [echo] Revision : 47
    [echo] Hash : 2af0b99
    [echo] Branch : master
    [echo] Date : 2015-04-20.15:04:03
    [echo] Version : 47.2af0b99.master-dirty.2015-04-20.15:04:03

Das Dirty-Flag ist hier, wenn Sie Dateien haben, die beim Generieren der Versionsnummer nicht festgeschrieben wurden. Denn normalerweise muss sich beim Erstellen / Packen Ihrer Anwendung jede Codeänderung im Repository befinden.


1

Zusammen mit der SHA-1-ID des Commits hätten Datum und Uhrzeit der Serverzeit geholfen?

Etwas wie das:

Das Festschreiben erfolgte am 19. August 2013 um 11:30:25 Uhr und wurde als 6886bbb7be18e63fc4be68ba41917b48f02e09d7_19aug2013_113025 angezeigt


1

Tags aus dem Git-Handbuch sind eine brillante Antwort auf dieses Problem:

Das Erstellen eines mit Anmerkungen versehenen Tags in Git ist einfach. Am einfachsten ist es, -a anzugeben, wenn Sie den Tag-Befehl ausführen:

$ git tag -a v1.4 -m 'my version 1.4'

$ git tag
v0.1
v1.3
v1.4

Schauen Sie sich 2.6 Git Basics - Tagging an


Schade, dass Sie durch Reifen springen müssen, um die By default, the git push command doesn’t transfer tags to remote servers.
Standardeinstellungen

1

Wir verwenden diesen Befehl, um Version und Revision von git abzurufen:

git describe --always --tags --dirty

Es kehrt zurück

  • commit Hash als Revisions wenn keine Markierung verwendet wird ( zum Beispiel gcc7b71f)
  • Tag-Name als Version auf einem Tag (z. B. v2.1.0für Releases verwendet)
  • Tag - Name, Revisionsnummer seit dem letzten Tag und zu begehen , wenn nach einem Hash - Tag (z v5.3.0-88-gcc7b71f)
  • wie oben plus einem „schmutziger“ tag , wenn der Arbeitsbaum lokale Änderungen (zB hat v5.3.0-88-gcc7b71f-dirty)

Siehe auch: https://www.git-scm.com/docs/git-describe#Documentation/git-describe.txt


0

Post-Build-Ereignis für Visual Studio

echo  >RevisionNumber.cs static class Git { public static int RevisionNumber =
git  >>RevisionNumber.cs rev-list --count HEAD
echo >>RevisionNumber.cs ; }

-1

Betrachten Sie zu verwenden

git-rev-label

Gibt Informationen zur Git-Repository-Revision in einem Format wie master-c73-gabc6bec. Kann Vorlagenzeichenfolge oder -datei mit Umgebungsvariablen und Informationen von Git füllen. Nützlich, um Informationen zur Version des Programms bereitzustellen: Zweig, Tag, Commit-Hash, Commit-Anzahl, Dirty-Status, Datum und Uhrzeit. Eines der nützlichsten Dinge ist die Anzahl der Commits, wobei zusammengeführte Zweige nicht berücksichtigt werden - nur der erste Elternteil.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.