Réponses:
La git describe
commande est un bon moyen de créer un "numéro de version" présentable par l'homme du code. D'après les exemples de la documentation:
Avec quelque chose comme l'arbre actuel de git.git, j'obtiens:
[torvalds@g5 git]$ git describe parent v1.0.4-14-g2414721
c'est-à-dire que la tête actuelle de ma branche "parent" est basée sur la v1.0.4, mais comme elle a quelques commits en plus de cela, describe a ajouté le nombre de commits supplémentaires ("14") et un nom d'objet abrégé pour le commit lui-même ("2414721") à la fin.
Depuis Python, vous pouvez faire quelque chose comme ce qui suit:
import subprocess
label = subprocess.check_output(["git", "describe"]).strip()
fatal: No names found, cannot describe anything.
git describe --always
reviendra au dernier commit si aucune balise n'est trouvée
git describe
nécessite normalement au moins une balise. Si vous n'avez pas de balises, utilisez l' --always
option. Consultez la documentation de git describe pour plus d'informations.
Pas besoin de pirater pour obtenir des données de la git
commande vous-même. GitPython est un très bon moyen de faire cela et bien d'autresgit
choses. Il a même un support "best effort" pour Windows.
Après avoir pip install gitpython
pu faire
import git
repo = git.Repo(search_parent_directories=True)
sha = repo.head.object.hexsha
ImportError: No module named gitpython
. Vous ne pouvez pas compter sur l'utilisateur final qui a gitpython
installé, et exiger d'eux qu'il l'installe avant que votre code fonctionne le rend non portable. À moins que vous n'incluiez des protocoles d'installation automatique, ce n'est plus une solution propre.
pip
/ requirements.txt
) sur toutes les plates-formes. Qu'est-ce qui n'est pas «propre»?
import numpy as np
on peut supposer tout au long de stackoverflow, mais l'installation de gitpython va au-delà de «propre» et «portable». Je pense que c'est de loin la meilleure solution, car elle ne réinvente pas la roue, cache la vilaine implémentation et ne pirate pas la réponse de git du sous-processus.
pip
ou possibilité d'installation facile pip
. Dans ces scénarios modernes, une pip
solution est tout aussi portable qu'une solution de «bibliothèque standard».
Ce message contient la commande, la réponse de Greg contient la commande de sous-processus.
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()
pour décoder la chaîne binaire (et supprimez le saut de ligne).
numpy
a une belle routine multi-plateforme dans son 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 était nécessaire pour la fonctionnalité multiplateforme. La réponse de Yuji ne le fait pas, mais peut-être que cela fonctionne à la fois sous UNIX et Windows.
.decode('ascii')
fonctionne - sinon le codage est inconnu.
Si le sous-processus n'est pas portable et que vous ne voulez pas installer un package pour faire quelque chose d'aussi simple, vous pouvez également le faire.
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()
Je n'ai testé cela que sur mes dépôts, mais cela semble fonctionner de manière assez cohérente.
Voici une version plus complète de la réponse de Greg :
import subprocess
print(subprocess.check_output(["git", "describe", "--always"]).strip().decode())
Ou, si le script est appelé depuis l'extérieur du dépôt:
import subprocess, os
os.chdir(os.path.dirname(__file__))
print(subprocess.check_output(["git", "describe", "--always"]).strip().decode())
os.chdir
, l' cwd=
argument peut être utilisé check_output
pour modifier temporairement le répertoire de travail avant de s'exécuter.
Si vous n'avez pas git disponible pour une raison quelconque, mais que vous avez le repo git (le dossier .git est trouvé), vous pouvez récupérer le hachage de validation à partir de .git / fetch / heads / [branch]
Par exemple, j'ai utilisé un extrait de code Python rapide et sale suivant à la racine du référentiel pour obtenir l'ID de validation:
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
partir de la ligne de commande. La syntaxe de sortie doit être évidente.