Respuestas:
El git describe
comando es una buena forma de crear un "número de versión" del código presentable por humanos. De los ejemplos en la documentación:
Con algo como el árbol actual de git.git, 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.
Desde Python, puede hacer algo como lo siguiente:
import subprocess
label = subprocess.check_output(["git", "describe"]).strip()
fatal: No names found, cannot describe anything.
git describe --always
recurrirá a la última confirmación si no se encuentran etiquetas
git describe
normalmente requiere al menos una etiqueta. Si no tiene ninguna etiqueta, use la --always
opción. Consulte la documentación de git describe para obtener más información.
No es necesario hackear para obtener datos del git
comando usted mismo. GitPython es una muy buena manera de hacer esto y muchas otras git
cosas. Incluso tiene soporte de "mejor esfuerzo" para Windows.
Después de pip install gitpython
que puedas hacer
import git
repo = git.Repo(search_parent_directories=True)
sha = repo.head.object.hexsha
ImportError: No module named gitpython
. No puede confiar en que el usuario final haya gitpython
instalado, y exigirles que lo instalen antes de que su código funcione no lo hace portátil. A menos que vaya a incluir protocolos de instalación automática, en ese momento ya no es una solución limpia.
pip
/ requirements.txt
) en todas las plataformas. ¿Qué no es "limpio"?
import numpy as np
se puede suponer en todo el stackoverflow, pero la instalación de gitpython está más allá de 'clean' y 'portable'. Creo que esta es, con mucho, la mejor solución, porque no reinventa la rueda, oculta la implementación fea y no anda pirateando la respuesta de git del subproceso.
pip
la capacidad de instalarse fácilmente pip
. En estos escenarios modernos, una pip
solución es tan portátil como una solución de "biblioteca estándar".
Esta publicación contiene el comando, la respuesta de Greg contiene el comando de subproceso.
import subprocess
def get_git_revision_hash():
return subprocess.check_output(['git', 'rev-parse', 'HEAD'])
def get_git_revision_short_hash():
return subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'])
.decode('ascii').strip()
para decodificar la cadena binaria (y elimine el salto de línea).
numpy
tiene una bonita rutina multiplataforma en su setup.py
:
import os
import subprocess
# Return the git revision as a string
def git_version():
def _minimal_ext_cmd(cmd):
# construct minimal environment
env = {}
for k in ['SYSTEMROOT', 'PATH']:
v = os.environ.get(k)
if v is not None:
env[k] = v
# LANGUAGE is used on win32
env['LANGUAGE'] = 'C'
env['LANG'] = 'C'
env['LC_ALL'] = 'C'
out = subprocess.Popen(cmd, stdout = subprocess.PIPE, env=env).communicate()[0]
return out
try:
out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD'])
GIT_REVISION = out.strip().decode('ascii')
except OSError:
GIT_REVISION = "Unknown"
return GIT_REVISION
env
dict era necesario para la funcionalidad multiplataforma. La respuesta de Yuji no, pero quizás eso funcione tanto en UNIX como en Windows.
.decode('ascii')
funcione; de lo contrario, la codificación es desconocida.
Si el subproceso no es portátil y no desea instalar un paquete para hacer algo así de simple, también puede hacerlo.
import pathlib
def get_git_revision(base_path):
git_dir = pathlib.Path(base_path) / '.git'
with (git_dir / 'HEAD').open('r') as head:
ref = head.readline().split(' ')[-1].strip()
with (git_dir / ref).open('r') as git_hash:
return git_hash.readline().strip()
Solo he probado esto en mis repositorios, pero parece funcionar de manera bastante consistente.
Aquí hay una versión más completa de la respuesta de Greg :
import subprocess
print(subprocess.check_output(["git", "describe", "--always"]).strip().decode())
O, si el script se llama desde fuera del repositorio:
import subprocess, os
os.chdir(os.path.dirname(__file__))
print(subprocess.check_output(["git", "describe", "--always"]).strip().decode())
os.chdir
, el cwd=
argumento puede usarse check_output
para realizar cambios temporales en el directorio de trabajo antes de ejecutarlo.
Si no tiene git disponible por alguna razón, pero tiene el repositorio git (se encuentra la carpeta .git), puede obtener el hash de confirmación de .git / fetch / heads / [branch]
Por ejemplo, he usado un siguiente fragmento de Python rápido y sucio en la raíz del repositorio para obtener la identificación de confirmación:
git_head = '.git\\HEAD'
# Open .git\HEAD file:
with open(git_head, 'r') as git_head_file:
# Contains e.g. ref: ref/heads/master if on "master"
git_head_data = str(git_head_file.read())
# Open the correct file in .git\ref\heads\[branch]
git_head_ref = '.git\\%s' % git_head_data.split(' ')[1].replace('/', '\\').strip()
# Get the commit hash ([:7] used to get "--short")
with open(git_head_ref, 'r') as git_head_ref_file:
commit_id = git_head_ref_file.read().strip()[:7]
git rev-parse HEAD
desde la línea de comando. La sintaxis de salida debería ser obvia.