一、分支是什么
分支(branch)本质上是一个指向某次提交的可移动指针 。每次提交后,当前分支指针自动前移;HEAD 则指向当前所在的分支。
gitGraph
commit id: "C1"
commit id: "C2"
branch feature/login
checkout feature/login
commit id: "C3"
commit id: "C4"
checkout main
commit id: "C5"
分支的核心价值:让多人/多任务并行开发互不干扰 。你在 feature/login 上写登录功能时,别人可以在 feature/pay 上写支付功能,互不影响;功能完成后再合并回主干。
二、主干分支规范(master / main)
| 项目 | 说明 |
|---|---|
| 默认分支名 | 早期 Git 默认 master;Git 2.28+ 可通过 git init -b main 或配置 init.defaultBranch 使用 main |
| 主干定位 | 永远保持稳定、可运行、可发布的代码 |
| 基本规则 | 不在主干上直接写功能;一切开发在分支进行,稳定后合并回主干 |
bash
# 设置新仓库默认分支为 main(推荐)
git config --global init.defaultBranch main
三、分支的增删改查
3.1 查看
bash
git branch # 列出本地分支,* 号为当前分支
git branch -a # 查看包含远程分支的全部列表
git branch -vv # 查看各分支与远程的跟踪关系
3.2 创建与切换
bash
git branch feature/login # 创建分支(不切换)
git checkout -b feature/login # 创建并切换(旧式写法)
git switch -c feature/login # 创建并切换(Git 2.23+ 推荐)
git switch feature/login # 切换到已存在的分支
git checkout feature/login # 旧式写法,效果相同
注意 :
git switch与git checkout在当前版本中功能等价,新项目建议统一使用switch(职责更单一)。
3.3 删除与重命名
bash
git branch -d feature/login # 删除已合并的分支
git branch -D feature/login # 强制删除未合并分支(丢失其独有提交,慎用)
git branch -m old-name new-name # 重命名当前分支
3.4 分支命令速查
| 场景 | 命令 |
|---|---|
| 查看分支 | git branch |
| 创建分支 | git branch <name> |
| 创建并切换 | git switch -c <name> |
| 切换分支 | git switch <name> |
| 删除已合并分支 | git branch -d <name> |
| 强制删除分支 | git branch -D <name>(危险) |
| 重命名分支 | git branch -m <新名> |
四、合并分支(merge)
合并有两种形态,取决于两个分支是否分叉。
4.1 快速合并(Fast-forward)
条件:当前分支是目标分支的"直系祖先",历史没有分叉。此时只需把指针直接前移,不产生新提交。
flowchart LR
subgraph 合并前
A1[C1] --> A2[C2] --> A3[C3]
A2 -.feature/login 停在 C2.-> A2
end
subgraph 合并后
B1[C1] --> B2[C2] --> B3[C3]
B3 -.main 与 feature/login 都指向 C3.-> B3
end
bash
git switch main # 先回到主干
git merge feature/login # 快速合并,输出 "Fast-forward"
4.2 普通合并(Merge commit)
条件 :两个分支各自有独立提交,历史分叉。Git 会生成一个合并提交(merge commit),把两边的改动合到一起。
gitGraph
commit id: "C1"
commit id: "C2"
branch feature/login
checkout feature/login
commit id: "C3"
checkout main
commit id: "C4"
merge feature/login
bash
git switch main
git merge feature/login # 输出 "Merge made by the 'ort' strategy."
git log --oneline --graph # 能看到合并产生的分叉与汇合
4.3 禁止快速合并
需要保留"功能分支完整历史"时,用 --no-ff 强制生成合并提交,便于后续回溯:
bash
git merge --no-ff feature/login
| 对比项 | Fast-forward | 普通合并 |
|---|---|---|
| 前提 | 历史无分叉 | 历史有分叉 |
| 是否产生新提交 | 否,指针前移 | 是,生成 merge commit |
| 历史是否保留分支信息 | 不保留 | 保留 |
| 回退 | 简单 | 可整体回退合并 |
五、代码冲突完整实战
5.1 冲突产生原因
两个分支修改了同一个文件的同一区域(或一方删除、另一方修改),Git 无法自动判断该保留哪份,只能交给人工处理。
5.2 冲突标记含义
执行 git merge 后若冲突,冲突文件内会出现如下标记:
markdown
<<<<<<< HEAD
这是 main 分支的代码(当前分支)
=======
这是 feature/login 分支的代码(被合并分支)
>>>>>>> feature/login
| 标记 | 含义 |
|---|---|
<<<<<<< HEAD |
冲突区块开始,上方是当前分支(HEAD)的内容 |
======= |
分界线 |
>>>>>>> feature/login |
冲突区块结束,下方是被合并分支的内容 |
5.3 实战流程(以 login.py 冲突为例)
第 1 步:触发合并
bash
git switch main
git merge feature/login
# 输出:CONFLICT (content): Merge conflict in login.py
git status
# 冲突文件标记为 both modified
第 2 步:打开冲突文件
bash
# login.py 内容:
<<<<<<< HEAD
def login(user):
print("main 版本登录")
=======
def login(user, code):
print("带验证码登录")
>>>>>>> feature/login
第 3 步:手动解决------保留需要的代码,删除冲突标记
python
def login(user, code):
print("带验证码登录")
解决原则:两边都合理就合并保留,以业务需求为准,必要时与同事沟通确认。
第 4 步:标记已解决并提交
bash
git add login.py # 告诉 Git 该冲突已解决
git commit # 完成合并提交(无需 -m,Git 已填好默认信息)
5.4 解决步骤速记
| 步骤 | 操作 |
|---|---|
| 1 | git status 找出冲突文件 |
| 2 | 打开文件,定位 <<<<<<< / ======= / >>>>>>> 标记 |
| 3 | 手动取舍代码,删除全部冲突标记 |
| 4 | git add <file> 标记已解决 |
| 5 | git commit 完成合并 |
想放弃本次合并:
git merge --abort可回到合并前状态。
六、团队开发规范:分支开发、主干稳定
6.1 分支命名规范
| 分支类型 | 命名示例 | 用途 |
|---|---|---|
| 主干 | main / master |
稳定可发布的代码 |
| 新功能 | feature/login、feature/order-list |
开发新功能 |
| Bug 修复 | bugfix/price-calc |
修复已发现问题 |
| 紧急修复 | hotfix/security-patch |
线上紧急问题,直连主干修复 |
6.2 标准开发流程
flowchart LR
A[main 主干] -->|git switch -c feature/xxx| B[功能分支开发]
B -->|开发 + 测试完成| C[合并回 main]
C -->|git branch -d 清理| A
- 从主干拉分支 :
git switch -c feature/login(保证分支基于最新主干); - 在分支上开发 :多次提交,随时
git push备份; - 合并前先同步主干 :
git switch main && git pull,再切回分支git merge main提前解决冲突; - 合并回主干 :
git switch main && git merge --no-ff feature/login; - 删除已合并分支 :
git branch -d feature/login。
6.3 规范要点
- 主干永远稳定:只接受已测试的功能合并,禁止直接在主干写代码;
- 一个分支一件事:分支职责单一,便于 review 与回退;
- 小步提交 :提交信息清晰(
feat:/fix:前缀),便于定位问题; - 及时清理:合并后删除分支,避免分支堆积。
七、总结
- 分支 = 指向提交的指针,
HEAD标记当前所在; - 增删改查 :
switch -c创建切换、branch -d删除、branch -m重命名; - 合并 :无分叉走 fast-forward,有分叉生成 merge commit,
--no-ff强制保留分支历史; - 冲突 :同一文件同一位置被两边修改,用
<<<<<<</=======/>>>>>>>定位,人工取舍后add+commit; - 规范:feature/bugfix 分支开发,main 主干保持稳定,合并后及时清理。