Git 协作流程¶
相关文档:Git 命令集 · 提交规范 · Gitignore 与 Hooks
阅读指引¶
- 概念:远程、分支、PR 在协作里各扮演什么角色
- 总览:常见协作模型、远程命名、命令与流程对照
- 场景:从 clone 到 merge 的完整路径与踩坑
- 文末速查:现象 → 建议
协作在 Git 里是什么¶
协作 = 多人向 同一套 Git 历史 贡献代码,通常通过 远程仓库(GitHub / GitLab / Gitee 等)交换 commit,用 分支 隔离进行中的工作,用 Pull Request(Merge Request) 做 review 后再合入主线。
一句话:「各人在自己的分支上 commit,通过远程和 PR 把改动 安全地 并进大家共用的 main。」
效果:main(或 master)一般代表可发布/可集成的代码;feature 分支可随意 push、force push(在仅自己使用时),合并前由 CI 和 reviewer 把关。
总览¶
常见协作模型¶
| 模型 | 谁用 | 远程关系 | 典型流程 | 场景 |
|---|---|---|---|---|
| 共享仓库 | 公司团队、私有库成员 | 一个 origin,大家都有 push 权 | 分支 → push → PR → merge | 成员协作 |
| Fork 工作流 | 开源、无直接 push 权 | origin=你的 fork,upstream=官方库 | fork → 分支 → PR 到 upstream | Fork |
| 主干 + 短分支(GitHub Flow) | 多数 Web 项目 | 保护 main,短生命周期 feature | main ← feature,频繁集成 | 功能分支 |
| 发布分支(Git Flow 简化) | 有版本发布节奏的产品 | main + release/* + hotfix/* | 发版从 release 切,热修复进 main | 热修复 |
具体用哪种以 目标仓库 的 CONTRIBUTING / 团队文档为准;下文按 最常见 的「共享库 + feature 分支 + PR」和「Fork + upstream」两条线讲。
远程与分支命名(惯例)¶
| 名称 | 常见含义 |
|---|---|
origin | 你 默认 push/pull 的远程(自己的 fork 或团队库) |
upstream | Fork 场景下,上游官方 仓库(只 fetch,一般不直接 push) |
main / master | 主线,受保护、随时可部署或集成 |
feature/*、fix/* | 功能 / 修复分支,合并后常删除 |
release/* | 发布准备分支(部分团队) |
本篇相关 Git 命令¶
| 命令 | 干什么 | 场景 | 命令集 |
|---|---|---|---|
git clone | 拷远程仓库到本地 | 首次参与 | git clone |
git remote add upstream | 添加上游远程 | Fork | git remote |
git fetch | 拉远程更新,不合并 | 同步主线 | git fetch |
git pull / pull --rebase | 拉并合并到当前分支 | 同步 | git pull |
git switch -c | 创建并切换分支 | 功能分支 | git switch |
git push -u origin | 首次 push 并记 upstream | 推分支开 PR | git push |
git merge | 合并另一分支进当前分支 | 合主线、冲突 | git merge |
git rebase | 变基到另一分支顶端 | 线性历史 | git rebase |
git push --force-with-lease | 安全强推(feature 分支) | rebase 后 push | git push |
PR 生命周期(平台无关)¶
创建分支 → 本地 commit → push 远程分支 → 开 PR/MR
→ CI 跑测 → Review 评论 → 修改后 push(同分支更新 PR)
→ Approve → Merge(merge / squash / rebase 三选一)
→ 删远程 feature 分支 → 本地切回 main 并 pull
合并后 commit 说明怎么写,见 提交规范 — PR 合并。
场景:首次 clone,作为仓库成员¶
常见场景:公司项目、你被加为 collaborator,直接 clone 团队仓库。
# HTTPS 或 SSH 二选一
git clone git@github.com:ORG/APP.git
cd APP
# 看远程
git remote -v
# origin git@github.com:ORG/APP.git (fetch)
# origin git@github.com:ORG/APP.git (push)
# 确认本地 main 跟踪远程
git switch main
git pull origin main
一句话:「origin 就是团队库,从 main 拉最新再开分支。」
效果:本地 main 与 origin/main 对齐后,新 work 不应直接在 main 上 commit(除非团队明确允许)。
场景:Fork 开源项目并添加上游¶
常见场景:没有 upstream 写权限,在 GitHub 点 Fork 后 clone 自己的 fork。
# clone 的是你的 fork
git clone git@github.com:YOUR_NAME/APP.git
cd APP
# 添加上游官方库(只读同步用)
git remote add upstream git@github.com:ORG/APP.git
git remote -v
# origin 你的 fork(push 到这里)
# upstream 官方库(fetch 同步)
# 首次:拉 upstream 的 main
git fetch upstream
git switch main
git merge upstream/main # 或 rebase,与团队习惯一致
一句话:「push 到 origin(fork),PR 的目标是 upstream(官方)。」
效果:你的 commit 先出现在 fork;合并进官方后,其他贡献者从 upstream 拉。
场景:开工前同步 main¶
常见场景:隔了一晚上 / 别人刚 merge 了 PR,你要基于最新 main 开分支。
git switch main
git pull origin main
# Fork 场景:先同步 upstream
git fetch upstream
git merge upstream/main
# 可选:把更新推回自己的 fork
git push origin main
一句话:「动新活之前,先把 main 拉到跟远程一样新。」
Note
若 main 受保护无法直接 push(Fork 时有时可 push 自己的 main),以平台规则为准;关键是 本地 main 包含 upstream 最新 commit 再切分支。
场景:功能分支开发与提交¶
常见场景:做一个 issue / 一个独立功能,生命周期几天内。
git switch main
git pull origin main
git switch -c feature/oauth-login
# 开发、多次 commit(说明见提交规范)
git add .
git commit -m "feat(auth): add OAuth callback handler"
git commit -m "test(auth): cover OAuth error paths"
一句话:「一个功能一条分支,commit 可以多个,但每个 commit 意图清晰。」
效果:main 保持干净;review 以 整个 PR 或 每个 commit 为单位,取决于团队。
场景:push 分支并开 Pull Request¶
# 首次 push:-u 建立 upstream 跟踪
git push -u origin feature/oauth-login
# 之后在网页:Compare & pull request
# 目标分支通常是 upstream/main(Fork)或 origin/main(成员库)
# 标题按提交规范写 — squash 时常变成最终 commit 说明
常见场景:
- PR 描述写 做了什么、为什么、如何测
- 关联 Issue:
Closes #123(见 Trailer) - Review 意见回来:在同一分支继续 commit + push,PR 自动更新
场景:长期分支如何跟进 main¶
feature 做了几天,main 已经前进,需要把最新 main 合进 feature。
方式 A:merge(保留 merge commit,简单)
git switch feature/oauth-login
git fetch origin
git merge origin/main
# 有冲突则解决后 git add && git commit
git push
方式 B:rebase(历史一条线,需 force push)
git switch feature/oauth-login
git fetch origin
git rebase origin/main
# 冲突:解决 → git add → git rebase --continue
git push --force-with-lease
| merge main 进 feature | rebase feature onto main | |
|---|---|---|
| 历史 | 可能有 merge commit | 线性 |
| push | 普通 push | 常需 --force-with-lease |
| 风险 | 较低 | 仅 个人分支;勿 rebase 已多人基于的分支 |
场景:rebase 还是 merge — 怎么选¶
常见团队约定(通用参考,非强制):
| 场景 | 倾向 |
|---|---|
| 合 feature → main(PR merge) | 平台选 squash / merge / rebase;很多团队 PR 用 squash |
| 更新 自己的 feature 与 main 对齐 | merge 或 rebase 均可;开源 fork 常用 rebase 保持 PR 干净 |
共享分支(多人 push 的 dev) | merge,不要 rebase 改历史 |
| 已 merge 的 main | 禁止 force push |
Warning
git push --force 会覆盖远程历史。优先 --force-with-lease(远程有别人新 push 时会拒绝),并与协作者确认。
场景:解决 merge / rebase 冲突¶
常见场景:同一文件的同一区域被两人修改。
git merge origin/main
# Auto-merging src/app.ts
# CONFLICT (content): Merge conflict in src/app.ts
git status
# both modified: src/app.ts
# 打开文件,找冲突标记:
# <<<<<<< HEAD
# 你的改动
# =======
# 对方的改动
# >>>>>>> origin/main
# 手工合并后:
git add src/app.ts
git commit # merge 完成
# 若在 rebase 中:
git add src/app.ts
git rebase --continue
# 放弃 rebase:git rebase --abort
一句话:「冲突不是 error,是 Git 要你 人工决定 保留哪段代码。」
效果:解决并 commit 后,PR 可继续;merge commit 有两个父提交时,用 git show HEAD^2 看另一侧(见 git show)。
场景:共享分支上的规矩¶
常见场景:main、develop 多人依赖,CI 和发布都盯着它。
| 约定 | 原因 |
|---|---|
禁止 直接 force push main | 会拆别人的本地历史 |
| 禁止 在已 push 的共享分支 rebase | 同上 |
| 通过 PR + review + CI 合入 | 质量与审计 |
| 合并后 删远程 feature 分支 | 减少陈旧分支 |
| hotfix 从 tag 或 release 分支 切 | 见 热修复 |
误 push 到 main 时:用 revert 新增反向 commit,而不是 reset 远程(见 提交规范 — 已 push)。
场景:生产热修复¶
常见场景:线上 bug,需从稳定点切分支,修完并进 main 与发布线。
git fetch origin
git switch -c hotfix/payment-timeout origin/release/v2.3
# 或从 tag:git switch -c hotfix/xxx v2.3.1
# 修复、测试、commit
git commit -m "fix: handle payment gateway timeout"
git push -u origin hotfix/payment-timeout
# 开 PR → main 与 release 分支(视团队流程)
一句话:「热修从 稳定点 切,别从半成品 feature 上修。」
场景:PR 合并之后本地清理¶
# 远程 PR 已 merge,网页上可删 remote branch
git switch main
git pull origin main
# 删本地 feature 分支
git branch -d feature/oauth-login
# 若 Git 提示未 merge 但你确认已合:git branch -D ...
# 清理已删的远程跟踪分支
git fetch origin --prune
效果:下次从最新 main 再切新分支,避免在 stale 分支上继续堆 commit。
场景:别人先 push 了,你 push 被拒¶
git push origin feature/oauth-login
# ! [rejected] ... (fetch first)
git fetch origin
git merge origin/feature/oauth-login
# 或 rebase origin/feature/oauth-login(仅个人分支)
git push
常见场景:两人极少同分支协作;更常见是 main 变了 而你未同步 — 回到 跟进 main。
速查:现象 → 建议¶
| 现象 | 建议 |
|---|---|
| 第一次参与项目 | 读 CONTRIBUTING → clone → 同步 main → 开分支 |
| 开源无写权限 | Fork → upstream → 从 upstream 同步 main |
| 不知 push 到哪 | git remote -v;PR 目标看网页 upstream/origin |
| PR 有 conflict | 本地 merge/rebase main → 解决 → push |
| feature 很旧 | 更新分支 再求 review |
| 能否 force push | 仅 仅你使用的 feature;用 --force-with-lease |
| main 上误提交 | revert,不要改写了的历史 |
| merge 后分支一堆 | git fetch --prune + 删本地已合并分支 |
命令索引:Git 命令集。