853 lines
23 KiB
Markdown
853 lines
23 KiB
Markdown
# 团队 Git 协作完整规范
|
||
|
||
> 适用对象:个人项目、小项目、大项目
|
||
> 版本:v1.0 · 2026-05-07
|
||
|
||
---
|
||
|
||
## 一、核心原则
|
||
|
||
不论团队规模大小,所有 Git 协作都遵守以下 5 条铁律:
|
||
|
||
1. **主干(main)永远可发布**
|
||
2. **凡是会影响他人的操作,事前通知、事中可见、事后可恢复**
|
||
3. **分支属于"任务",不属于"人"**(详见第六章)
|
||
4. **推送前先同步**:`git pull --rebase` 后再 `git push`
|
||
5. **重要分支禁止直接 push,必须走 PR**
|
||
|
||
---
|
||
|
||
## 二、如何选择工作流
|
||
|
||
### 决策树
|
||
|
||
```
|
||
你一个人做这个项目吗?
|
||
├─ 是 → 【方案 A】个人极简流
|
||
└─ 否 → 团队 ≥ 6 人 或 同时维护多版本?
|
||
├─ 是 → 【方案 C】Git Flow Lite(带 develop)
|
||
└─ 否 → 【方案 B】GitHub Flow(90% 小项目适用)
|
||
```
|
||
|
||
### 三种方案对比
|
||
|
||
| 维度 | A·个人 | B·小项目 | C·大项目 |
|
||
|------|--------|---------|---------|
|
||
| 团队规模 | 1 人 | 2-5 人 | 6+ 人 |
|
||
| 主分支 | main | main | main + develop |
|
||
| 是否需 develop | ❌ | ❌ | ✅ |
|
||
| 是否需 release 分支 | ❌ | ❌ | ✅(可选) |
|
||
| 是否需 hotfix 分支 | ❌ | ✅ | ✅ |
|
||
| 部署策略 | 手动 / tag | 持续部署 | 阶段部署 |
|
||
| 发布周期 | 不固定 | 随时 | 双周 / 月度 |
|
||
| PR Review | 自看 | ≥1 人 | ≥2 人 |
|
||
| 复杂度 | ★ | ★★ | ★★★★ |
|
||
|
||
### 升级信号
|
||
|
||
**A → B**:第二个人加入,立刻配 main 保护 + PR 流程。
|
||
|
||
**B → C**:满足以下任一即升级
|
||
- 同时维护多个版本(v1 还在用,v2 在开发)
|
||
- 有专门 QA 阶段,main 不能合并即上线
|
||
- 发布周期 ≥ 2 周
|
||
- 团队 ≥ 6 人
|
||
|
||
> ⚠️ **宁可滞后升级,也不要预防性复杂化**。多数团队过度设计,把简单事搞复杂。
|
||
|
||
---
|
||
|
||
## 三、方案 A:个人项目工作流
|
||
|
||
### 分支模型
|
||
|
||
```
|
||
main (主线 + 发布锚点)
|
||
└─ feature/* (按需,仅用于实验性大改动)
|
||
```
|
||
|
||
### 日常工作流
|
||
|
||
**小改动 → 直接上 main**
|
||
|
||
```bash
|
||
git add .
|
||
git commit -m "fix: 修复登录按钮样式"
|
||
git push
|
||
```
|
||
|
||
**大改动 / 不确定的实验 → 开分支保命**
|
||
|
||
```bash
|
||
git checkout -b feature/重构数据层
|
||
# ...开发...
|
||
|
||
# 没问题 → 合并
|
||
git checkout main
|
||
git merge --no-ff feature/重构数据层
|
||
git push
|
||
git branch -d feature/重构数据层
|
||
|
||
# 实验失败 → 直接丢弃
|
||
git checkout main
|
||
git branch -D feature/重构数据层
|
||
```
|
||
|
||
### 发布流程
|
||
|
||
```bash
|
||
git tag -a v1.2.0 -m "release: v1.2.0 - 评查详情页上线"
|
||
git push --tags
|
||
```
|
||
|
||
**版本号遵循 [SemVer](https://semver.org/)**:
|
||
- `v主版本.次版本.补丁`
|
||
- 主版本:不兼容改动
|
||
- 次版本:新功能(向下兼容)
|
||
- 补丁:bug 修复
|
||
|
||
### 个人项目最低纪律
|
||
|
||
| 习惯 | 价值 |
|
||
|------|------|
|
||
| 每天 push 到远程 | 硬盘坏了不丢工 |
|
||
| commit 信息写人话 | 半年后能看懂 |
|
||
| 重大改动前打 tag | 有回滚锚点 |
|
||
| README 记录关键决策 | 时间久了不抓瞎 |
|
||
| `.gitignore` 配齐 | 不把密钥推上去 |
|
||
|
||
### 不要做的事
|
||
|
||
- ❌ `git commit -m "update"` / `"修改"` / `"123"`
|
||
- ❌ 一周不 push
|
||
- ❌ 在 main 上做不确定的实验
|
||
- ❌ 把 `.env` 推到远程
|
||
|
||
---
|
||
|
||
## 四、方案 B:小项目工作流(GitHub Flow)
|
||
|
||
**适用:2-5 人,持续部署**
|
||
|
||
### 分支模型
|
||
|
||
```
|
||
main (受保护,PR 合并,自动部署到生产)
|
||
├─ feature/评查详情页
|
||
├─ fix/登录闪退
|
||
└─ hotfix/支付失败 (紧急修生产)
|
||
```
|
||
|
||
**核心思想**:
|
||
- main 永远可发布
|
||
- feature 分支**生命周期短**(1-3 天最佳,最长 1 周)
|
||
- 所有改动走 PR
|
||
|
||
### 日常工作流(每个任务都按这个跑)
|
||
|
||
```bash
|
||
# 1. 开分支前先同步 main
|
||
git checkout main
|
||
git pull --rebase
|
||
|
||
# 2. 创建任务分支(任务命名,不要带人名)
|
||
git checkout -b feature/评查详情页
|
||
|
||
# 3. 开发,频繁小步提交,频繁推送
|
||
git add .
|
||
git commit -m "feat(评查): 新增详情页骨架"
|
||
git push -u origin feature/评查详情页
|
||
|
||
# 4. 推送前同步 main,避免冲突堆积
|
||
git fetch origin
|
||
git rebase origin/main
|
||
# 解决冲突 → 本地测试通过
|
||
|
||
# 5. 推送(rebase 后需要 force-with-lease)
|
||
git push --force-with-lease
|
||
|
||
# 6. 提 PR → Review → 合并 → 自动部署
|
||
|
||
# 7. 合并后清理本地
|
||
git checkout main
|
||
git pull
|
||
git branch -d feature/评查详情页
|
||
```
|
||
|
||
### PR 流程规范
|
||
|
||
**提 PR 时**:
|
||
- 标题:`<type>(<scope>): <简短描述>`,例:`feat(评查): 新增详情页`
|
||
- 描述模板:
|
||
```markdown
|
||
## 改动内容
|
||
- ...
|
||
|
||
## 测试方法
|
||
- ...
|
||
|
||
## 截图(如有 UI 改动)
|
||
|
||
## 关联 Issue
|
||
Closes #123
|
||
```
|
||
- 自检:lint 通过、测试通过、不含调试代码
|
||
|
||
**Review 时**:
|
||
- 24 小时内响应
|
||
- 给具体可操作的反馈,不要"建议优化一下"
|
||
- Approve 前自己心里跑一遍代码逻辑
|
||
|
||
### 紧急修复(hotfix)
|
||
|
||
```bash
|
||
git checkout main && git pull
|
||
git checkout -b hotfix/支付失败
|
||
# 修 → 测 → push → PR → 紧急合并 → 立即部署
|
||
```
|
||
|
||
### 仓库一次性配置(落地关键)
|
||
|
||
**main 分支保护(GitHub/GitLab 后台)**:
|
||
- ✅ 禁止直接 push
|
||
- ✅ 禁止 force push
|
||
- ✅ 必须 PR + ≥1 Approve
|
||
- ✅ 必须通过 CI(lint + test)
|
||
- ✅ 合并后自动删除分支
|
||
|
||
---
|
||
|
||
## 五、方案 C:大项目工作流(Git Flow Lite)
|
||
|
||
**适用:6+ 人 / 多版本并存 / 有 QA 测试期**
|
||
|
||
### 分支模型
|
||
|
||
```
|
||
main (生产版本,受保护,只接受来自 release/hotfix 的合并)
|
||
└─ develop (开发主线,受保护,所有 feature 合并到这里)
|
||
├─ feature/评查详情页 (个人功能分支)
|
||
├─ feature/登录优化
|
||
├─ release/v2.3.0 (准备发布的快照分支)
|
||
└─ hotfix/支付失败 (从 main 拉,修完合并回 main + develop)
|
||
```
|
||
|
||
### 各分支角色
|
||
|
||
| 分支 | 来源 | 合并去向 | 生命周期 |
|
||
|------|------|---------|---------|
|
||
| `main` | 永久 | — | 永久 |
|
||
| `develop` | 永久 | — | 永久 |
|
||
| `feature/*` | develop | develop | 任务期 |
|
||
| `release/*` | develop | main + develop | 发布周期 |
|
||
| `hotfix/*` | main | main + develop | 紧急修复 |
|
||
|
||
### develop 的角色
|
||
|
||
- **开发主线**:所有 feature 合并到 develop
|
||
- **集成测试环境**:QA 在 develop 上测试
|
||
- **不直接发布**:发布前从 develop 拉 release 分支封板
|
||
|
||
### release 分支:发布前的"封板"
|
||
|
||
```bash
|
||
# 1. 从 develop 拉 release 分支(功能冻结)
|
||
git checkout develop && git pull
|
||
git checkout -b release/v2.3.0
|
||
|
||
# 2. 在 release 上只修 bug,不加新功能
|
||
# QA 测试 → 修 bug → 改版本号 → 写 changelog
|
||
|
||
# 3. 测试通过,合并到 main 并打 tag
|
||
git checkout main && git pull
|
||
git merge --no-ff release/v2.3.0
|
||
git tag -a v2.3.0 -m "release: v2.3.0"
|
||
git push --tags
|
||
|
||
# 4. 合并回 develop(带上 release 上的 bug 修复)
|
||
git checkout develop
|
||
git merge --no-ff release/v2.3.0
|
||
git push
|
||
|
||
# 5. 删除 release 分支
|
||
git branch -d release/v2.3.0
|
||
```
|
||
|
||
### hotfix 分支:紧急修生产
|
||
|
||
```bash
|
||
# 1. 从 main 拉 hotfix 分支
|
||
git checkout main && git pull
|
||
git checkout -b hotfix/支付失败
|
||
|
||
# 2. 修 → 测 → 提 PR
|
||
|
||
# 3. 合并到 main 并打 patch tag
|
||
git checkout main
|
||
git merge --no-ff hotfix/支付失败
|
||
git tag -a v2.3.1 -m "hotfix: 修复支付失败"
|
||
git push --tags
|
||
|
||
# 4. 必须合并回 develop!否则下次发布 bug 复发
|
||
git checkout develop
|
||
git merge --no-ff hotfix/支付失败
|
||
git push
|
||
|
||
# 5. 删除 hotfix 分支
|
||
git branch -d hotfix/支付失败
|
||
```
|
||
|
||
### 日常 feature 工作流
|
||
|
||
```bash
|
||
# 从 develop(不是 main!)开分支
|
||
git checkout develop && git pull --rebase
|
||
git checkout -b feature/评查详情页
|
||
|
||
# 开发 → 推送 → PR 到 develop(不是 main!)
|
||
git push -u origin feature/评查详情页
|
||
# 提 PR:feature/评查详情页 → develop
|
||
```
|
||
|
||
### 大项目仓库配置
|
||
|
||
- **main**:禁止 push、禁止 force push、只接受 release/hotfix 合并、必须 ≥2 Approve
|
||
- **develop**:禁止 push、必须 PR + ≥1 Approve、必须通过 CI
|
||
- **CI 要求**:lint + 单元测试 + 集成测试 + 静态分析
|
||
|
||
---
|
||
|
||
## 六、为什么禁止使用个人分支【专题】
|
||
|
||
### 反模式(团队中常见错误)
|
||
|
||
```
|
||
❌ feature/评查详情页-zhangsan
|
||
❌ zhangsan-dev
|
||
❌ feature/zhangsan/xxx
|
||
❌ 张三的分支
|
||
❌ wy-dev / wy-test
|
||
```
|
||
|
||
### 5 大问题
|
||
|
||
#### 1️⃣ 强化"个人所有权",破坏协作精神
|
||
|
||
分支带人名 → 同事潜意识"这是张三的地盘,我别动" → 协作变独行 → 出问题没人帮看。
|
||
|
||
**好的协作是任务驱动**:分支属于任务,谁有空谁接手。
|
||
|
||
#### 2️⃣ 离职、休假、轮岗时难交接
|
||
|
||
**真实场景**:
|
||
> 张三休假一周,留下 5 条 `feature/xxx-zhangsan` 分支。李四接手时是改名(影响远程)、还是新开 `feature/xxx-lisi`(造成分裂)?怎么处理都别扭。
|
||
|
||
如果分支叫 `feature/评查详情页`,李四直接 `git checkout` 接着干,**零摩擦**。
|
||
|
||
#### 3️⃣ 分支语义模糊,看名字不知道做什么
|
||
|
||
`zhangsan-dev` 这条分支在做啥?
|
||
- 评查模块?
|
||
- 登录优化?
|
||
- 性能调优?
|
||
- 还是张三的"我啥都往这塞"草稿?
|
||
|
||
**好的分支名 = 一句话任务说明**,看到 `feature/评查详情页` 立刻明白。
|
||
|
||
#### 4️⃣ 容易堆积成"杂物分支"
|
||
|
||
人名分支没有边界,张三会把"评查详情页 + 顺手优化的登录 + 试验性能改动"都塞进 `feature/zhangsan-dev`。结果:
|
||
- PR 改动巨大,没人能 Review
|
||
- 一个 bug 拖延了三个功能
|
||
- 不能单独 revert 某项改动
|
||
|
||
**任务分支天然有边界**:`feature/评查详情页` 只装评查相关改动,超出范围就该开新分支。
|
||
|
||
#### 5️⃣ 多人协作同一功能时命名混乱
|
||
|
||
**真实场景**:
|
||
> 评查详情页很大,张三李四王五一起做。分支会变成:
|
||
> - `feature/评查详情页-zhangsan`
|
||
> - `feature/评查详情页-lisi`
|
||
> - `feature/评查详情页-wangwu`
|
||
>
|
||
> 三人改动如何同步?合并顺序?谁先合谁后合?混乱。
|
||
|
||
**正确做法**:开一条父分支 `feature/评查详情页`,每人开**子任务分支**:
|
||
- `feature/评查详情页-头部`
|
||
- `feature/评查详情页-列表`
|
||
- `feature/评查详情页-筛选`
|
||
|
||
子任务都合并回父分支,最后父分支整体合到 develop。
|
||
|
||
---
|
||
|
||
### 真实案例:人名分支造成的事故
|
||
|
||
**案例 1:交接黑洞**
|
||
> 某团队张三离职前留下 `zhangsan/refactor-payment` 分支,里面有他重构支付的工作(约 60% 完成)。半年后团队想接着做,发现:分支与 main 已差异巨大,无法 rebase;分支内 commit 信息全是"WIP",没人知道每个 commit 在做什么;最终只能放弃,**重做**。
|
||
|
||
**案例 2:紧急修复无法落地**
|
||
> 周五晚上生产支付功能挂了。值班发现修复需要改一个文件,但该文件在 `feature/支付重构-zhangsan` 分支上张三已改了一周。要么强行修生产(与张三的分支冲突会变大),要么等张三周一来。最终用了一个肮脏的 hotfix,**技术债累计**。
|
||
|
||
**案例 3:PR Review 无人能审**
|
||
> `feature/zhangsan-dev` 一个 PR 改了 2000 行,包含评查、登录、列表、性能 4 个不相关的改动。Review 同事看了一上午放弃,盖章通过。两天后线上 bug,**无法定位是哪个改动引起的**。
|
||
|
||
---
|
||
|
||
### 正确做法
|
||
|
||
#### ✅ 任务命名规范
|
||
|
||
```
|
||
feature/<任务描述> feature/评查详情页
|
||
feature/<issue号>-<描述> feature/PROJ-123-评查详情页
|
||
fix/<bug简述> fix/登录闪退
|
||
hotfix/<紧急bug> hotfix/支付失败
|
||
refactor/<范围> refactor/数据层
|
||
```
|
||
|
||
#### ✅ 任务归属体现在 PR/Issue Assignee
|
||
|
||
谁负责这个任务 → 在 **PR/Issue 的 Assignee** 字段标记,不要污染分支名。
|
||
|
||
#### ✅ 分支只与「任务/目标」关联
|
||
|
||
看到 `feature/评查详情页` 应当能立刻回答:
|
||
- 这条分支在做什么
|
||
- 合并目标是什么
|
||
- 何时该删除
|
||
|
||
---
|
||
|
||
### 例外:可以带人名的场景
|
||
|
||
**仅限以下短期、可丢弃的情况**:
|
||
|
||
#### 1. 个人探索/草稿分支(明确不打算合并)
|
||
|
||
```
|
||
zhangsan/试个性能方案
|
||
zhangsan/sandbox
|
||
```
|
||
|
||
用斜线作为"个人 sandbox 命名空间"前缀,与正式 feature 分支区分。
|
||
|
||
#### 2. Fork 工作流(开源项目常见)
|
||
|
||
你 fork 仓库到自己账号后,分支名随意,提 PR 时再说。这是**远程 fork 模式**,不属于"单仓库协作"场景。
|
||
|
||
#### 3. 多人并行试方案的临时区分
|
||
|
||
```
|
||
feature/评查详情页/方案A-zhangsan
|
||
feature/评查详情页/方案B-lisi
|
||
```
|
||
|
||
验证完保留赢的方案,删除全部分支,重命名为正式分支。
|
||
|
||
> **核心:这些场景都是短期、明确不污染主流分支的。**
|
||
|
||
---
|
||
|
||
## 七、通用规范
|
||
|
||
### 分支命名
|
||
|
||
```
|
||
<type>/<description>
|
||
<type>/<issue-id>-<description>
|
||
```
|
||
|
||
**type 类型**:
|
||
- `feature/` 新功能
|
||
- `fix/` bug 修复
|
||
- `hotfix/` 紧急修复(生产)
|
||
- `refactor/` 重构
|
||
- `docs/` 文档
|
||
- `test/` 测试
|
||
- `chore/` 杂项(依赖升级、配置)
|
||
- `release/` 发布分支(仅 Git Flow)
|
||
|
||
**示例**:
|
||
```
|
||
feature/评查详情页
|
||
feature/PROJ-123-评查详情页
|
||
fix/登录闪退
|
||
hotfix/v2.3-支付失败
|
||
```
|
||
|
||
**禁止**:
|
||
- ❌ 人名前缀/后缀
|
||
- ❌ 拼音缩写如 `wy-dev`
|
||
- ❌ 没有 type 前缀
|
||
- ❌ 空格、特殊字符
|
||
|
||
### 提交信息(Conventional Commits)
|
||
|
||
```
|
||
<type>(<scope>): <简短描述>
|
||
|
||
<可选详细说明>
|
||
|
||
<可选 footer>
|
||
```
|
||
|
||
**type**:
|
||
- `feat:` 新功能
|
||
- `fix:` 修 bug
|
||
- `refactor:` 重构(不改外部行为)
|
||
- `perf:` 性能优化
|
||
- `test:` 测试
|
||
- `docs:` 文档
|
||
- `style:` 格式(不改代码逻辑)
|
||
- `chore:` 杂项
|
||
- `build:` 构建相关
|
||
- `ci:` CI 相关
|
||
|
||
**示例**:
|
||
```
|
||
feat(评查): 新增详情页骨架屏
|
||
|
||
- 添加加载占位组件
|
||
- 实现进入动画
|
||
- 适配移动端
|
||
|
||
Closes #123
|
||
```
|
||
|
||
**禁止**:
|
||
- ❌ `update`、`fix`、`修改`、`123`
|
||
- ❌ 一个 commit 改 N 个不相关的事
|
||
- ❌ `WIP`(合并前应 squash 掉)
|
||
|
||
### 标签(Tag)规范
|
||
|
||
**版本标签**遵循 [SemVer](https://semver.org/):
|
||
```
|
||
v1.2.3 正式版
|
||
v1.2.3-beta.1 beta 版
|
||
v1.2.3-rc.1 发布候选版
|
||
```
|
||
|
||
**打 tag 时机**:
|
||
- 个人项目:每次发布
|
||
- 小项目:每次部署到生产
|
||
- 大项目:release 合并到 main 时
|
||
|
||
### .gitignore 通用模板
|
||
|
||
```gitignore
|
||
# 依赖
|
||
node_modules/
|
||
__pycache__/
|
||
*.pyc
|
||
venv/
|
||
.venv/
|
||
|
||
# 环境变量(永远不要提交)
|
||
.env
|
||
.env.*
|
||
!.env.example
|
||
|
||
# 编辑器
|
||
.vscode/
|
||
.idea/
|
||
*.swp
|
||
.DS_Store
|
||
|
||
# 构建产物
|
||
dist/
|
||
build/
|
||
*.log
|
||
coverage/
|
||
|
||
# 本地配置
|
||
.cache/
|
||
*.local
|
||
```
|
||
|
||
---
|
||
|
||
## 八、共享资源协作守则
|
||
|
||
### 通用原则
|
||
|
||
> **凡是会影响他人的操作,事前通知、事中可见、事后可恢复。**
|
||
|
||
### 共享资源守则表
|
||
|
||
| 共享资源 | 守则 |
|
||
|---------|------|
|
||
| 共享开发/测试机 | 默认主分支;切换通知;用完还原;优先 `git worktree` |
|
||
| 共享数据库 | 不在共用库做破坏性改动;每人独立 schema;测试用 docker 起本地 |
|
||
| 共享 API Key / Secret | 用 secret manager;禁止贴 IM/代码/截图 |
|
||
| CI/CD pipeline | 改流水线前通知;不在大家忙时触发昂贵任务 |
|
||
| 第三方账号 | SSO + 审计;操作记录可追溯 |
|
||
| 部署环境 | 部署窗口公告;锁机制(谁部署谁举手) |
|
||
|
||
### 切换共享资源的标准动作
|
||
|
||
```
|
||
1. 群里通知:"我要 [操作] [资源],预计 [时间]"
|
||
2. 操作
|
||
3. 用完恢复默认状态
|
||
4. 群里告知:"已恢复"
|
||
```
|
||
|
||
### 优先用隔离手段,而不是切换
|
||
|
||
```bash
|
||
# git worktree:在不同目录跑不同分支,主目录不动
|
||
git worktree add ../preview-xxx feature/xxx
|
||
git worktree remove ../preview-xxx
|
||
|
||
# Docker:每个分支起独立容器
|
||
docker compose -p preview-xxx up
|
||
```
|
||
|
||
### 终极方案:消除"共享"本身
|
||
|
||
- 每个 PR 自动起一个独立预览环境(Vercel / Netlify / K8s preview)
|
||
- 每人独立数据库 schema(自动迁移)
|
||
- 每人独立云资源(云厂商沙盒账号)
|
||
|
||
> **根本不需要"共享调试机"。**
|
||
|
||
---
|
||
|
||
## 九、常见问题 FAQ
|
||
|
||
### Q1:合并前应该用 merge 还是 rebase?
|
||
|
||
| 场景 | 推荐 |
|
||
|------|------|
|
||
| 个人 feature 分支同步 main | `git rebase`(历史干净) |
|
||
| 多人协作的分支 | `git merge`(不重写他人 commit) |
|
||
| 合并 PR 到 main | **Squash and merge**(main 历史干净) |
|
||
| 已推送的分支 | 谨慎使用 rebase,需 `--force-with-lease` |
|
||
|
||
### Q2:feature 分支多久合并一次?
|
||
|
||
- **理想**:1-3 天
|
||
- **可接受**:1 周
|
||
- **超过 1 周必须警惕**:分支过大 → 拆分;同步频率提高(每天 rebase main)
|
||
|
||
### Q3:commit 太多太乱怎么办?
|
||
|
||
合并到主分支前 squash 整理:
|
||
```bash
|
||
git rebase -i HEAD~5
|
||
# 把第二个开始的 pick 改成 squash 或 fixup
|
||
```
|
||
|
||
或在 PR 合并时选择 **"Squash and merge"**。
|
||
|
||
### Q4:误推了敏感信息(密钥)怎么办?
|
||
|
||
1. **立即作废**这个密钥(去后台重新生成)
|
||
2. 用 `git filter-repo` 或 BFG 清除历史
|
||
3. **强制推送**所有分支
|
||
4. **通知所有人**重新 clone
|
||
|
||
预防:
|
||
- `.gitignore` 配齐 `.env`
|
||
- 用 secret manager
|
||
- 装 `git-secrets` / `gitleaks` pre-commit 钩子
|
||
|
||
### Q5:rebase 时遇到冲突怎么办?
|
||
|
||
```bash
|
||
# 1. 解决冲突文件
|
||
# 2. git add <冲突文件>
|
||
# 3. git rebase --continue
|
||
|
||
# 实在搞不定就放弃
|
||
git rebase --abort
|
||
```
|
||
|
||
### Q6:误删了分支怎么恢复?
|
||
|
||
```bash
|
||
# 找到最后一次 commit
|
||
git reflog
|
||
|
||
# 恢复
|
||
git checkout -b feature/xxx <commit-sha>
|
||
```
|
||
|
||
### Q7:`git push` 被拒(rejected)
|
||
|
||
意味着远程分支有新 commit 你本地没有。
|
||
|
||
```bash
|
||
# 同步后再推
|
||
git pull --rebase
|
||
git push
|
||
|
||
# 如果是 rebase 后推自己的分支
|
||
git push --force-with-lease # 注意是 --force-with-lease,不是 --force
|
||
```
|
||
|
||
> ⚠️ **永远不要对 main / develop 用 `--force`!**
|
||
|
||
### Q8:什么时候删分支?
|
||
|
||
- 合并到主干后**立即删除**远程和本地
|
||
- GitHub/GitLab 可设置"合并后自动删除"
|
||
- 本地:`git branch -d feature/xxx`
|
||
|
||
### Q9:长期废弃的分支能直接删吗?
|
||
|
||
先 `git log feature/xxx` 看是否有未合并 commit。若有:
|
||
- 询问作者是否还需要
|
||
- 或导出 patch:`git format-patch main..feature/xxx`
|
||
|
||
### Q10:Reviewer 检查清单
|
||
|
||
审视 PR 是否值得合并:
|
||
|
||
- [ ] 分支命名规范,无人名
|
||
- [ ] 改动只做一件事,与 PR 标题一致
|
||
- [ ] 提交信息规范
|
||
- [ ] 测试覆盖关键路径
|
||
- [ ] CI 全绿
|
||
- [ ] 无调试代码(console.log、注释掉的代码)
|
||
- [ ] 无敏感信息(API Key、密码)
|
||
- [ ] 文档/注释 同步更新
|
||
- [ ] 跑过本地测试
|
||
|
||
---
|
||
|
||
## 十、配套工具与一键配置
|
||
|
||
### 全员 Git 配置(每台机器跑一次)
|
||
|
||
```bash
|
||
# pull 默认 rebase(避免无意义 merge commit)
|
||
git config --global pull.rebase true
|
||
|
||
# push 自动追踪上游
|
||
git config --global push.autoSetupRemote true
|
||
|
||
# rebase 自动 stash
|
||
git config --global rebase.autoStash true
|
||
|
||
# 默认分支名
|
||
git config --global init.defaultBranch main
|
||
|
||
# 换行符处理
|
||
git config --global core.autocrlf input # Mac/Linux
|
||
git config --global core.autocrlf true # Windows
|
||
```
|
||
|
||
### 推荐工具
|
||
|
||
| 类型 | 工具 | 作用 |
|
||
|------|------|------|
|
||
| 提交检查 | husky + lint-staged | commit 前自动跑 lint/format |
|
||
| 提交规范 | commitlint | 强制 Conventional Commits |
|
||
| 密钥扫描 | gitleaks / git-secrets | 防止推送密钥 |
|
||
| 图形化客户端 | Fork / SourceTree / GitKraken | 新人友好 |
|
||
| CLI 增强 | gh / lazygit | 命令行高效操作 |
|
||
| CI/CD | GitHub Actions / GitLab CI | 自动测试和部署 |
|
||
| PR 预览 | Vercel / Netlify | 每 PR 一个独立环境 |
|
||
|
||
### 一键安装 husky + lint-staged + commitlint(Node 项目)
|
||
|
||
```bash
|
||
bun add -D husky lint-staged @commitlint/cli @commitlint/config-conventional
|
||
|
||
# 初始化 husky
|
||
bunx husky init
|
||
|
||
# 配置 commitlint
|
||
echo "export default { extends: ['@commitlint/config-conventional'] }" > commitlint.config.mjs
|
||
|
||
# 添加 hooks
|
||
echo "bunx commitlint --edit \$1" > .husky/commit-msg
|
||
echo "bunx lint-staged" > .husky/pre-commit
|
||
```
|
||
|
||
`package.json` 添加:
|
||
|
||
```json
|
||
{
|
||
"lint-staged": {
|
||
"*.{js,ts,tsx}": ["eslint --fix", "prettier --write"]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 附录:决策速查表
|
||
|
||
### 我该开什么类型的分支?
|
||
|
||
| 我要做的事 | 分支前缀 | 例子 |
|
||
|----------|---------|------|
|
||
| 新功能 | `feature/` | `feature/评查详情页` |
|
||
| 修 bug | `fix/` | `fix/登录闪退` |
|
||
| 紧急修生产 | `hotfix/` | `hotfix/支付失败` |
|
||
| 重构 | `refactor/` | `refactor/数据层` |
|
||
| 写文档 | `docs/` | `docs/api文档` |
|
||
| 升级依赖 | `chore/` | `chore/升级react18` |
|
||
|
||
### 我该写什么 commit type?
|
||
|
||
| 我做了什么 | type |
|
||
|----------|------|
|
||
| 写了新功能 | `feat` |
|
||
| 修 bug | `fix` |
|
||
| 重构(不改行为) | `refactor` |
|
||
| 性能优化 | `perf` |
|
||
| 改文档 | `docs` |
|
||
| 改格式(空格、缩进) | `style` |
|
||
| 加测试 | `test` |
|
||
| 杂项 | `chore` |
|
||
|
||
### 我该用哪个工作流?
|
||
|
||
```
|
||
1 人 → 方案 A(main + 偶尔 feature)
|
||
2-5 人 → 方案 B(GitHub Flow,main + feature + PR)
|
||
6+ 人 / 多版本 → 方案 C(Git Flow Lite,main + develop + ...)
|
||
```
|
||
|
||
---
|
||
|
||
## 附录:一页纸速查(打印贴墙)
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ 团队 Git 协作 · 一页纸速查 │
|
||
├─────────────────────────────────────────────────────────┤
|
||
│ 1. 永远从最新主干开任务分支 │
|
||
│ git checkout main && git pull --rebase │
|
||
│ git checkout -b feature/任务描述 │
|
||
│ │
|
||
│ 2. 分支命名 = 任务,不带人名! │
|
||
│ ✅ feature/评查详情页 │
|
||
│ ❌ feature/评查详情页-zhangsan │
|
||
│ │
|
||
│ 3. commit 写人话 │
|
||
│ ✅ feat(评查): 新增详情页骨架 │
|
||
│ ❌ update │
|
||
│ │
|
||
│ 4. 推送前先同步 │
|
||
│ git fetch && git rebase origin/main │
|
||
│ │
|
||
│ 5. 主分支 = PR 入口,禁止直推 │
|
||
│ │
|
||
│ 6. 共享资源 = 通知 → 操作 → 还原 → 告知 │
|
||
│ │
|
||
│ 7. 永远不对 main/develop --force │
|
||
│ │
|
||
│ 8. 合并后立刻删分支 │
|
||
└─────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|