在Python脚本中获取当前的git哈希值

276
我想在Python脚本的输出中包含当前git哈希(作为生成该输出的代码的版本号)。如何在Python脚本中访问当前的git哈希?需要使用html标签格式保留。

8
从命令行开始,输入 git rev-parse HEAD。输出的语法应该很明显。 - Mel Nicholson
6
在导入了subprocess后,执行以下命令:subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).decode('ascii').strip() - Charlie Parker
12个回答

2
如果由于某些原因您没有可用的Git,但您有git仓库(找到.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]

这对我有用,尽管我不得不将“\”更改为“/”。一定是Windows的问题? - chrislondon
@Reishin 我想你的意思是“环境特定编码”。我这么认为是因为这样会更少被标记为不适当的语言风格。(顺便说一下,我没有因为太慢而被标记为不适当...) - Yunnosch

-1

如果您和我一样:

  • 使用多平台,因此子进程可能会崩溃
  • 使用Python 2.7,因此无法使用GitPython
  • 不想仅为此目的使用Numpy
  • 已经在使用Sentry(旧版弃用版本:raven)

那么(由于shell无法检测到当前文件路径,请将BASE_DIR替换为您的当前文件路径):

import os
import raven

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
print(raven.fetch_git_sha(BASE_DIR))

就这样。

我正在寻找另一个解决方案,因为我想迁移到 sentry_sdk 并离开 raven,但也许你们中的一些人想继续使用 raven 一段时间。

这里是讨论,将我带入了这个 StackOverflow 问题

因此,在没有 raven 的情况下使用 raven 的代码也是可能的(请参见讨论):

from __future__ import absolute_import

import os.path

__all__ = 'fetch_git_sha'


def fetch_git_sha(path, head=None):
    """
    >>> fetch_git_sha(os.path.dirname(__file__))
    """
    if not head:
        head_path = os.path.join(path, '.git', 'HEAD')

        with open(head_path, 'r') as fp:
            head = fp.read().strip()

        if head.startswith('ref: '):
            head = head[5:]
            revision_file = os.path.join(
                path, '.git', *head.split('/')
            )
        else:
            return head
    else:
        revision_file = os.path.join(path, '.git', 'refs', 'heads', head)

    if not os.path.exists(revision_file):
        # Check for Raven .git/packed-refs' file since a `git gc` may have run
        # https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery
        packed_file = os.path.join(path, '.git', 'packed-refs')
        if os.path.exists(packed_file):
            with open(packed_file) as fh:
                for line in fh:
                    line = line.rstrip()
                    if line and line[:1] not in ('#', '^'):
                        try:
                            revision, ref = line.split(' ', 1)
                        except ValueError:
                            continue
                        if ref == head:
                            return revision

    with open(revision_file) as fh:
        return fh.read().strip()

我将这个文件命名为versioning.py,并在需要它的地方导入“fetch_git_sha”,并将文件路径作为参数传递。
希望能对你们中的一些人有所帮助;)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接