跳转至

Git 协作流程

多人、多远程 下怎么拉代码、开分支、提 PR、合并。命令细节见 Git 命令集;提交说明见 提交规范

相关文档Git 命令集 · 提交规范 · Gitignore 与 Hooks


阅读指引

  1. 概念:远程、分支、PR 在协作里各扮演什么角色
  2. 总览:常见协作模型、远程命名、命令与流程对照
  3. 场景:从 clone 到 merge 的完整路径与踩坑
  4. 文末速查:现象 → 建议

协作在 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 拉最新再开分支。」

效果:本地 mainorigin/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 自动更新
# 根据 review 修改
git add .
git commit -m "fix: address review comments on token expiry"
git push

场景:长期分支如何跟进 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 vs merge 取舍


场景: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
# rebase 后推送个人 feature(确认无他人基于该分支)
git push --force-with-lease origin feature/oauth-login

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)。


场景:共享分支上的规矩

常见场景maindevelop 多人依赖,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 命令集