GitHub PR 流程与 cherry-pick 多 commit 标准做法
PR 流程 SOP
第一性原理:PR base 必须是 upstream/main
GitHub 计算 PR diff 是从 fork head 仓库的 branch 出发对比到 base 仓库的 branch。如果 base 选成 fork main(Diraw:main)或本地分支,GitHub 会从 fork main → upstream main 的 merge-base 算起——所有 fork 独有的 commit 都会被算进 PR diff。
正确姿势:
base repository: Yuan-lai-ru-ci/ProferAI ← 上游 |
新功能 PR 6 步
# 1. 同步 upstream |
本地 main 同步
git fetch upstream main |
为什么不能 merge origin/main:
- Diraw fork 的 main 通过 GitHub “Sync fork” 跟着 upstream 同步,但有延迟
- merge origin/main 等于把 fork 那份陈旧镜像吃进本地 main
- 下次开 feat 分支基于本地 main 时,那批陈旧 commit 又会被算进 PR diff
长 commit message 的写法
# ❌ 多行 + 中文双引号 → bash 引号嵌套爆炸 |
cherry-pick 多 commit SOP
触发场景
把一个旧分支上的多个 commit 重放到新 base 上:
- 旧分支基于
upstream@old-tip,要基于upstream@new-tip重做 - 旧分支混入了 fork 无关历史,需要剔除后重建
- PR review 后要 rebase 但不想用 rebase(rebase abort 会触发 ref 写坏)
三步走标准做法
# 第 1 步:working tree 同步到新 base |
untracked file 冲突根因
git reset --hard 改的是 tracked files,untracked files 不会动。新 base 上没有 HistoryDrawer.tsx / conversation-manager.test.ts 这些 cherry-pick 要新建的文件,但 working tree 里有它们(之前旧分支留下)→ cherry-pick 报 “would be overwritten”。
处理:
# 冲突时先 abort |
cherry-pick hash ≠ merge hash
PR 合并进 upstream 后:
git branch -d feature/<name> |
根因:cherry-pick 重放了文件内容但创建了新的 commit 对象,本地 hash(如 576d7bfd)跟 PR 在 upstream main 上的 merge commit hash(如 15ef1d30)不一样。git branch -d 看本地 hash 不在 upstream history 就拒绝删。
正确做法:内容已合 upstream,直接 git branch -D。
vs git rebase
| cherry-pick | rebase | |
|---|---|---|
| 风险 | 低(只 apply 选定 commit) | 高(重写整条历史) |
| 中途 abort | 不破坏 ref | rebase abort 在 Git for Windows 上会触发 packed-refs bug,导致 ref 全废 |
| 推荐场景 | 多 commit 跨 base 重放 | 单分支线性 history 整理 |
默认走 cherry-pick,只在确实需要清理单分支历史时才用 rebase。
SOP 速查表
| 场景 | 错误做法 | 正确做法 |
|---|---|---|
| PR base | Diraw:main 或本地分支 |
Yuan-lai-ru-ci:main |
| 新建分支 | 基于本地 main 或 origin/main | git checkout -b feat/<name> upstream/main |
| 同步本地 main | merge --ff-only origin/main |
merge --ff-only upstream/main |
| 长 commit message | -m "多行中文..." |
-F <file> |
| cherry-pick 多 commit | 直接 cherry-pick 报冲突 | 先 reset --hard <new-base> + rm <untracked> + cherry-pick 全部 |
| untracked 冲突处理 | 强行 git add 解决 |
abort + rm + 重 cherry-pick |
| 删已合并分支 | git branch -d 因 hash 不匹配失败 |
git branch -D |
| 重放多 commit | git rebase(风险高) |
git cherry-pick <多个 hash> |
| PR 想 “改 commit message” | git reset |
git commit-tree <原-tree> -p <parent> -m "新 message" 重写 commit,不动 ref |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Diraw的世界!
评论