You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建每次Git推送时自动更新的version.py文件?

问题修复与优化方案

现有脚本的核心问题

你的脚本无法生效主要有以下几个原因:

  • 钩子类型不匹配:pre-push钩子的参数不是提交消息文件,直接使用会导致读取文件失败;prepare-commit-msg钩子的时机是提交消息生成后、提交创建前,此时git rev-parse HEAD获取的是上一次提交的哈希,并非本次提交的哈希。
  • Shebang错误:原脚本的#!/usr/bin/env /usr/bin/python写法错误,env后应跟命令名而非绝对路径,兼容性差。
  • 异常处理缺失:未处理文件读取失败、版本号解析失败、Git命令执行失败等情况,容易崩溃。
  • 冗余操作:重复执行git add命令,无意义。

修复后的prepare-commit-msg钩子脚本

该脚本会在提交消息生成后修改version.py,并将其加入当前提交的暂存区(注意:此时无法获取本次提交的哈希,改用暂存区的树哈希替代):

#!/usr/bin/env python3
import os
import subprocess
import re
import sys

# 检查参数是否存在
if len(sys.argv) < 1:
    print("错误:未提供提交消息文件", file=sys.stderr)
    sys.exit(1)

commit_msg_file = sys.argv[1]

# 读取提交消息
try:
    with open(commit_msg_file, 'r') as file:
        commit_msg = file.read().strip()
except Exception as e:
    print(f"读取提交消息文件失败:{e}", file=sys.stderr)
    sys.exit(1)

version_file = os.path.abspath('version.py')

# 获取暂存区的树哈希(提交未创建,无法获取提交哈希)
try:
    hashed_code = subprocess.check_output(['git', 'write-tree']).strip().decode('utf-8')
except subprocess.CalledProcessError as e:
    print(f"获取Git哈希失败:{e}", file=sys.stderr)
    sys.exit(1)

# 解析或初始化版本号
major, minor, patch = 0, 0, 1
if os.path.exists(version_file):
    print(f'读取已有版本文件:{version_file}')
    try:
        with open(version_file, 'r') as f:
            content = f.read()
            match = re.search(r'version = "(\d+)\.(\d+)\.(\d+)"', content)
            if match:
                major, minor, patch = map(int, match.groups())
                patch += 1
            else:
                print("警告:版本号格式错误,重置为0.0.1", file=sys.stderr)
    except Exception as e:
        print(f"读取版本文件失败:{e}", file=sys.stderr)
        print("重置版本号为0.0.1", file=sys.stderr)
else:
    print(f'创建新的版本文件:{version_file}')

# 写入version.py内容
print(f'写入版本文件,提交消息:"{commit_msg}"')
try:
    with open(version_file, 'w') as f:
        f.write(f'''# This file is created by the prepare-commit-msg script
class Version:
    comment = "{commit_msg}"
    hash = "{hashed_code}"
    version = "{major}.{minor}.{patch}"


if __name__ == "__main__":
    print(Version.version)
''')
except Exception as e:
    print(f"写入版本文件失败:{e}", file=sys.stderr)
    sys.exit(1)

# 将版本文件加入暂存区
print(f'将{version_file}加入暂存区')
try:
    subprocess.check_call(['git', 'add', version_file])
except subprocess.CalledProcessError as e:
    print(f'Git添加文件失败:{e}', file=sys.stderr)
    sys.exit(1)

使用方法

  1. 将脚本保存到项目的.git/hooks/prepare-commit-msg文件中
  2. 赋予执行权限:chmod +x .git/hooks/prepare-commit-msg

更好的实现(获取真实提交哈希)

如果需要version.py中包含本次提交的真实哈希,可以使用post-commit钩子,提交完成后自动更新版本文件并创建新提交(通过提交消息判断避免循环):

#!/usr/bin/env python3
import os
import subprocess
import re
import sys

version_file = os.path.abspath('version.py')

# 获取当前提交的哈希和消息
try:
    hashed_code = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode('utf-8')
    commit_msg = subprocess.check_output(['git', 'log', '-1', '--pretty=%B']).strip().decode('utf-8')
except subprocess.CalledProcessError as e:
    print(f"获取Git信息失败:{e}", file=sys.stderr)
    sys.exit(1)

# 避免循环提交:如果当前提交是自动更新版本的提交,则跳过
if commit_msg.strip() == "Update version.py":
    print("跳过自动生成的版本更新提交", file=sys.stdout)
    sys.exit(0)

# 解析或初始化版本号
major, minor, patch = 0, 0, 1
if os.path.exists(version_file):
    print(f'读取已有版本文件:{version_file}')
    try:
        with open(version_file, 'r') as f:
            content = f.read()
            match = re.search(r'version = "(\d+)\.(\d+)\.(\d+)"', content)
            if match:
                major, minor, patch = map(int, match.groups())
                patch += 1
            else:
                print("警告:版本号格式错误,重置为0.0.1", file=sys.stderr)
    except Exception as e:
        print(f"读取版本文件失败:{e}", file=sys.stderr)
        print("重置版本号为0.0.1", file=sys.stderr)
else:
    print(f'创建新的版本文件:{version_file}')

# 写入version.py内容
print(f'写入版本文件,提交消息:"{commit_msg}"')
try:
    with open(version_file, 'w') as f:
        f.write(f'''# This file is created by the post-commit script
class Version:
    comment = "{commit_msg}"
    hash = "{hashed_code}"
    version = "{major}.{minor}.{patch}"


if __name__ == "__main__":
    print(Version.version)
''')
except Exception as e:
    print(f"写入版本文件失败:{e}", file=sys.stderr)
    sys.exit(1)

# 提交版本文件修改
try:
    subprocess.check_call(['git', 'add', version_file])
    subprocess.check_call(['git', 'commit', '-m', 'Update version.py'])
except subprocess.CalledProcessError as e:
    print(f'提交版本文件失败:{e}', file=sys.stderr)
    sys.exit(1)

使用方法

  1. 将脚本保存到项目的.git/hooks/post-commit文件中
  2. 赋予执行权限:chmod +x .git/hooks/post-commit

内容的提问来源于stack exchange,提问作者jordanthompson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 18:44:49