使用 Git 标签对源代码进行版本控制不难手动完成,但也很容易自动化,这意味着:
- 您可以将其用于 CI/CD 流程
- 减少团队协作时出错的机会
- 节省搜索或查找步骤的时间,以防您忘记了
我将向您展示如何使用一个简单的 Bash 脚本来自动化这个过程。
手动版本控制过程
在我们自动化这个过程之前,让我们首先看一下如何手动使用 Git 标签对源代码进行版本控制。
一般来说,基本的步骤如下:
- 修改您的源代码,并准备发布一个新版本
- 在项目文件中递增版本号,例如,Node 项目的
package.json
- 提交您的更改到 Git
- 为具有新版本号的提交创建 Git 标签,例如
v1.0.4
- 推送您的提交和标签到远程存储库
根据这些步骤,除了第一步,我们可以自动化所有其他步骤。
自动化版本控制步骤
基于上述步骤,让我们拆分脚本之前所需的不同部分。
验证 Git 本地仓库是否干净
在我们开始对本地仓库进行自动更改之前,最好验证它是否处于干净状态。
# 列出未提交的更改,并检查输出是否为空
if [ -n "$(git status --porcelain)" ]; then
# 打印错误消息
printf "\\n错误:仓库中有未提交的更改\\n\\n"
# 以错误代码退出
exit 1
fi
从 Git 标签获取最新版本
为了递增版本号,我们需要知道上一个版本是什么。有两种方法可以获取它:
- 从我们的清单文件,例如
package.json
或Cargo.toml
- 从以前的 Git 标签
我更喜欢后者,有几个原因:
- 不依赖于特定的编程语言和环境
- 将 Git 标签作为我们版本的真相源保持不变
# 按语义版本排序列出 Git 标签
GIT_TAGS=$(git tag --sort=version:refname)
# 获取输出的最后一行,它返回最后一个标签(最新版本)
GIT_TAG_LATEST=$(echo "$GIT_TAGS" | tail -n 1)
# 如果没有找到标签,默认为 v0.0.0
if [ -z "$GIT_TAG_LATEST" ]; then
GIT_TAG_LATEST="v0.0.0"
fi
# 从标签中删除前缀 'v' 以便轻松递增
GIT_TAG_LATEST=$(echo "$GIT_TAG_LATEST" | sed 's/^v//')
递增我们的版本号
我们将支持三种类型的版本递增:
- 修订版本:
v1.0.0 -> v1.0.1
- 次要版本:
v1.0.0 -> v1.1.0
- 主要版本:
v1.0.0 -> v2.0.0
脚本将接受一个确定如何递增版本号的参数。然后使用 awk
递增版本的正确部分,根据需要将后续部分归零。
# 从传递给脚本的第一个参数获取版本类型
VERSION_TYPE="${1-}"
VERSION_NEXT=""
if [ "$VERSION_TYPE" = "patch" ]; then
# 递增修订版本
VERSION_NEXT="$(echo "$GIT_TAG_LATEST" | awk -F. '{$NF++; print $1"."$2"."$NF}')"
elif [ "$VERSION_TYPE" = "minor" ]; then
# 递增次要版本
VERSION_NEXT="$(echo "$GIT_TAG_LATEST" | awk -F. '{$2++; $3=0; print $1"."$2"."$3}')"
elif [ "$VERSION_TYPE" = "major" ]; then
# 递增主要版本
VERSION_NEXT="$(echo "$GIT_TAG_LATEST" | awk -F. '{$1++; $2=0; $3=0; print $1"."$2"."$3}')"
else
# 为未知的版本类型打印错误
printf "\\n错误:传递的 VERSION_TYPE 参数无效,必须是 'patch'、'minor' 或 'major'\\n\\n"
# 以错误代码退出
exit 1
fi
更新清单文件中的版本号
此步骤是可选的,但对于保持事物同步是一个好主意。
最好在您的清单文件中(如 package.json
或 Cargo.toml
)更新版本号。这里有两个示例,您可以修改并适应其他文件。
package.json
# 更新 package.json 中的版本
sed -i "s/\\"version\\": \\".*\\"/\\"version\\": \\"$VERSION_NEXT\\"/" package.json
# 提交更改
git add .
git commit -m "build: bump package.json version - v$VERSION_NEXT"
Cargo.toml
# 在 Cargo.toml 中更新版本
sed -i "s/^version = .*/version = \\"$VERSION_NEXT\\"/" Cargo.toml
# 更新 Cargo.lock,因为在清单中更新版本时,它也会更改
cargo generate-lockfile
# 提交更改
git add .
git commit -m "build: bump Cargo.toml version - v$VERSION_NEXT"
创建 Git 标签
现在,其他一切都准备好了,我们
可以为新版本创建 Git 标签。
# 创建带注释的标签
git tag -a "v$VERSION_NEXT" -m "发布:v$VERSION_NEXT"
# 可选:将提交和标签推送到远程的 'main' 分支
git push origin main --follow-tags
完整的版本控制脚本
现在,我们了解了所有单独的步骤,我们可以将它们汇总到一起。
#!/usr/bin/env bash
# 如果命令失败或使用了未初始化的变量,退出脚本
set -euo pipefail
# ==================================
# 验证仓库是否干净
# ==================================
# 列出未提交的更改,并检查输出是否为空
if [ -n "$(git status --porcelain)" ]; then
# 打印错误消息
printf "\\n错误:仓库中有未提交的更改\\n\\n"
# 以错误代码退出
exit 1
fi
# ==================================
# 从 Git 标签获取最新版本
# ==================================
# 按语义版本排序列出 Git 标签
GIT_TAGS=$(git tag --sort=version:refname)
# 获取输出的最后一行,它返回最后一个标签(最新版本)
GIT_TAG_LATEST=$(echo "$GIT_TAGS" | tail -n 1)
# 如果没有找到标签,默认为 v0.0.0
if [ -z "$GIT_TAG_LATEST" ]; then
GIT_TAG_LATEST="v0.0.0"
fi
# 从标签中删除前缀 'v' 以便轻松递增
GIT_TAG_LATEST=$(echo "$GIT_TAG_LATEST" | sed 's/^v//')
# ==================================
# 递增版本号
# ==================================
# 从传递给脚本的第一个参数获取版本类型
VERSION_TYPE="${1-}"
VERSION_NEXT=""
if [ "$VERSION_TYPE" = "patch" ]; then
# 递增修订版本
VERSION_NEXT="$(echo "$GIT_TAG_LATEST" | awk -F. '{$NF++; print $1"."$2"."$NF}')"
elif [ "$VERSION_TYPE" = "minor" ]; then
# 递增次要版本
VERSION_NEXT="$(echo "$GIT_TAG_LATEST" | awk -F. '{$2++; $3=0; print $1"."$2"."$3}')"
elif [ "$VERSION_TYPE" = "major" ]; then
# 递增主要版本
VERSION_NEXT="$(echo "$GIT_TAG_LATEST" | awk -F. '{$1++; $2=0; $3=0; print $1"."$2"."$3}')"
else
# 为未知的版本类型打印错误
printf "\\n错误:传递的 VERSION_TYPE 参数无效,必须是 'patch'、'minor' 或 'major'\\n\\n"
# 以错误代码退出
exit 1
fi
# ==================================
# 更新清单文件中的版本号(可选)
# 假设是 Rust 项目,有 Cargo.toml 文件,根据您的项目需要进行修改
# ==================================
# 在 Cargo.toml 中更新版本
sed -i "s/^version = .*/version = \\"$VERSION_NEXT\\"/" Cargo.toml
# 更新 Cargo.lock,因为在清单中更新版本时,它也会更改
cargo generate-lockfile
# 提交更改
git add .
git commit -m "build: bump Cargo.toml version - v$VERSION_NEXT"
# ==================================
# 为新版本创建 Git 标签
# ==================================
# 创建带注释的标签
git tag -a "v$VERSION_NEXT" -m "发布:v$VERSION_NEXT"
# 可选:将提交和标签推送到远程的 'main' 分支
git push origin main --follow-tags
现在,只需执行脚本:
# 递增版本
bash ./version.sh patch
bash ./version.sh minor
bash ./version.sh major
# 使脚本具有可执行权限,以便无需使用 bash 执行
chmod +x ./version.sh
./version.sh patch
至此,使用 Git 标签管理版本控制就是这么简单!
请注意,这是翻译后的文档,其中包含了英文原文中的链接和代码示例。如果您需要进一步的修改或有特定的格式要求,请随时告诉我,我将根据您的需求进行调整。