Answers:
该git describe
命令是创建代码的人为表示的“版本号”的好方法。从文档中的示例中:
使用git.git之类的当前树,我得到:
[torvalds@g5 git]$ git describe parent v1.0.4-14-g2414721
即我的“父”分支的当前头基于v1.0.4,但是由于它的顶部还有一些提交,describe添加了额外的提交数量(“ 14”)和该提交的缩写对象名称本身(“ 2414721”)结尾。
在Python中,您可以执行以下操作:
import subprocess
label = subprocess.check_output(["git", "describe"]).strip()
fatal: No names found, cannot describe anything.
git describe --always
如果找不到标签,将回退到最后一次提交
无需费力地git
自己从命令中获取数据。GitPython是执行此操作以及许多其他工作的非常好方法git
。它甚至对Windows具有“尽力而为”的支持。
之后pip install gitpython
,你可以做
import git
repo = git.Repo(search_parent_directories=True)
sha = repo.head.object.hexsha
ImportError: No module named gitpython
。您不能依赖已gitpython
安装的最终用户,而要求他们在代码工作之前安装它就使其无法移植。除非您要包括自动安装协议,否则它不再是干净的解决方案。
pip
/ requirements.txt
)进行安装。什么不是“干净”的?
import numpy as np
可以在整个stackoverflow中使用它,但是安装gitpython超出了“ clean”和“ portable”的范围。我认为这是迄今为止最好的解决方案,因为它不会重新发明轮子,不会隐藏丑陋的实现,也不会从子进程中破解git的答案。
pip
或易于安装的Docker容器,虚拟环境和机器映像(例如AMI)pip
。在这些现代方案中,pip
解决方案与“标准库”解决方案一样可移植。
这篇文章包含命令,Greg的答案包含subprocess命令。
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()
以解码二进制字符串(并删除换行符)。
numpy
有一个好看的多平台程序在其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对于跨平台功能是必需的。Yuji的答案没有,但是也许在UNIX和Windows上都可以。
.decode('ascii')
工作-否则编码是未知的。
如果子进程不是可移植的,并且您不想安装软件包来执行此简单操作,则也可以执行此操作。
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()
我只在我的存储库上测试过此功能,但它似乎工作得相当稳定。
这是Greg答案的更完整版本:
import subprocess
print(subprocess.check_output(["git", "describe", "--always"]).strip().decode())
或者,如果脚本是从仓库外调用的:
import subprocess, os
os.chdir(os.path.dirname(__file__))
print(subprocess.check_output(["git", "describe", "--always"]).strip().decode())
os.chdir
时,cwd=
ARG可以用于check_output
临时改变工作目录执行前。
如果由于某种原因没有可用的git,但是您有git repo(找到了.git文件夹),则可以从.git / fetch / heads / [branch]获取提交哈希
例如,我使用了在存储库根目录下运行的以下快速且肮脏的Python代码段来获取提交ID:
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
从命令行开始。输出语法应该很明显。