Qual è l'equivalente Git per il numero di revisione?


244

Usiamo SVN al lavoro, ma per i miei progetti personali ho deciso di usare Git. Quindi ho installato Git ieri e mi chiedo quale sia l' equivalente del numero di revisione in Git .

Supponiamo di lavorare sulla versione 3.0.8 e ogni correzione di bug ha il proprio numero di revisione che possiamo usare quando parliamo di questa correzione di bug. Quindi, se taggo il codice in Git su 3.0.8, cosa posso usare come numero di revisione o qualche altro tipo di identificazione più dettagliato? Trovo l'hash non così facile da usare per gli umani.



C'è un articolo per una delle possibili soluzioni. Potrebbe sembrare un po 'pesante ma integrato nell'output di "git log" e non richiede altri comandi oltre a "git push / pull / fetch".
Dmitry Pavlenko,

Peccato che l'articolo collegato di @DmitryPavlenko sia su un dominio morto: gitsvn.x10.mx. Senza alcuna indicazione sull'argomento, sarà difficile per chiunque trovarlo altrove.
Michael Donohue,

Nota: non è più necessario abbrev con git descrivere: vedi stackoverflow.com/a/41308073/6309
VonC

1
No, Laurence Gonsalves, questo non è un duplicato di "come ottenere il conteggio del commit git?" - si tratta del numero di versione, e anche se il conteggio dei commit può essere modificato in modo che si assomigli un po 'allo stesso modo - la versione hash è molto diversa rispetto al conteggio dei commit :-)
David Svarrer,

Risposte:


149

Buone o cattive notizie per te, che l'hash È il numero di revisione. Ho anche avuto problemi con questo quando ho fatto il passaggio da SVN a git.

Puoi usare "tagging" in git per taggare una certa revisione come "release" per una versione specifica, facilitando il riferimento a quella revisione. Dai un'occhiata a questo post sul blog .

La cosa chiave da capire è che git non può avere numeri di revisione - pensa alla natura decentralizzata. Se gli utenti A e B si impegnano entrambi nei loro repository locali, come può git ragionevolmente assegnare un numero di revisione sequenziale? A non ha conoscenza di B prima che si spingano / tirino l'un l'altro le modifiche.

Un'altra cosa da guardare è la ramificazione semplificata per i rami bugfix:

Inizia con una versione: 3.0.8. Quindi, dopo quella versione, procedere come segue:

git branch bugfixes308

Questo creerà un ramo per le correzioni dei bug. Dai un'occhiata alla filiale:

git checkout bugfixes308

Ora apporta le modifiche alla correzione dei bug che desideri.

git commit -a

Commettili e torna al ramo principale:

git checkout master

Quindi inserisci le modifiche dall'altro ramo:

git merge bugfixes308

In questo modo, hai un ramo bugfix separato specifico per il rilascio, ma stai ancora inserendo le modifiche bugfix nel tuo trunk sviluppatore principale.


11
Ho capito che l'hash è il numero di revisione, ma speravo non fosse :-))) grazie per la spiegazione molto bella e per il suggerimento ora di affrontarlo.
Radek,

3
Prego. Ero molto frustrato con Git quando l'ho raccolto per la prima volta da SVN, ma ora
oscillo

4
Inoltre, è da un po 'di tempo che non l'ho pubblicato, ma ricorda che puoi anche fare "git checkout -b new_branch_name" per fare "git branch foo" e "git checkout foo" come una riga.
Makdad,

1
Ho ragione che gli hash sono hash "veri" e nemmeno remotamente sequenziali? Quindi, soprattutto, se il database dei bug dice fixed in 547cc3e..c4b2eba, e hai qualche altra revisione, non hai idea se il tuo codice dovrebbe contenere la correzione ?! Sicuramente i git di git-central hanno una soluzione per questo?!?!
Olie,

3
In SVN, il fatto che un bug sia stato corretto in r42 non ti dice se è stato corretto anche in r43 non appena usi effettivamente i rami.
Matthieu Moy,

186

Con Git moderno (1.8.3.4 nel mio caso) e non usando i rami puoi fare:

$ git rev-list --count HEAD
68

22
Considera di usaregit rev-list --count --first-parent HEAD
Flimm il

8
Date queste informazioni (il numero 68), c'è un modo per determinare la revisione per riacquisire il codice? Supponiamo che la "revisione 68" venga rilasciata in un ambiente di test, lo sviluppo continua e in seguito uno sviluppatore deve riacquistare la "revisione 68" dal controllo del codice sorgente. Come sceglierebbe la clonazione della versione specifica? O mi manca qualcosa su Git che lo rende inutile?
David,

9
Tieni presente che questa soluzione produrrebbe risultati diversi per sviluppatori diversi. Inoltre, il calcolo all'indietro dal "conteggio" al commit produrrebbe commit diversi per sviluppatori diversi !! Ciò è dovuto alla natura distribuita di Git e che gli commit avvengono in diversi repository durante lo stesso periodo di tempo, ma potrebbero non essere conteggiati a git rev-list --count HEADseconda di quando sono stati effettuati gli ultimi push e pull.
Jason,

2
@Jason, il commento di David sull'aggiungere risolve la --first-parenttua preoccupazione? Odierei evitare una soluzione apparentemente più semplice a causa di un raro caso limite se esiste una soluzione altrettanto semplice o un modo per renderlo più robusto.
MarkHu,

4
@MarkHu, --first-parentaiuta. Finché non viene eseguito alcun rebasing e lo stesso ramo viene sempre utilizzato per creare rilasci (e ovviamente per calcolare questo numero di rilascio), penso che questo possa essere usato. Tuttavia, sono ancora incerto che identificherà sempre in modo univoco il commit da cui proviene la versione. Ci sono così tante cose che possono andare storte qui ... ma al momento non riesco a pensare a qualcosa che possa sicuramente rompere questo (date le mie affermazioni "fintanto che" sopra). Il git describemetodo menzionato in un'altra risposta è la strada da percorrere. Crea un tag se vuoi qualcosa di leggibile dall'uomo.
Jason,

104

Il git describecomando crea un nome leggermente più leggibile dall'uomo che si riferisce a un commit specifico. Ad esempio, dalla documentazione:

Con qualcosa come git.git albero attuale, ottengo:

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

cioè l'attuale capo del mio ramo "genitore" si basa sulla v1.0.4, ma dato che ha alcuni commit oltre a ciò, descrivi ha aggiunto il numero di commit aggiuntivi ("14") e un nome oggetto abbreviato per il commit stesso ("2414721") alla fine.

Fintanto che si utilizzano tag denominati in modo ragionevole per contrassegnare rilasci particolari, questo può essere considerato approssimativamente equivalente a un "numero di revisione" SVN.


7
Vorrei solo notare che questo funziona solo se il tuo gitrepository ha già dei tag; in caso contrario, potresti ottenere che git descrive non riesce con "fatale: nessun nome trovato, non puoi descrivere nulla". - Stack Overflow ; nel senso che dovresti impostare tu stesso i tag.
sdaau,

14
@sdaau: se lo stai usando in uno script o qualcosa del genere e non vuoi git describemai fallire, usa l' git describe --alwaysopzione.
Greg Hewgill,

L'output di può git describeessere usato per trovare il commit della fonte, in qualche modo? A meno che il conteggio manuale si impegna nel registro, intendo.
Lii,

@Lii: cosa intendi con "commit della fonte"? Sia il tag più vicino ( v1.0.4) che il più recente commit id ( 2414721) fanno già parte dell'output di descrizione git.
Greg Hewgill,

@GregHewgill: Sì, grazie, quando ho posto la domanda non mi sono reso conto che il "nome oggetto abbreviato" è un valore che può essere utilizzato per identificare il commit. È geniale!
Lii,

67

Gli altri poster hanno ragione, non esiste un "numero di revisione".

Penso che il modo migliore sia usare i tag per le "versioni"!

Ma ho usato quanto segue per falsificare i numeri di revisione (solo per i clienti di vedere le revisioni e i progressi, in quanto volevano avere le stesse revisioni crescenti da Git che erano abituate da sovversione).

Mostra che la "revisione corrente" di "HEAD" è simulata usando questo:

git rev-list HEAD | wc -l

Ma cosa succede se il client mi dice che c'è un bug nella "revisione" 1302?

Per questo ho aggiunto quanto segue alla sezione [alias] del mio ~ / .gitconfig:

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

usando git show-rev-number 1302verrà quindi stampato l' hash per la "revisione" :)

Ho pubblicato un post sul blog (in tedesco) su quella "tecnica" qualche tempo fa.


@Radek - "a volte è necessario sapere cosa 'modifica del codice = commit' ha risolto qualcosa" - quindi git bisect(link) è lo strumento appropriato per identificare cosa è cambiato quando da chi.
michael,

@Radek Sì, è un numero sempre crescente. Conta solo le revisioni registrate su HEAD. Quindi ogni commit è una nuova revisione. Questo non funzionerà per diversi rami.
OderWat,

1
Mi piace la tua soluzione. Si noti che è possibile semplificarlo: show-rev-number =! Sh -c 'git rev-list --reverse HEAD | awk NR == $ 0 '
avner

@avner Grazie! Ovviamente non ho usato molto awk nella mia vita :)
OderWat,

3
Ho dovuto usaregit rev-list --reverse HEAD | awk "{ print NR }" | tail -n 1
Gerry il

27

Git non ha lo stesso concetto di numeri di revisione di sovversione. Invece ogni dato snapshot fatto con un commit è taggato da un checksum SHA1. Perché? Esistono diversi problemi con un revno in esecuzione in un sistema di controllo della versione distribuita:

Innanzitutto, poiché lo sviluppo non è affatto lineare, l'attaccamento di un numero è piuttosto difficile come un problema da risolvere in un modo che soddisferà le tue esigenze di programmatore. Cercare di risolvere questo problema aggiungendo un numero potrebbe diventare rapidamente problematico quando il numero non si comporta come previsto.

In secondo luogo, i numeri di revisione possono essere generati su macchine diverse. Ciò rende molto più difficile la sincronizzazione dei numeri, soprattutto perché la connettività è a senso unico; potresti non avere nemmeno accesso a tutte le macchine che hanno il repository.

In terzo luogo, in git, in qualche modo sperimentato dall'ormai defunto sistema OpenCM, l' identità di un commit (che cos'è il commit) è equivalente al suo nome (l'id SHA). Questo concetto di denominazione = identità è molto forte. Quando ti siedi con un nome di commit in mano, identifica anche il commit in modo imperdonabile. Questo a sua volta ti consente di controllare tutti i tuoi commit alla prima iniziale per corruzione con il git fsckcomando.

Ora, poiché abbiamo un DAG (Directed Acyclic Graph) di revisioni e queste costituiscono l'albero corrente, abbiamo bisogno di alcuni strumenti per risolvere il tuo problema: come discriminare le diverse versioni. Innanzitutto, puoi omettere parte dell'hash se un determinato prefisso, ad esempio 1516bd , identifica in modo univoco il tuo commit. Ma anche questo è piuttosto inventato. Invece, il trucco è usare tag e / o rami. Un tag o un ramo è simile a una "nota gialla" che si collega a un determinato ID SHA1 di commit. In sostanza, i tag sono pensati per essere non mobili, mentre un ramo si sposterà quando vengono fatti nuovi commit nella sua TESTA. Ci sono modi per fare riferimento a un commit attorno a un tag o ramo, vedere la pagina man di git-rev-parse.

Di solito, se devi lavorare su un pezzo di codice specifico, quel pezzo sta subendo delle modifiche e come tale dovrebbe essere un ramo con un nome di argomento detto. Creare un sacco di rami (20-30 per programmatore non è inaudito, con 4-5 pubblicati per altri su cui lavorare) è il trucco per un git efficace. Ogni lavoro dovrebbe iniziare come un proprio ramo e poi essere unito quando viene testato. I rami inediti possono essere riscritti interamente e questa parte della distruzione della storia è una forza di chiacchiere.

Quando il cambiamento è accettato in maestro, si congela in qualche modo e diventa archeologia. A quel punto, puoi etichettarlo, ma più spesso viene fatto un riferimento a un particolare commit in un bug tracker o in un tracker di problemi tramite la somma sha1. I tag tendono ad essere riservati ai dossi della versione e ai punti di diramazione per i rami di manutenzione (per le vecchie versioni).


18

Se sei interessato, ho gestito automaticamente i numeri di versione dalle informazioni git qui sotto il formato

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

dove build è il numero totale di commit. Vedrai il codice interessante nel Makefile. Ecco la parte pertinente per accedere alle diverse parti del numero di versione:

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

Una funzione Bash:

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}
}

produce qualcosa di simile

$ git_rev
2:0f8e14e:20130220

Questo è

commit_count:last_abbrev_commit:date_YYmmdd

Questo genere di cose potrebbe essere utile, ma se si è interessati ai numeri di versione incrementali, si scambieranno le posizioni dei campi in modo che l'hash (non incrementale) sia l'ultimo.
MarkHu

8

L' hash SHA1 del commit è equivalente a un numero di revisione di Subversion.


7
Sfortunatamente ha proprietà abbastanza diverse da un numero di revisione. È piuttosto lungo e non aumenta monotono. Suppongo che sia il prezzo da pagare per la distribuzione ...
CodesInChaos

1
@CodeInChaos: so a cosa stai arrivando, ma è generalmente possibile fare riferimento a commit git con solo i primi 6 o 8 caratteri del codice hash.
Chris Pitman,

5
@Radek: non sono garantiti unici (anche se trovi una collisione puoi vincere una piccola quantità di celebrità).
Slartibartfast,

8
@Radek Secondo en.wikipedia.org/wiki/Collision_attack , con 4 caratteri dell'hash hai un ID a 16 bit, il che significa che in un repository con 256 (= 2 ^ (16/2)) si commette un 50 % di probabilità che due commit abbiano lo stesso prefisso a quattro caratteri (e con 65536 commit è certo, da allora l'intervallo di ID a 4 caratteri è esaurito). Quando aggiungi un carattere, hai un ID a 20 bit, il che significa che la soglia del 50% è a 1024 commit. Ma poiché si tratta di un parametro statistico, nulla garantisce che tali collisioni non avvengano prima.
Rudi,

2
Poiché l'hash si basa sul contenuto, è ancora probabile che due commit abbiano lo stesso prefisso hash, non una certezza. A 65536 commit è molto probabile che due abbiano lo stesso prefisso a quattro caratteri, ma non è ancora certo. Per inciso, l'hash completo non ha una collisione ancora, ma git sta lavorando su di esso :) stackoverflow.com/questions/3475648/...
goodeye

6

Questo è ciò che ho fatto nel mio makefile sulla base di altre soluzioni. Nota non solo questo dà al tuo codice un numero di revisione, ma aggiunge anche l'hash che ti consente di ricreare la versione.

# 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
Sembra il modo più sicuro di usare git-describeper evitare errori, è con git describe --always --dirty --long --tagsquale funziona in tutti i casi che mi vengono in mente.
MarkHu,

5

Il problema con l'uso dell'hash git come numero di build è che non sta aumentando monotonicamente. OSGi suggerisce di utilizzare un timestamp per il numero di build. Sembra che il numero di commit nel ramo possa essere usato al posto della sovversione o del numero di modifica della forza.


5

Ho scritto alcune utility di PowerShell per recuperare informazioni sulla versione da Git e semplificare la codifica

funzioni: 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

Ogni commit ha un hash unico. A parte questo, non ci sono numeri di revisione in git. Dovrai taggare te stesso se vuoi una maggiore facilità d'uso.


3

Vorrei solo notare un altro possibile approccio - e cioè usando git git-notes (1) , esistente dalla v 1.6.6 ( Note a Self - Git ) (Sto usandogit versione 1.7.9.5).

Fondamentalmente, ero solito git svnclonare un repository SVN con cronologia lineare (senza layout standard, senza rami, senza tag) e volevo confrontare i numeri di revisione nel gitrepository clonato . Questo clone git non ha tag di default, quindi non posso usarlo git describe. La strategia qui probabilmente funzionerebbe solo per la storia lineare - non sono sicuro di come andrebbe a finire con le fusioni ecc .; ma ecco la strategia di base:

  • Richiedi l' git rev-listelenco di tutta la cronologia di commit
    • Dal momento che rev-listè di default in "ordine cronologico inverso", useremmo il suo --reverseinterruttore per ottenere l'elenco dei commit ordinati per primi
  • Usa bashshell per
    • aumentare una variabile contatore per ogni commit come contatore di revisione,
    • genera e aggiungi una nota git "temporanea" per ogni commit
  • Quindi, sfogliare il registro usando git logcon --notes, che scaricherà anche una nota di commit, che in questo caso sarebbe il "numero di revisione"
  • Al termine, cancella le note temporanee ( NB: non sono sicuro che queste note siano impegnate o meno; in realtà non vengono visualizzategit status )

Innanzitutto, notiamo che githa una posizione predefinita di note - ma puoi anche specificare un ref(erence) per le note - che le memorizzerebbe in una directory diversa in .git; ad esempio, mentre ci si trova in una gitcartella repo, è possibile chiamare git notes get-refper vedere quale directory sarà:

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

La cosa da notare è che se si notes addutilizza un --ref, è necessario anche utilizzare nuovamente quel riferimento, altrimenti si potrebbero ottenere errori come " Nessuna nota trovata per l'oggetto XXX ... ".

Per questo esempio, ho scelto di chiamare le refnote "linrev" (per la revisione lineare); ciò significa anche che non è probabile che la procedura interferisca con le note già esistenti. Sto anche usando lo --git-dirswitch, dato che essendo un gitprincipiante, ho avuto qualche problema a capirlo - quindi mi piacerebbe "ricordare per dopo" :); e uso anche --no-pagerper sopprimere la generazione di lessquando si usa git log.

Quindi, supponendo che ti trovi in ​​una directory, con una sottocartella myrepo_gitche è un gitrepository; si potrebbe fare:

### 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.

Quindi, almeno nel mio caso specifico di storia completamente lineare senza rami, i numeri di revisione sembrano corrispondere a questo approccio - e inoltre, sembra che questo approccio consentirà l'utilizzo git logcon intervalli di revisione, pur ottenendo i giusti numeri di revisione - YMMV con un contesto diverso, sebbene ...

Spero che questo aiuti qualcuno,
Salute!


EDIT: Ok, qui è un po 'più semplice, con gitalias per i loop sopra, chiamato setlinreve unsetlinrev; quando sei nella cartella del tuo repository git, fai ( Nota la cattiva bashfuga, vedi anche # 16136745 - Aggiungi un alias Git contenente un punto e virgola ):

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

... quindi puoi semplicemente invocare git setlinrevprima di provare a fare il log che coinvolge note di revisione lineari; e git unsetlinrevper eliminare quelle note quando hai finito; un esempio dall'interno della directory repository git:

$ 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 <<

Il tempo impiegato dalla shell per completare questi alias dipende dalla dimensione della cronologia del repository.


2

Per le persone che hanno una formica processo di compilazione, è possibile generare un numero di versione per un progetto su git con questo target:

<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>

Il risultato è simile al seguente:

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

Il flag sporco è qui quando non hai eseguito il commit dei file quando generi il numero di versione. Perché di solito, quando crei / impacchetti la tua applicazione, ogni modifica del codice deve essere nel repository.


1

Insieme all'ID SHA-1 del commit, la data e l'ora dell'ora del server avrebbero aiutato?

Qualcosa come questo:

il commit è avvenuto alle 11:30:25 il 19 agosto 2013 come mostrato da 6886bbb7be18e63fc4be68ba41917b48f02e09d7_19aug2013_113025


1

Dal manuale di Git, i tag sono una risposta brillante a questo problema:

La creazione di un tag annotato in Git è semplice. Il modo più semplice è specificare -a quando si esegue il comando tag:

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

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

Scopri 2.6 Nozioni di base su Git - Tagging


Peccato che devi saltare attraverso i cerchi per cambiare le impostazioni predefinite:By default, the git push command doesn’t transfer tags to remote servers.
MarkHu

1

Stiamo usando questo comando per ottenere la versione e la revisione da git:

git describe --always --tags --dirty

Ritorna

  • commettere l'hash come revisione quando non viene utilizzata la codifica (ad es. gcc7b71f)
  • nome tag come versione quando su un tag (ad esempio v2.1.0, utilizzato per le versioni)
  • nome del tag, numero di revisione dall'ultimo tag e hash di commit dopo un tag (ad es. v5.3.0-88-gcc7b71f)
  • come sopra più un tag "sporco" se l'albero di lavoro ha modifiche locali (ad es. v5.3.0-88-gcc7b71f-dirty)

Vedi anche: https://www.git-scm.com/docs/git-describe#Documentation/git-describe.txt


0

Evento post build per Visual Studio

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

-1

Considerare di usare

git-rev-label

Fornisce informazioni sulla revisione del repository Git in formato simile master-c73-gabc6bec. Può riempire la stringa o il file di modello con variabili di ambiente e informazioni da Git. Utile per fornire informazioni sulla versione del programma: branch, tag, hash commit, commit commit, stato sporco, data e ora. Una delle cose più utili è il conteggio dei commit, non tenendo conto delle filiali unite - solo il primo genitore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.