¿Cuál es el equivalente de Git para el número de revisión?


244

Usamos SVN en el trabajo, pero para mis proyectos personales decidí usar Git. Así que instalé Git ayer, y me pregunto cuál es el número de revisión equivalente en Git .

Digamos que trabajamos en la versión 3.0.8 y cada corrección de errores tiene su propio número de revisión que podemos usar cuando hablamos de esta corrección de errores. Entonces, si etiqueto el código en Git a 3.0.8, ¿qué puedo usar como número de revisión o algún otro tipo de identificación más detallado? Me parece que el hash no es tan fácil de usar para los humanos.



Hay un artículo para una de las posibles soluciones. Puede parecer un poco pesado pero integrado en la salida "git log" y no requiere comandos adicionales aparte de "git push / pull / fetch".
Dmitry Pavlenko

Desafortunadamente, el artículo vinculado de @DmitryPavlenko está en un dominio muerto: gitsvn.x10.mx. Sin indicación del tema, será difícil para cualquiera encontrarlo en otro lugar.
Michael Donohue

Nota: no se necesita más abreviatura con git describe: consulte stackoverflow.com/a/41308073/6309
VonC

1
No, Laurence Gonsalves, esto no es un duplicado de "¿cómo obtener el conteo de git commit?" - se trata del número de versión, y aunque el recuento de confirmaciones se puede modificar para que se parezca un poco - la versión hash es muy diferente al recuento de confirmaciones :-)
David Svarrer el

Respuestas:


149

Buenas o malas noticias para ti, ese hash ES el número de revisión. También tuve problemas con esto cuando hice el cambio de SVN a git.

Puede usar "etiquetar" en git para etiquetar una determinada revisión como "lanzamiento" para una versión específica, lo que facilita la referencia a esa revisión. Mira esta publicación de blog .

La clave para entender es que git no puede tener números de revisión: piense en la naturaleza descentralizada. Si los usuarios A y B se comprometen con sus repositorios locales, ¿cómo puede git asignar razonablemente un número de revisión secuencial? A no tiene conocimiento de B antes de que empujen / tiren de los cambios del otro.

Otra cosa a tener en cuenta es la ramificación simplificada para las ramas de corrección de errores:

Comience con una versión: 3.0.8. Luego, después de ese lanzamiento, haga esto:

git branch bugfixes308

Esto creará una rama para la corrección de errores. Pagar la sucursal:

git checkout bugfixes308

Ahora realice los cambios de corrección de errores que desee.

git commit -a

Compromételos y vuelve a la rama maestra:

git checkout master

Luego, aplique esos cambios desde la otra rama:

git merge bugfixes308

De esa manera, tiene una rama de corrección de errores específica de la versión separada, pero aún está arrastrando los cambios de corrección de errores en su tronco de desarrollo principal.


11
Comprendí que hash es el número de revisión, pero esperaba que no lo fuera :-))) gracias por una muy buena explicación y por la sugerencia de tratarlo.
Radek el

3
De nada. Estaba muy frustrado con git cuando lo recogí por primera vez de SVN, pero ahora me giro hacia el otro lado ...
#

44
TAMBIÉN, ha pasado un tiempo desde que publiqué esto, pero recuerda que también puedes hacer "git checkout -b new_branch_name" para hacer "git branch foo" y "git checkout foo" como una frase.
makdad

1
¿Estoy en lo cierto de que los hashes son hash "verdaderos" y ni siquiera remotamente secuenciales? Entonces, lo más importante, si la base de datos de errores dice fixed in 547cc3e..c4b2eba, y tiene alguna otra revisión, ¡no tiene idea de si su código debe contener o no la solución! Seguramente los gits en git-central tienen una solución para esto?!?!
Olie

3
En SVN, el hecho de que un error se corrija en r42 no le dice si también se corrigió en r43 tan pronto como utiliza las ramas.
Matthieu Moy

186

Con Git moderno (1.8.3.4 en mi caso) y sin usar ramas, puede hacer:

$ git rev-list --count HEAD
68

22
Considere usargit rev-list --count --first-parent HEAD
Flimm

8
Dada esta información (el número 68), ¿hay alguna forma de determinar la revisión para volver a adquirir el código? Suponga que la "revisión 68" se lanza a un entorno de prueba, el desarrollo continúa y luego un desarrollador necesita volver a adquirir la "revisión 68" del control de origen. ¿Cómo apuntaría él a la versión específica para clonar? ¿O me estoy perdiendo algo sobre Git que hace que esto sea innecesario?
David

99
Tenga en cuenta que esta solución produciría resultados diferentes para diferentes desarrolladores. ¡Además, calcular hacia atrás desde el "conteo" hasta el compromiso produciría diferentes compromisos para diferentes desarrolladores! Esto se debe a la naturaleza distribuida de Git y que las confirmaciones ocurren en diferentes repositorios durante el mismo período de tiempo, pero es posible que no se cuenten en git rev-list --count HEADfunción de cuándo se realizaron los últimos empujones y tirones.
Jason

2
@Jason, ¿el comentario de David sobre agregar --first-parentaborda su preocupación? Odiaría evitar una solución aparentemente más simple debido a un caso marginal poco común si existe una solución o una forma igualmente simple de hacerlo más robusto.
MarkHu

44
@ MarkHu, --first-parentayuda. Siempre que no se realice un rebase y se use siempre la misma rama para hacer lanzamientos (y calcular este número de lanzamiento, por supuesto), creo que esto podría usarse. Sin embargo, todavía no estoy seguro de que siempre identifique de manera única el compromiso del que proviene el lanzamiento. Hay tantas cosas que pueden salir mal aquí ... pero por el momento no puedo pensar en algo que definitivamente rompa esto (dadas mis declaraciones anteriores "siempre y cuando"). El git describemétodo mencionado en otra respuesta es el camino a seguir. Crea una etiqueta si quieres algo legible por humanos.
Jason

104

El git describecomando crea un nombre ligeramente más legible para humanos que se refiere a una confirmación específica. Por ejemplo, de la documentación:

Con algo como git.git árbol actual, obtengo:

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

es decir, el encabezado actual de mi rama "principal" se basa en v1.0.4, pero dado que tiene algunas confirmaciones además de eso, describe ha agregado el número de confirmaciones adicionales ("14") y un nombre de objeto abreviado para la confirmación en sí ("2414721") al final.

Siempre que use etiquetas con nombres razonables para etiquetar lanzamientos particulares, esto puede considerarse aproximadamente equivalente a un "número de revisión" SVN.


77
Solo me gustaría señalar que esto funciona solo si su gitrepositorio ya tiene etiquetas; de lo contrario, es posible que git describe falle con "fatal: no se encontraron nombres, no se puede describir nada". - Desbordamiento de pila ; lo que significa que tendría que configurar las etiquetas usted mismo.
sdaau

14
@sdaau: Si está usando esto en un script o algo y no quiere git describefallar nunca, use la git describe --alwaysopción
Greg Hewgill

¿Se git describepuede usar la salida de para encontrar la confirmación de origen, de alguna manera? A falta de contar manualmente las confirmaciones en el registro, quiero decir.
Lii

@Lii: ¿Qué quieres decir con "compromiso de origen"? Tanto la etiqueta más cercana ( v1.0.4) como la identificación de confirmación más reciente ( 2414721) ya forman parte de la salida de git describe.
Greg Hewgill

@GregHewgill: Sí, gracias, cuando hice la pregunta no me di cuenta de que el "nombre de objeto abreviado" es un valor que se puede usar para identificar la confirmación. ¡Eso es brillante!
Lii

67

Los otros carteles tienen razón, no hay un "número de revisión".

¡Creo que la mejor manera es usar etiquetas para "lanzamientos"!

Pero hice uso de los siguientes números de revisión falsos (solo para que los clientes vean las revisiones y el progreso, ya que querían tener las mismas revisiones crecientes de git que las que usaban por subversión).

Mostrar la "revisión actual" de "HEAD" se simula usando esto:

git rev-list HEAD | wc -l

Pero, ¿qué pasa si el cliente me dice que hay un error en la "revisión" 1302?

Para esto, agregué lo siguiente a la sección [alias] de mi ~ / .gitconfig:

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

usando git show-rev-number 1302luego imprimirá el hash para la "revisión" :)

Hice una publicación de blog (en alemán) sobre esa "técnica" hace algún tiempo.


@Radek - "a veces necesitamos saber qué 'cambio de código = confirmar' arregló algo" - entonces git bisect(enlace) es la herramienta adecuada para identificar qué cambió cuándo quién lo cambió.
michael

@Radek Sí, es un número cada vez mayor. Solo cuenta las revisiones que registró en el HEAD. Entonces cada commit es una nueva revisión. Esto no funcionará para diferentes ramas.
OderWat

1
Me gusta tu solución Tenga en cuenta que puede simplificarlo: show-rev-number =! Sh -c 'git rev-list --reverse HEAD | awk NR == $ 0 '
avner

@avner ¡Gracias! No
usé

3
Tuve que usargit rev-list --reverse HEAD | awk "{ print NR }" | tail -n 1
Gerry

27

Git no tiene el mismo concepto de números de revisión que subversión. En cambio, cada instantánea realizada con una confirmación se etiqueta con una suma de verificación SHA1. ¿Por qué? Existen varios problemas con un revno en ejecución en un sistema de control de versiones distribuido:

Primero, dado que el desarrollo no es lineal en absoluto, la fijación de un número es bastante difícil como un problema para resolver de una manera que satisfaga su necesidad como programador. Intentar arreglar esto agregando un número puede volverse problemático rápidamente cuando el número no se comporta como espera.

En segundo lugar, se pueden generar números de revisión en diferentes máquinas. Esto hace que la sincronización de números sea mucho más difícil, especialmente porque la conectividad es unidireccional; Es posible que ni siquiera tenga acceso a todas las máquinas que tienen el repositorio.

En tercer lugar, en git, algo pionero por el sistema OpenCM ahora desaparecido, la identidad de un commit (lo que es el commit) es equivalente a su nombre (la identificación SHA). Este concepto de denominación = identidad es muy fuerte. Cuando te sientas con un nombre de confirmación en la mano, también identifica la confirmación de una manera inolvidable. Esto a su vez le permite verificar todas sus confirmaciones hasta la primera inicial para detectar daños con el git fsckcomando.

Ahora, dado que tenemos un DAG (Gráfico Acíclico Dirigido) de revisiones y estas constituyen el árbol actual, necesitamos algunas herramientas para resolver su problema: ¿Cómo discriminamos las diferentes versiones? Primero, puede omitir parte del hash si un prefijo dado, digamos 1516bd , identifica de manera exclusiva su confirmación. Pero esto también es bastante artificial. En cambio, el truco es usar etiquetas y / o ramas. Una etiqueta o rama es similar a una "nota adhesiva amarilla" que adjunta a una confirmación SHA1-id determinada. Las etiquetas, en esencia, están destinadas a no moverse, mientras que una rama se moverá cuando se realicen nuevos compromisos en su HEAD. Hay formas de referirse a un commit alrededor de una etiqueta o rama, vea la página de manual de git-rev-parse.

Por lo general, si necesita trabajar en una parte específica del código, esa parte está experimentando cambios y, como tal, debe ser una rama con un nombre de tema que diga. La creación de muchas ramas (20-30 por programador no es desconocido, con unas 4-5 publicadas para que otros trabajen) es el truco para un git efectivo. Cada trabajo debe comenzar como su propia rama y luego fusionarse cuando se prueba. Las ramas no publicadas pueden reescribirse por completo y esta parte de destruir la historia es una fuerza de git.

Cuando el cambio se acepta en maestro, se congela y se convierte en arqueología. En ese punto, puede etiquetarlo, pero con mayor frecuencia se hace una referencia a la confirmación particular en un rastreador de errores o rastreador de problemas a través de la suma sha1. Las etiquetas tienden a estar reservadas para los baches de versión y los puntos de ramificación para las ramificaciones de mantenimiento (para versiones antiguas).


18

Si está interesado, administré los números de versión automáticamente desde git infos aquí bajo el formato

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

donde build es el número total de commits. Verá el código interesante en el Makefile. Aquí está la parte relevante para acceder a la parte diferente del número de versión:

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 función 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 algo como

$ git_rev
2:0f8e14e:20130220

Es decir

commit_count:last_abbrev_commit:date_YYmmdd

Ese tipo de cosas podría ser útil, pero si uno está interesado en números de versión incrementales, intercambiarían las posiciones de campo para que el hash (no incremental) sea el último.
MarkHu

8

El hash SHA1 de la confirmación es el equivalente a un número de revisión de Subversion.


77
Lamentablemente tiene propiedades bastante diferentes de un número de revisión. Es bastante largo y no aumenta de manera monótona. Supongo que ese es el precio a pagar por la distribución ...
CodesInChaos

1
@CodeInChaos: Sé a lo que se refiere, pero en general es posible referirse a git commits con solo los primeros 6 u 8 caracteres del código hash.
Chris Pitman el

55
@Radek: No se garantiza que sean únicos (aunque si encuentras una colisión puedes ganar una pequeña cantidad de celebridades).
Slartibartfast

8
@Radek De acuerdo con en.wikipedia.org/wiki/Collision_attack , con 4 caracteres del hash tienes un Id de 16 bits, lo que significa que en un repositorio con 256 (= 2 ^ (16/2)) confirma que hay un 50 % de probabilidad de que dos confirmaciones tengan el mismo prefijo de cuatro caracteres (y con 65536 confirmaciones es seguro, ya que el rango de los ID de 4 caracteres está agotado). Cuando agrega un carácter, tiene un Id de 20 bits, lo que significa que el umbral del 50% está en 1024 confirmaciones. Pero dado que este es un parámetro estadístico, nada garantiza que tales colisiones no ocurran antes.
Rudi

2
Dado que el hash se basa en el contenido, todavía es probable que dos commits tengan el mismo prefijo hash, no una certeza. Con 65536 confirmaciones es muy probable que dos tengan el mismo prefijo de cuatro caracteres, pero aún no es seguro. Por otro lado, el hash completo aún no tiene una colisión, pero git está trabajando en eso :) stackoverflow.com/questions/3475648/…
goodeye

6

Esto es lo que hice en mi archivo MAKE basado en otras soluciones. Tenga en cuenta que esto no solo le da a su código un número de revisión, sino que también agrega el hash que le permite recrear la versión.

# 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
Parece que la forma más segura de usar git-describepara evitar errores es con la git describe --always --dirty --long --tagsque funciona en todos los casos que se me ocurren.
MarkHu

5

El problema con el uso del git hash como número de compilación es que no está aumentando monotónicamente. OSGi sugiere usar una marca de tiempo para el número de compilación. Parece que el número de confirmaciones a la rama podría usarse en lugar del número de subversión o cambio de fuerza.


5

Escribí algunas utilidades de PowerShell para recuperar información de versión de Git y simplificar el etiquetado

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

Cada commit tiene un hash único. Aparte de eso, no hay números de revisión en git. Tendrá que etiquetar las confirmaciones usted mismo si desea una mayor facilidad de uso.


3

Solo me gustaría señalar otro enfoque posible, y eso es mediante el uso de git git-notes (1) , existente desde v 1.6.6 ( Note to Self - Git ) (estoy usando la gitversión 1.7.9.5).

Básicamente, solía git svnclonar un repositorio SVN con historial lineal (sin diseño estándar, sin ramas, sin etiquetas), y quería comparar los números de revisión en el gitrepositorio clonado . Este clon de git no tiene etiquetas por defecto, por lo que no puedo usarlo git describe. La estrategia aquí probablemente funcionaría solo para la historia lineal, no estoy seguro de cómo resultaría con fusiones, etc .; Pero aquí está la estrategia básica:

  • Solicite git rev-listuna lista de todos los historiales de confirmación
    • Como rev-listestá por defecto en "orden cronológico inverso", usaríamos su --reverseinterruptor para obtener la lista de confirmaciones ordenadas por las más antiguas primero
  • Use bashshell para
    • aumentar una variable de contador en cada confirmación como un contador de revisión,
    • generar y agregar una nota git "temporal" para cada confirmación
  • Luego, explore el registro usando git logwith --notes, que también volcará una nota de confirmación, que en este caso sería el "número de revisión"
  • Cuando termine, borre las notas temporales ( Nota: no estoy seguro de si estas notas están confirmadas o no; en realidad no se muestrangit status )

Primero, observemos que gittiene una ubicación predeterminada de notas, pero también puede especificar una ref(diferencia) para las notas, que las almacenaría en un directorio diferente en .git; por ejemplo, mientras está en una gitcarpeta de repositorio, puede llamar git notes get-refpara ver qué directorio será:

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

Lo que debe tenerse en cuenta es que si notes addtiene un --ref, también debe usar esa referencia nuevamente; de ​​lo contrario, puede obtener errores como " No se encontró nota para el objeto XXX ... ".

Para este ejemplo, he elegido llamar a las refnotas "linrev" (para revisión lineal); esto también significa que no es probable que el procedimiento interfiera con las notas ya existentes. También estoy usando el --git-dirinterruptor, ya que siendo un gitnovato, tuve algunos problemas para entenderlo, así que me gustaría "recordar para más adelante" :); y también uso --no-pagerpara suprimir el desove lesscuando lo uso git log.

Entonces, suponiendo que esté en un directorio, con una subcarpeta myrepo_gitque es un gitrepositorio; uno podría hacer:

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

Entonces, al menos en mi caso específico de historia completamente lineal sin ramificaciones, los números de revisión parecen coincidir con este enfoque, y además, parece que este enfoque permitirá usar git logcon rangos de revisión, mientras sigue obteniendo los números de revisión correctos: YMMV con un contexto diferente, aunque ...

Espero que esto ayude a alguien,
¡salud!


EDITAR: Ok, aquí es un poco más fácil, con gitalias para los bucles anteriores, llamado setlinrevy unsetlinrev; cuando esté en su carpeta de repositorio de git, haga ( Note el desagradable bashescape, vea también # 16136745 - Agregue un alias de Git que contenga un punto y coma ):

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

... para que pueda simplemente invocar git setlinrevantes de intentar hacer un registro con notas de revisión lineal; y git unsetlinrevpara eliminar esas notas cuando haya terminado; un ejemplo desde dentro del directorio git repo:

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

El tiempo que le llevaría al shell completar estos alias dependería del tamaño del historial del repositorio.


2

Para las personas que tienen un proceso de compilación Ant , puede generar un número de versión para un proyecto en git con este objetivo:

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

El resultado se ve así:

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

El indicador sucio está aquí cuando tiene archivos no confirmados cuando genera el número de versión. Porque generalmente, cuando compila / empaqueta su aplicación, cada modificación de código debe estar en el repositorio.


1

¿Junto con la identificación SHA-1 de la confirmación, la fecha y la hora de la hora del servidor habrían ayudado?

Algo como esto:

commit ocurrió a las 11:30:25 el 19 de agosto de 2013 como 6886bbb7be18e63fc4be68ba41917b48f02e09d7_19aug2013_113025


1

Del manual de Git, las etiquetas son una respuesta brillante a este problema:

Crear una etiqueta anotada en Git es simple. La forma más fácil es especificar -a cuando ejecuta el comando de etiqueta:

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

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

Consulte 2.6 Conceptos básicos de Git: etiquetado


Lástima que tengas que saltar a través de aros para cambiar los valores predeterminados:By default, the git push command doesn’t transfer tags to remote servers.
MarkHu

1

Estamos usando este comando para obtener la versión y la revisión de git:

git describe --always --tags --dirty

Vuelve

  • confirmar hash como revisión cuando no se usa etiquetado (por ejemplo gcc7b71f)
  • nombre de la etiqueta como versión cuando está en una etiqueta (p v2.1.0. ej. , utilizada para lanzamientos)
  • nombre de etiqueta, número de revisión desde la última etiqueta y hash de confirmación cuando después de una etiqueta (p v5.3.0-88-gcc7b71f. ej. )
  • igual que el anterior más una etiqueta "sucia" si el árbol de trabajo tiene modificaciones locales (por ejemplo v5.3.0-88-gcc7b71f-dirty)

Ver también: https://www.git-scm.com/docs/git-describe#Documentation/git-describe.txt


0

Evento posterior a la compilación para Visual Studio

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

-1

Considere usar

git-rev-label

Proporciona información sobre la revisión del repositorio de Git en formato como master-c73-gabc6bec. Puede llenar una cadena de plantilla o un archivo con variables de entorno e información de Git. Útil para proporcionar información sobre la versión del programa: rama, etiqueta, hash de confirmación, recuento de confirmaciones, estado sucio, fecha y hora. Una de las cosas más útiles es el recuento de confirmaciones, sin tener en cuenta las ramas fusionadas, solo el primer padre.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.