GitVer
命令行版本管理工具,从 Git 仓库读取 tag 自动生成并回写版本号。
用法总览
gitver
gitver rewrite [PEType] [-f]
gitver setver=<pid> [repodir=<path>] [-test] [-setup=0|1]
gitver nuitkabuild=<pid> [repodir=<path>] [-test] [params="<mainPy> <nuitka参数>"]
gitver nuitkapydbuild=<pid> [repodir=<path>] [-test] [params="<modulePy> <nuitka参数>"]
gitver pyinstaller=<pid> [repodir=<path>] [-test] [params="<mainPy|specFile> <pyinstaller参数>"]
gitver setup=n [pid=m] [repodir=<path>] [-test]
通用参数说明:
| 参数 | 说明 |
|---|---|
pid |
产品 ID,整数,范围 0-65535,内嵌在命令名中(如 setver=5) |
repodir=<path> |
Git 仓库目录,缺省使用当前运行目录 |
-test |
将产品版本号的 major/minor 置为 0(测试版本构建) |
params="..." |
传递给 Nuitka 或 PyInstaller 的参数(含入口文件名),用双引号括起来 |
BID 规则:
main/master 分支固定 bid=0;其他分支格式须为 <描述>.<数字>,自动读取末尾数字作为 bid。
命令详解
gitver(无参数交互模式)
自动读取当前分支最近三次符合 <分支>.major.minor 格式的 tag,提示用户选择 major+1 或 minor+1,二次确认后创建新 tag。
当前分支无有效 tag 时进入首发引导:提示输入默认 major/minor(回车使用默认 1/0),再创建首个 tag。
交互示例(已有 tag):
当前分支: main,最近三个 tag:
main.1920.9
main.1920.10
main.1920.11
输入 1 → 创建 main.1921.0
输入 2 → 创建 main.1920.12
交互示例(无 tag 首发):
未找到符合规则的历史标签
输入默认 major(回车=1): 2
输入默认 minor(回车=0): 5
→ 创建 <分支>.2.5
gitver rewrite
自动识别当前目录源码类型(C++、C#、Python),执行默认版本回写。
gitver rewrite [PEType] [-f]
| 参数 | 说明 |
|---|---|
PEType |
可选,1=EXE(默认),2=DLL,最多出现一次 |
-f |
强制模式:未找到目标文件或回写失败仅提示,不返回错误码 35 |
回写行为:
- C++:递归查找首个
.rc文件,回写FILEVERSION、PRODUCTVERSION、VALUE "FileVersion"、VALUE "ProductVersion"(限定在VS_VERSION_INFO版本块内) - C#:递归查找首个
AssemblyInfo.cs,回写AssemblyVersion、AssemblyFileVersion - Python:不执行回写,提示改用
nuitkabuild=或nuitkapydbuild=
示例:
gitver rewrite
gitver rewrite 2
gitver rewrite -f
gitver setver=<pid>
从 Git 仓库读取 tag,生成产品版本号与文件版本号,并按源码类型自动回写。
gitver setver=<pid> [repodir=<path>] [-test]
版本号生成规则:
ProductVersion = pid.bid.major.minor(取当前分支前缀的最新 tag)FileVersion = pid.yy.mmdd.id(id = 当天当前分支提交次数)
示例:
gitver setver=5
gitver setver=5 repodir=E:\Code\OTH\gitver
gitver setver=5 -test
输出示例:
ProductVersion=5.0.1920.11
FileVersion=5.26.0519.3
回写说明:
- C++:回写
.rc文件中的 FILEVERSION、PRODUCTVERSION 及对应字符串字段 - C#:回写
AssemblyInfo.cs中的 AssemblyVersion、AssemblyFileVersion - Python:仅输出版本号,不执行文件回写,提示改用 Nuitka 命令
- 编码:支持 ANSI/UTF-8(保留 UTF-8 BOM);UTF-16 文件会报错停止
- 当前分支无匹配 tag 时自动使用默认版本
1.0
gitver nuitkabuild=<pid>
生成版本号并调用 Nuitka 打包 Python 程序(EXE 模式)。
gitver nuitkabuild=<pid> [repodir=<path>] [-test] [params="<mainPy> <nuitka参数>"]
自动调用:
python -m nuitka --windows-product-version=<版本> --windows-file-version=<版本> <params>
示例:
gitver nuitkabuild=5 params="main.py"
gitver nuitkabuild=5 -test params="main.py"
gitver nuitkabuild=5 repodir=E:\Code\MyPyProj params="src\\app.py --standalone --output-dir=dist"
输出示例:
Nuitka 打包开始..
ProductVersion=5.0.1920.11
FileVersion=5.26.0519.3
需要当前环境已安装 Nuitka(可通过
python -m nuitka --version验证)。
gitver nuitkapydbuild=<pid>
生成版本号并调用 Nuitka 打包 Python 模块(pyd/DLL 模式)。
gitver nuitkapydbuild=<pid> [repodir=<path>] [-test] [params="<modulePy> <nuitka参数>"]
自动调用:
python -m nuitka --module --windows-product-version=<版本> --windows-file-version=<版本> <params>
示例:
gitver nuitkapydbuild=5 params="module.py"
gitver nuitkapydbuild=5 -test params="module.py"
gitver nuitkapydbuild=5 repodir=E:\Code\MyPyProj params="src\\core.py --output-dir=dist"
需要当前环境已安装 Nuitka(可通过
python -m nuitka --version验证)。
gitver pyinstaller=<pid>
生成版本号并调用 PyInstaller 打包 Python 程序,支持直接传入 .py 入口脚本或 .spec 构建配置文件。
gitver pyinstaller=<pid> [repodir=<path>] [-test] [params="<mainPy|specFile> <pyinstaller参数>"]
自动调用:
python -m PyInstaller <params>
版本号照常从 Git tag 计算并输出。在 spec 模式下,gitver 会在调用 PyInstaller 前自动将版本号写入版本信息,具体行为取决于 spec 文件中 version= 字段的值:
spec 中 version= 的值 |
行为 |
|---|---|
'version_info.txt'(引号路径,文件存在) |
就地更新外部版本信息文件 |
'1.2.3.4'(引号字符串,非有效文件路径) |
替换 spec 内该引号字符串为新版本号 |
version_info(无引号标识符,spec 内定义的 VSVersionInfo 对象) |
就地更新 spec 文件内的版本字段 |
无 version= / version=None |
在 spec 目录生成 version_info.txt 并自动注入 version='version_info.txt' |
在 脚本模式(.py 入口)下,PyInstaller 不接受命令行版本参数,版本号仅输出到控制台,不嵌入 EXE。
两种打包模式:
| 模式 | 参数示例 | 说明 |
|---|---|---|
| 脚本模式 | params="main.py" |
由 PyInstaller 自动生成 spec 并打包 |
| spec 模式 | params="myapp.spec" |
使用已有 spec 文件,打包配置完全由 spec 控制;gitver 在调用 PyInstaller 前自动将版本号写入版本信息(见下表) |
示例:
gitver pyinstaller=5 params="main.py"
gitver pyinstaller=5 -test params="main.py"
gitver pyinstaller=5 repodir=E:\Code\MyPyProj params="src\\app.py --onefile --name=MyApp"
gitver pyinstaller=5 params="myapp.spec"
gitver pyinstaller=5 -test params="myapp.spec"
gitver pyinstaller=5 repodir=E:\Code\MyPyProj params="myapp.spec"
输出示例:
PyInstaller 打包开始.. (main.py)
ProductVersion=5.0.1920.11
FileVersion=5.26.0519.3
需要当前环境已安装 PyInstaller(可通过
python -m PyInstaller --version验证)。
gitver setup=n(独立打包命令)
独立调用安装脚本打包,不依赖其他命令。
gitver setup=n [pid=m] [repodir=<path>] [-test]
| 参数 | 说明 |
|---|---|
n |
安装脚本类型,0=Inno Setup(setup.iss),1=NSIS(setup.nsi) |
pid=m |
可选,产品 ID(整数 0-65535);不指定时自动从项目的 .rc、AssemblyInfo.cs 或 .spec 文件中读取版本信息 |
示例:
gitver setup=0
gitver setup=1
gitver setup=0 pid=5
gitver setup=1 pid=5 repodir=E:\Code\MyProj
Nuitka 与 PyInstaller 常用参数速查
Nuitka 常用参数
通过 params="..." 传递给 gitver nuitkabuild= / nuitkapydbuild=。
| 参数 | 说明 |
|---|---|
--standalone |
独立模式:将所有依赖打包进输出目录,可单独分发 |
--onefile |
单文件模式:将独立包压缩为单个 EXE(需配合 --standalone) |
--output-dir=<dir> |
指定输出目录,如 --output-dir=dist |
--windows-icon-from-ico=<ico> |
设置 EXE 图标 |
--windows-company-name=<name> |
设置公司名(写入文件属性) |
--windows-product-name=<name> |
设置产品名 |
--enable-plugin=<plugin> |
启用插件,如 pyside6、tk-inter、numpy |
--follow-imports |
跟踪所有隐式导入(打包更完整,体积也更大) |
--nofollow-import-to=<mod> |
排除指定模块不展开,如 --nofollow-import-to=tests |
--include-package=<pkg> |
强制包含指定包 |
--include-data-files=<src>=<dst> |
打包额外数据文件 |
--remove-output |
打包前先清理上次输出 |
--lto=yes |
启用链接时优化(Release 构建推荐) |
--jobs=<n> |
并行编译线程数,如 --jobs=4 |
典型用法示例:
# 最小单文件 EXE
gitver nuitkabuild=5 params="main.py --standalone --onefile --output-dir=dist"
# 带图标、公司名的独立包
gitver nuitkabuild=5 params="main.py --standalone --windows-icon-from-ico=app.ico --windows-company-name=MyCompany --output-dir=dist"
# PySide6 GUI 应用
gitver nuitkabuild=5 params="main.py --standalone --enable-plugin=pyside6 --output-dir=dist"
# 打包 pyd 模块
gitver nuitkapydbuild=5 params="core.py --output-dir=dist"
# 异地仓库
gitver nuitkabuild=5 repodir=E:\Code\MyProj params="main.py --standalone --onefile --output-dir=dist"
PyInstaller 常用参数
通过 params="..." 传递给 gitver pyinstaller=。
| 参数 | 说明 |
|---|---|
--onefile / -F |
单文件模式:打包成单个 EXE |
--onedir / -D |
单目录模式(默认) |
--name=<name> / -n |
指定输出文件名(不含后缀) |
--icon=<ico> / -i |
设置 EXE 图标 |
--distpath=<dir> |
指定输出目录,默认 dist |
--workpath=<dir> |
中间文件目录,默认 build |
--specpath=<dir> |
spec 文件生成位置,默认当前目录 |
--noconsole / -w |
不显示控制台窗口(GUI 应用) |
--hidden-import=<mod> |
手动指定隐式导入的模块 |
--add-data=<src>;<dst> |
打包额外数据文件,Windows 分隔符为 ;,Linux/macOS 为 : |
--version-file=<file> |
从文件读入 Windows 版本信息嵌入 EXE |
--uac-admin |
请求管理员权限运行 |
--clean |
构建前清理缓存 |
--log-level=WARN |
减少构建输出噪音,可选 DEBUG、INFO、WARN、ERROR |
典型用法示例:
# 最小单文件 EXE
gitver pyinstaller=5 params="main.py --onefile --name=MyApp"
# GUI 应用(关指控制台)
gitver pyinstaller=5 params="main.py --onefile --noconsole --icon=app.ico --name=MyApp"
# 包含资源文件
gitver pyinstaller=5 params="main.py --onefile --add-data=assets;assets --name=MyApp"
# 指定输出目录
gitver pyinstaller=5 params="main.py --onefile --distpath=dist --workpath=build --name=MyApp"
# 使用 spec 文件(配置均在 spec 中,不需要其他 params)
gitver pyinstaller=5 params="myapp.spec"
# 使用 spec 并覆盖输出路径
gitver pyinstaller=5 params="myapp.spec --distpath=release"
# 异地仓库
gitver pyinstaller=5 repodir=E:\Code\MyProj params="main.py --onefile --name=MyApp"
spec 文件嵌入版本信息(推荐方式):
PyInstaller 不支持命令行版本参数。需将版本号嵌入 EXE 时,建议先用 gitver setver=<pid> 生成版本号,再在 spec 文件中设置 version_file 字段:
# myapp.spec 片段
exe = EXE(
pyz,
...,
version='version_info.txt', # Windows 版本信息文件
name='MyApp',
)
完整 spec 文件示例(myapp.spec):
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['src\\main.py'], # 入口脚本
pathex=[],
binaries=[],
datas=[
('assets', 'assets'), # 额外资源目录:源路径, 目标路径
],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='MyApp',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False, # True=控制台程序,False=GUI程序
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='assets\\app.ico', # 图标文件路径
version='version_info.txt', # Windows 版本信息文件
)
配套的 version_info.txt 示例:
# UTF-8
# Windows EXE 版本信息文件
# 版本号格式:major, minor, patch, build(均为整数)
VSVersionInfo(
ffi=FixedFileInfo(
filevers=(5, 0, 1920, 11), # FileVersion,对应 FileVersion=5.0.1920.11
prodvers=(5, 0, 1920, 11), # ProductVersion
mask=0x3f,
flags=0x0,
OS=0x40004,
fileType=0x1, # 0x1=EXE, 0x2=DLL
subtype=0x0,
date=(0, 0),
),
kids=[
StringFileInfo([
StringTable(
'040904B0', # 语言 0409=英语, 04B0=Unicode
[
StringStruct('CompanyName', 'MyCompany'),
StringStruct('FileDescription', 'MyApp Application'),
StringStruct('FileVersion', '5.0.1920.11'),
StringStruct('InternalName', 'MyApp'),
StringStruct('LegalCopyright', 'Copyright (C) 2026 MyCompany'),
StringStruct('OriginalFilename', 'MyApp.exe'),
StringStruct('ProductName', 'MyApp'),
StringStruct('ProductVersion', '5.0.1920.11'),
]
)
]),
VarFileInfo([VarStruct('Translation', [0x0409, 0x04B0])])
]
)
在 spec 模式下,gitver 会在调用 PyInstaller 前自动将计算出的版本号写入版本信息,无需手动维护
version_info.txt。
错误码
| 码 | 含义 |
|---|---|
| 2 | 默认回写流程下未获取到 git 提交号 |
| 3 | 参数非法或未知参数 |
| 4 | setver= 的 pid 非法 |
| 5 | setver= 无法根据分支名计算 bid |
| 9 | setver= 获取当天分支提交次数失败 |
| 15 | 回写流程未识别源码类型 |
| 16 | 回写流程识别到 Python,请改用 nuitka 命令 |
| 17 | nuitkabuild= 参数不足(缺少 mainPy) |
| 18 | nuitkabuild= 的 pid 非法 |
| 19 | nuitkabuild= 无法根据分支名计算 bid |
| 21 | nuitkabuild= 获取当天分支提交次数失败 |
| 22 | rewrite 参数非法(PEType 非法或重复) |
| 23 | repodir= 不是有效目录 |
| 24 | nuitkapydbuild= 参数不足(缺少 modulePy) |
| 25 | nuitkapydbuild= 的 pid 非法 |
| 26 | nuitkapydbuild= 无法根据分支名计算 bid |
| 28 | nuitkapydbuild= 获取当天分支提交次数失败 |
| 29 | 无参数模式下无法获取当前分支 |
| 30 | 无参数模式下读取标签列表失败 |
| 31 | 无参数模式下未读取到用户输入 |
| 32 | 无参数模式下用户选择非法,或 major/minor 已达上限 |
| 33 | 无参数模式下创建 tag 失败 |
| 34 | 无参数模式下创建 tag 后校验失败 |
| 35 | 未找到可回写目标文件,或回写失败 |
| 36 | setup= 值不支持(仅支持 0 和 1) |
| 37 | 未找到安装脚本(setup.iss / setup.nsi) |
| 38 | 修改安装脚本失败 |
| 39 | 未找到安装编译器(ISCC.exe / makensis.exe) |
| 40 | pyinstaller= 参数不足(缺少 mainPy 或 specFile) |
| 41 | pyinstaller= 的 pid 非法 |
| 42 | pyinstaller= 无法根据分支名计算 bid |
| 43 | pyinstaller= 读取 tag 失败 |
| 44 | pyinstaller= 获取当天分支提交次数失败 |
| 45 | pyinstaller= 版本信息文件无法生成或更新 |
| 46 | pyinstaller= spec 文件无法注入或修改版本信息 |
最小自测
基础验证:setver=
# 初始化测试仓库
mkdir test_repo && cd test_repo
git init
echo test > README.txt
git add . && git commit -m "init"
git tag main.1920.10
git tag main.1920.11
# 验证版本生成
gitver setver=5
# 预期:
# ProductVersion=5.0.1920.11
# FileVersion=5.yy.mmdd.<id>
# 返回码: 0
验证无 tag 时自动使用默认版本
git checkout -b newbranch
gitver setver=5
# 预期: ProductVersion=5.<bid>.1.0(无 tag 自动回落默认 1.0)
# 返回码: 0
验证分支 tag 隔离
git checkout -b feature.12
git tag feature.12.1930.7
git tag feature.12.1930.8
gitver setver=5
# 预期: ProductVersion=5.12.1930.8(忽略 main.* tag)
# 返回码: 0
验证 -test
gitver setver=5 -test
# 预期: ProductVersion=5.0.0.0(major/minor 置零)
# 返回码: 0
验证 nuitkabuild=
gitver nuitkabuild=5 params="main.py"
# 预期: 调用 python -m nuitka,注入版本号参数
gitver nuitkabuild=5 params="src\\app.py --standalone --output-dir=dist"
# 预期: 额外参数传递给 Nuitka
验证 pyinstaller=
gitver pyinstaller=5 params="main.py"
# 预期: 调用 python -m PyInstaller main.py
# 输出 ProductVersion / FileVersion
gitver pyinstaller=5 params="myapp.spec"
# 预期: 调用 python -m PyInstaller myapp.spec(spec 模式)
gitver pyinstaller=5 params="main.py --onefile --name=MyApp"
# 预期: 额外参数传递给 PyInstaller
验证 setup=
# 确保 exe 目录或上级目录有 setup.iss
gitver setup=0
# 预期: 从 .rc 或 AssemblyInfo.cs 读取版本号,修改 setup.iss 并调用 ISCC.exe 编译
gitver setup=0 pid=5
# 预期: 使用 pid=5 生成版本号,修改 setup.iss 并调用 ISCC.exe 编译
回归清单
rewrite 组
| 命令 | 预期返回码 |
|---|---|
gitver rewrite |
0 / 15 / 16 / 35 |
gitver rewrite -f |
0 / 15 / 16 |
gitver rewrite 2 |
0 / 15 / 35 |
gitver rewrite 1 2 |
22 |
setver= 组
| 命令 | 预期返回码 |
|---|---|
gitver setver=5 |
0 |
gitver setver=5 -test |
0 |
gitver setver=5 repodir=E:\NotExists |
23 |
gitver setver=abc |
4 |
nuitkabuild= 组
| 命令 | 预期返回码 |
|---|---|
gitver nuitkabuild=5 params="main.py" |
0 / 19 / 21 |
gitver nuitkabuild=5 -test params="main.py" |
0 |
gitver nuitkabuild=5 params="main.py --standalone" |
0 |
gitver nuitkabuild=5 repodir=E:\NotExists params="main.py" |
23 |
gitver nuitkabuild=5 |
0 |
nuitkapydbuild= 组
| 命令 | 预期返回码 |
|---|---|
gitver nuitkapydbuild=5 params="module.py" |
0 / 26 / 28 |
gitver nuitkapydbuild=5 -test params="module.py" |
0 |
gitver nuitkapydbuild=5 params="module.py --output-dir=dist" |
0 |
gitver nuitkapydbuild=5 repodir=E:\NotExists params="module.py" |
23 |
gitver nuitkapydbuild=5 |
0 |
pyinstaller= 组
| 命令 | 预期返回码 |
|---|---|
gitver pyinstaller=5 params="main.py" |
0 / 42 / 44 |
gitver pyinstaller=5 -test params="main.py" |
0 |
gitver pyinstaller=5 params="main.py --onefile" |
0 |
gitver pyinstaller=5 params="myapp.spec" |
0 |
gitver pyinstaller=5 -test params="myapp.spec" |
0 |
gitver pyinstaller=5 repodir=E:\NotExists params="main.py" |
23 |
gitver pyinstaller=5 |
0 |
gitver pyinstaller=abc params="main.py" |
41 |
setup= 组
| 命令 | 预期返回码 |
|---|---|
gitver setup=0 |
0 / 37 / 38 / 39 |
gitver setup=1 |
0 / 37 / 38 / 39 |
gitver setup=0 pid=5 |
0 / 37 / 38 / 39 |
gitver setup=0 pid=5 repodir=E:\NotExists |
23 |
gitver setup=9 |
36 |
gitver setup=0 pid=abc |
4 |
注意:如果打包时提示“未找到安装编译器(ISCC.exe / makensis.exe)”,请手动下载安装对应工具,并将其可执行文件路径(如
ISCC.exe或makensis.exe所在目录)添加到系统环境变量PATH。常见下载地址:
- Inno Setup: https://jrsoftware.org/isinfo.php
- NSIS: https://nsis.sourceforge.io/Download
添加方法:
- 复制编译器安装目录路径(如
C:\Program Files (x86)\Inno Setup 6)。- 打开“系统属性”→“高级”→“环境变量”,在“系统变量”中找到
PATH,点击“编辑”,添加上述路径。- 重新打开命令行窗口后再运行打包命令。