Antworten:
Der git describe
Befehl ist eine gute Möglichkeit, eine vom Menschen präsentierbare "Versionsnummer" des Codes zu erstellen. Aus den Beispielen in 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.
In Python können Sie Folgendes tun:
import subprocess
label = subprocess.check_output(["git", "describe"]).strip()
fatal: No names found, cannot describe anything.
git describe --always
wird auf das letzte Commit zurückgreifen, wenn keine Tags gefunden werden
git describe
Normalerweise ist mindestens ein Tag erforderlich. Wenn Sie keine Tags haben, verwenden Sie die --always
Option. Weitere Informationen finden Sie in der Dokumentation zur Git-Beschreibung .
Sie müssen nicht herumhacken, um selbst Daten vom git
Befehl abzurufen. GitPython ist eine sehr schöne Möglichkeit, dies und viele andere Dinge zu tun git
. Es bietet sogar "Best Effort" -Unterstützung für Windows.
Nachdem pip install gitpython
Sie tun können
import git
repo = git.Repo(search_parent_directories=True)
sha = repo.head.object.hexsha
ImportError: No module named gitpython
. Sie können sich nicht darauf verlassen, dass der Endbenutzer ihn gitpython
installiert hat. Wenn er ihn installieren muss, bevor Ihr Code funktioniert, ist er nicht portierbar. Sofern Sie keine automatischen Installationsprotokolle einschließen, ist dies keine saubere Lösung mehr.
pip
/ requirements.txt
) auf allen Plattformen installiert werden . Was ist nicht "sauber"?
import numpy as np
während des gesamten Stackoverflow davon ausgegangen werden kann, aber die Installation von Gitpython geht über "sauber" und "portabel" hinaus. Ich denke, dies ist bei weitem die beste Lösung, da es das Rad nicht neu erfindet, die hässliche Implementierung verbirgt und nicht darum herumgeht, die Antwort von git aus dem Teilprozess zu hacken.
pip
oder die Möglichkeit zur einfachen Installation pip
. In diesen modernen Szenarien ist eine pip
Lösung genauso portabel wie eine "Standardbibliothek".
Dieser Beitrag enthält den Befehl, Gregs Antwort enthält den Unterprozessbefehl.
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()
, um die Binärzeichenfolge zu dekodieren (und entfernen Sie den Zeilenumbruch).
numpy
hat eine gut aussehende Multi-Plattform-Routine in seiner 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
Diktats für die plattformübergreifende Funktionalität erforderlich ist. Yujis Antwort nicht, aber vielleicht funktioniert das sowohl unter UNIX als auch unter Windows.
.decode('ascii')
funktioniert - ansonsten ist die Codierung unbekannt.
Wenn der Unterprozess nicht portierbar ist und Sie kein Paket installieren möchten, um etwas so Einfaches zu tun, können Sie dies auch tun.
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()
Ich habe dies nur auf meinen Repos getestet, aber es scheint ziemlich konstant zu funktionieren.
Hier ist eine vollständigere Version von Gregs Antwort :
import subprocess
print(subprocess.check_output(["git", "describe", "--always"]).strip().decode())
Oder wenn das Skript von außerhalb des Repos aufgerufen wird:
import subprocess, os
os.chdir(os.path.dirname(__file__))
print(subprocess.check_output(["git", "describe", "--always"]).strip().decode())
os.chdir
, kann das cwd=
Argument verwendet werden, check_output
um das Arbeitsverzeichnis vor der Ausführung vorübergehend zu ändern.
Wenn Sie aus irgendeinem Grund kein Git zur Verfügung haben, aber das Git-Repo haben (der Ordner .git wurde gefunden), können Sie den Commit-Hash aus .git / fetch / Heads / [branch] abrufen.
Zum Beispiel habe ich ein folgendes schnelles und schmutziges Python-Snippet verwendet, das im Repository-Stammverzeichnis ausgeführt wird, um die Commit-ID abzurufen:
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
über die Befehlszeile. Die Ausgabesyntax sollte offensichtlich sein.