Ответы:
Команда git describe
- это хороший способ создания презентабельного «номера версии» кода. Из примеров в документации:
С чем-то вроде текущего дерева git.git я получаю:
[torvalds@g5 git]$ git describe parent v1.0.4-14-g2414721
то есть текущий заголовок моей «родительской» ветви основан на v1.0.4, но так как он имеет несколько коммитов, к ним добавлено число дополнительных коммитов («14») и сокращенное имя объекта для фиксации. сам ("2414721") в конце.
Из Python вы можете сделать что-то вроде следующего:
import subprocess
label = subprocess.check_output(["git", "describe"]).strip()
fatal: No names found, cannot describe anything.
git describe --always
будет возвращаться к последнему коммиту, если теги не найдены
git describe
обычно требуется хотя бы один тег. Если у вас нет тегов, используйте --always
опцию. Смотрите документацию git description для получения дополнительной информации.
Не нужно взламывать получение данных от 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
можно предположить, что такое весь стекопоток, но установка gitpython выходит за рамки «чистого» и «портативного». Я думаю, что это, безусловно, лучшее решение, потому что оно не изобретает колесо, скрывает уродливую реализацию и не пытается взломать ответ git из подпроцесса.
pip
возможностью простой установки pip
. В этих современных сценариях pip
решение столь же переносимо, как и решение «стандартной библиотеки».
Этот пост содержит команду, а ответ Грега содержит команду подпроцесса.
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 была необходима для кросс-платформенной функциональности. Ответ Юджи - нет, но, возможно, это работает как в 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()
Я только протестировал это на своих репозиториях, но, похоже, работает довольно стабильно.
Вот более полная версия ответа Грега :
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=
аргумент может быть использован в check_output
временные изменения в рабочем каталоге перед выполнением.
Если по какой-то причине у вас нет git, но у вас есть git-репозиторий (найдена папка .git), вы можете получить хеш коммита из .git / fetch /heads / [branch]
Например, я использовал следующий быстрый и грязный фрагмент Python, запускаемый в корне хранилища, чтобы получить идентификатор фиксации:
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
командной строки. Синтаксис вывода должен быть очевидным.