diff --git a/docs/提交与发版流程.md b/docs/提交与发版流程.md new file mode 100644 index 0000000..52e0bb5 --- /dev/null +++ b/docs/提交与发版流程.md @@ -0,0 +1,144 @@ +# 提交与发版流程 + +本文档说明 EvoScientist 项目的代码提交、版本号管理与发版流程。 + +## 基本信息 + +| 项 | 值 | +|---|---| +| 远端仓库 | `https://git.foksai.com/ouyangbo/EvoScientist.git` | +| 主开发分支 | `Ai4Sci` | +| 版本号来源 | `EvoScientist/_version.py` (`__version__` 变量) | +| `pyproject.toml` | 通过 `version = { attr = "EvoScientist._version.__version__" }` 动态读取 | +| Tag 命名规则 | `v` + 版本号,如 `v0.1.20` ↔ `_version.py` 中的 `0.1.20` | + +--- + +## 一、平时改代码(不发新版) + +只是提交代码、版本号不变、**不打 tag**: + +```bash +git status # 查看改了什么 +git diff +git add <文件> # 或 git add -A 全部暂存 +git commit -m "fix: 修复 xxx 问题" # 说明「为什么改」 +git push origin Ai4Sci +``` + +--- + +## 二、发新版本(手动 6 步) + +以 `0.1.19 → 0.1.20` 为例。**顺序不能乱**: + +```bash +# 1. 改版本号 (只改 _version.py 一处) +sed -i '' 's/__version__ = "0.1.19"/__version__ = "0.1.20"/' EvoScientist/_version.py + +# 2. 验证改对 +grep version EvoScientist/_version.py # 应输出 __version__ = "0.1.20" + +# 3. 提交版本号改动 +git add EvoScientist/_version.py +git commit -m "Bump version to 0.1.20" + +# 4. 打 tag (tag 名必须 = v + 版本号) +git tag -a v0.1.20 -m "Release v0.1.20" + +# 5. 推代码 +git push origin Ai4Sci + +# 6. 推 tag +git push origin v0.1.20 +``` + +### 版本号怎么选(SemVer) + +| 改动类型 | 升级哪段 | 例子 | +|---|---|---| +| bug 修复、小调整 | patch(末位) | `0.1.19 → 0.1.20` | +| 新增功能、向后兼容 | minor(中位) | `0.1.19 → 0.2.0` | +| 破坏性改动 | major(首位) | `0.1.19 → 1.0.0` | + +--- + +## 三、发新版本(自动,推荐) + +用 `scripts/release.sh` 一条命令完成 bump + 提交 + tag + 推送: + +```bash +./scripts/release.sh patch # 0.1.19 → 0.1.20 +./scripts/release.sh minor # 0.1.19 → 0.2.0 +./scripts/release.sh major # 0.1.19 → 1.0.0 +``` + +**前置条件**:工作区必须干净(所有代码改动已提交)。脚本会自动检查,如果有未提交改动会拒绝运行。 + +### 典型发版流程 + +```bash +# 1. 先提交代码改动 +git add -A +git commit -m "feat: 新增 xxx 功能" +git push origin Ai4Sci + +# 2. 再发版 +./scripts/release.sh patch +``` + +### 脚本内部做了什么 + +``` +读取 _version.py 当前版本 → 计算新版本 → sed 改写 → 验证 → +git add _version.py → git commit → git tag → push 代码 → push tag +``` + +--- + +## 四、Tag 与 Release 的区别 + +| | Tag | Release | +|---|---|---| +| 本质 | git 自带的提交标记 | Gitea 的「发布」页面 | +| 位置 | 仓库 → Commits → Tags 子标签 | 仓库首页 / Releases 标签 | +| 显示 | 仅 tag 名 + 一句说明 | tag + 标题 + 详细说明 + 附件 | +| 创建 | `git push origin v0.1.20` | 网页手动「New Release」或 API | + +`release.sh` 推的是 **Tag**。如想在仓库首页显眼位置看到版本号,需另建 Release: + +```bash +# 需在网页生成 Access Token (勾选 write:repository) +curl -X POST "https://git.foksai.com/api/v1/repos/ouyangbo/EvoScientist/releases" \ + -H "Authorization: token 你的TOKEN" \ + -H "Content-Type: application/json" \ + -d '{ + "tag_name": "v0.1.20", + "name": "v0.1.20", + "body": "新增 xxx 功能", + "target_commitish": "Ai4Sci" + }' +``` + +--- + +## 五、常见问题 + +| 现象 | 原因 | 解决 | +|---|---|---| +| `git push` 被拒 `rejected` | 远端有本地没有的提交 | `git pull origin Ai4Sci --rebase` 再 push | +| tag 推不上去 | tag 已存在于远端 | 换版本号,或删本地 `git tag -d v0.1.20` | +| 改了版本号但 tag 名对不上 | 步骤 1 和 4 版本号不一致 | tag 名必须 `v` + 版本号 | +| 推送要密码 | HTTPS 认证 | 用 Access Token 当密码,或改 SSH | +| `release.sh` 报「工作区有未提交改动」 | 发版前没提交代码 | 先 `git commit` 代码改动,再跑脚本 | + +--- + +## 六、速查清单 + +``` +平时: git add → git commit → git push +发版: 先提交代码 → ./scripts/release.sh patch|minor|major +手动发版: 改 _version.py → add → commit → tag → push 代码 → push tag +纪律: tag 名 = v + _version.py 版本号,打 tag 前一定先提交版本号改动 +``` diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 0000000..52dbf42 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# scripts/release.sh — 发版脚本: bump 版本号 → 提交 → 打 tag → 推送 +# 用法: ./scripts/release.sh patch|minor|major +set -euo pipefail + +VERSION_FILE="EvoScientist/_version.py" + +# ── 参数检查 ── +BUMP="${1:-}" +if [[ -z "$BUMP" ]]; then + cat </dev/null 2>&1 || { echo "✗ 不在 git 仓库内"; exit 1; } + +BRANCH=$(git rev-parse --abbrev-ref HEAD) +[[ "$BRANCH" != "HEAD" ]] || { echo "✗ 处于 detached HEAD, 请先切到分支"; exit 1; } + +# 工作区必须干净 —— 发版提交只应包含版本号改动, 不混入其他代码 +if ! git diff --quiet || ! git diff --cached --quiet; then + echo "✗ 工作区有未提交改动, 请先提交:" + git status --short + echo + echo "提示: 先 git add + git commit 你的代码改动, 再运行本脚本。" + exit 1 +fi + +# ── 计算新版本号 ── +current=$(grep -oE '[0-9]+\.[0-9]+\.[0-9]+' "$VERSION_FILE" | head -1) +[[ -n "$current" ]] || { echo "✗ $VERSION_FILE 里找不到版本号"; exit 1; } + +IFS='.' read -r major minor patch <<< "$current" +case "$BUMP" in + major) major=$((major+1)); minor=0; patch=0 ;; + minor) minor=$((minor+1)); patch=0 ;; + patch) patch=$((patch+1)) ;; + *) echo "✗ 无效参数: $BUMP (用 patch|minor|major)"; exit 1 ;; +esac +new="$major.$minor.$patch" + +[[ "$current" != "$new" ]] || { echo "✗ 版本号没变 ($current)"; exit 1; } + +echo "▶ $current → $new (分支: $BRANCH)" + +# ── 改版本号 (兼容 macOS/Linux) ── +if [[ "$(uname)" == "Darwin" ]]; then + sed -i '' "s/__version__ = \"$current\"/__version__ = \"$new\"/" "$VERSION_FILE" +else + sed -i "s/__version__ = \"$current\"/__version__ = \"$new\"/" "$VERSION_FILE" +fi +grep -q "__version__ = \"$new\"" "$VERSION_FILE" || { echo "✗ 版本号替换失败, 检查 $VERSION_FILE 格式"; exit 1; } + +# ── 提交 + 打 tag + 推送 ── +git add "$VERSION_FILE" +git commit -m "Bump version to $new" >/dev/null +git tag -a "v$new" -m "Release v$new" +git push origin "$BRANCH" +git push origin "v$new" + +echo +echo "✓ 发布完成" +echo " 版本: $new" +echo " Tag: v$new" +echo " 分支: $BRANCH" +echo " 提交: $(git rev-parse --short HEAD)"