本节目标
这一节学习 Git 中非常重要的能力:分支。
你要理解这些问题:
什么是分支?
为什么不要直接在 master/main 上开发?
如何创建自己的功能分支?
如何在不同分支之间切换?
如何把一个分支的代码合并到另一个分支?
Gerrit 工作流中分支有什么作用?
本节重点命令:
git branch
git switch
git switch -c
git merge
git log --oneline --graph
git branch -d
1. 分支是什么
分支可以理解为:
从当前代码版本上,拉出一条独立的开发线。
假设主分支现在是这样:
A --- B --- C main
现在你要开发登录功能,不应该直接在 main 上改,而是创建一个新分支:
A --- B --- C main
\
D --- E feature/login
这里:
-
main是主分支 -
feature/login是你的功能分支 -
D和E是你在功能分支上的提交
这样做的好处是:
你的开发不会影响主分支。
别人也可以继续基于主分支开发。
功能完成后,再通过评审和合并进入主分支。
2. 为什么不能直接在 main/master 上开发
主分支通常代表项目的稳定版本。
常见主分支名称有:
main
master
develop
release
如果你直接在主分支开发,容易带来几个问题:
-
写到一半的代码可能影响别人
-
临时代码可能混进主线
-
功能没有完成就被别人拉走
-
多人同时修改时更容易混乱
-
Gerrit 或 CI 评审流程不好管理
真实公司中常见规则是:
不要直接在 main/master 上开发。
每个任务创建自己的功能分支。
开发完成后提交到 Gerrit 或发起代码评审。
评审通过后再合入目标分支。
3. 查看当前分支
查看本地所有分支:
git branch
你可能看到:
* main
其中 * 表示你当前所在的分支。
如果看到:
feature/login
* main
意思是:
当前在 main 分支。
本地还有一个 feature/login 分支。
也可以用:
git status
它通常会显示:
On branch main
表示你当前在 main 分支。
4. 创建并切换分支
创建新分支并立即切换过去:
git switch -c feature/login
这条命令可以拆成两层意思:
git switch 切换分支
-c create,创建新分支
feature/login 新分支名称
执行后再查看:
git branch
你会看到:
* feature/login
main
表示你现在已经在 feature/login 分支。
老版本 Git 也可以使用:
git checkout -b feature/login
现在更推荐新命令:
git switch -c feature/login
因为 switch 的语义更清楚:它就是用来切换分支的。
5. 分支命名习惯
分支名要让别人一眼看懂你在做什么。
常见命名方式:
feature/login
feature/user-profile
bugfix/login-crash
hotfix/payment-error
release/v1.2.0
常见前缀:
| 前缀 | 含义 |
|---|---|
feature/ |
新功能 |
bugfix/ |
普通问题修复 |
hotfix/ |
紧急线上修复 |
release/ |
发布准备 |
test/ |
临时测试 |
示例:
git switch -c feature/student-management
表示:
创建一个用于开发学生管理功能的分支。
6. 在分支上开发
假设你已经在功能分支:
git switch -c feature/login
然后修改文件:
echo "login feature" > login.txt
查看状态:
git status
提交:
git add login.txt
git commit -m "添加登录功能文件"
现在这个提交只属于 feature/login 分支。
查看历史:
git log --oneline
如果想看更清楚的分支图:
git log --oneline --graph --all
这个命令非常有用。
它可以用图形方式显示分支关系。
7. 切换回 main 分支
切换回主分支:
git switch main
如果你的主分支叫 master:
git switch master
切换后再查看文件,你会发现:
在 feature/login 分支创建的文件,可能在 main 分支上看不到。
这是正常的。
因为不同分支代表不同代码状态。
你可以理解为:
切换分支,就是切换整个项目目录到另一个版本状态。
8. 切换分支前要注意工作区是否干净
切换分支前,最好先执行:
git status
如果看到:
nothing to commit, working tree clean
表示工作区干净,可以安全切换。
如果有未提交修改,例如:
Changes not staged for commit
这时切换分支可能会失败,或者把未提交修改带到另一个分支。
所以建议养成习惯:
切换分支前先看 git status。
如果修改已经完成,可以提交:
git add .
git commit -m "完成某个修改"
如果修改暂时不想提交,后面会学习:
git stash
stash 可以临时保存工作区修改。
9. 合并分支:git merge
当功能分支开发完成后,可以把它合并回目标分支。
假设当前分支结构是:
A --- B --- C main
\
D --- E feature/login
现在要把 feature/login 合并到 main。
第一步,切换到目标分支:
git switch main
第二步,执行合并:
git merge feature/login
合并后可能变成:
A --- B --- C --- F main
\ /
D -- E feature/login
其中 F 是一个合并提交。
有时候也可能是 fast-forward 合并:
A --- B --- C --- D --- E main
这取决于 main 分支在你开发期间有没有新的提交。
10. Fast-forward 合并
Fast-forward 可以理解为:
主分支没有新的变化,只需要把 main 指针往前移动。
例如:
A --- B --- C main
\
D --- E feature/login
如果 main 在 C 之后没有新提交,执行:
git switch main
git merge feature/login
结果可能是:
A --- B --- C --- D --- E main, feature/login
这种合并不会产生额外的 merge commit。
11. 普通 merge commit
如果你开发功能时,main 分支也被别人更新了:
A --- B --- C --- X --- Y main
\
D --- E feature/login
这时合并:
git switch main
git merge feature/login
可能产生:
A --- B --- C --- X --- Y --- M main
\ /
D --- E ---- feature/login
其中 M 是 merge commit。
它的作用是:
把 main 上的新变化和 feature/login 上的新变化合在一起。
12. 合并冲突是什么
合并时最常见的问题是冲突。
冲突通常发生在:
两个分支修改了同一个文件的同一处内容。
Git 不知道应该保留哪一个。
例如 main 分支把一行改成:
hello main
而 feature/login 分支把同一行改成:
hello feature
Git 无法自动判断哪个正确,就会产生冲突。
冲突文件里通常会出现:
<<<<<<< HEAD
hello main
=======
hello feature
>>>>>>> feature/login
含义是:
-
HEAD表示当前分支的内容 -
=======上面是当前分支版本 -
=======下面是被合并分支版本 -
>>>>>>> feature/login表示来自feature/login的内容
冲突解决会在下一课详细讲。
本节先记住:
冲突不是错误,而是 Git 需要你人工判断最终代码应该是什么。
13. 删除已经完成的本地分支
功能分支合并完成后,可以删除本地分支:
git branch -d feature/login
-d 表示安全删除。
如果分支还没有被合并,Git 通常会阻止删除,避免你丢失提交。
如果强制删除:
git branch -D feature/login
-D 是强制删除。
新手阶段不建议随便使用 -D。
14. Gerrit 工作流中的分支
在 Gerrit 中,你通常还是会在本地创建功能分支:
git switch -c feature/login
开发完成后提交:
git add .
git commit -m "实现用户登录功能"
然后推送到 Gerrit:
git push origin HEAD:refs/for/master
这里要注意:
feature/login 是你的本地开发分支。
refs/for/master 表示你申请合入 Gerrit 远端的 master 分支。
如果目标分支是 develop:
git push origin HEAD:refs/for/develop
也就是说:
本地分支叫什么,不一定等于目标分支叫什么。
本地可以叫:
feature/login
但你可以申请合入:
master
develop
release/v1.0
15. Gerrit 和 GitHub/GitLab 的区别
GitHub/GitLab 常见方式:
git push origin feature/login
然后创建 Pull Request 或 Merge Request。
流程是:
本地分支 -> 远程功能分支 -> PR/MR -> 合并
Gerrit 常见方式:
git push origin HEAD:refs/for/master
流程是:
本地提交 -> Gerrit Change -> Review -> Submit
所以 Gerrit 更关注:
每一个 commit 或 Change 的评审质量。
而不是只关注某个远程功能分支。
16. 实战练习一:创建分支并提交
创建练习目录:
mkdir git-branch-demo
cd git-branch-demo
git init
创建初始文件:
echo "# Git Branch Demo" > readme.md
git add readme.md
git commit -m "添加项目说明"
查看当前分支:
git branch
创建功能分支:
git switch -c feature/login
创建登录文件:
echo "login page" > login.txt
git add login.txt
git commit -m "添加登录页面文件"
查看历史图:
git log --oneline --graph --all
17. 实战练习二:切换分支
切回主分支:
git switch main
如果你的 Git 默认分支是 master,使用:
git switch master
查看文件:
dir
在 Windows PowerShell 中可以用:
Get-ChildItem
你可能会发现 login.txt 不见了。
这是正常现象。
因为 login.txt 是在 feature/login 分支上创建的,还没有合并到主分支。
再切回功能分支:
git switch feature/login
再次查看文件,login.txt 会回来。
18. 实战练习三:合并分支
切换到主分支:
git switch main
如果主分支叫 master:
git switch master
合并功能分支:
git merge feature/login
查看历史:
git log --oneline --graph --all
查看文件:
dir
这时你应该能看到:
login.txt
因为它已经被合并到主分支。
19. 实战练习四:删除已合并分支
查看分支:
git branch
删除功能分支:
git branch -d feature/login
再次查看:
git branch
你应该只看到主分支。
20. 本节常见错误
错误一:不知道自己在哪个分支
提交前先看:
git status
git branch
不要在不知道当前分支的情况下提交代码。
错误二:直接在主分支开发
更好的习惯是:
git switch -c feature/your-task
先创建任务分支,再开始开发。
错误三:切换分支前不看状态
切换分支前先执行:
git status
如果工作区不干净,先处理修改。
错误四:分支名没有意义
不要这样命名:
test
aaa
new
mybranch
推荐这样命名:
feature/login
bugfix/login-null-error
hotfix/order-submit-crash
错误五:误删未合并分支
优先使用:
git branch -d 分支名
不要随便使用:
git branch -D 分支名
21. 本节必须记住的命令
git branch
git switch 分支名
git switch -c 新分支名
git merge 分支名
git log --oneline --graph --all
git branch -d 分支名
对应含义:
git branch 查看本地分支
git switch 分支名 切换到已有分支
git switch -c 新分支名 创建并切换到新分支
git merge 分支名 把指定分支合并到当前分支
git log --oneline --graph --all 图形化查看提交历史
git branch -d 分支名 删除已合并的本地分支
22. 工程师习惯总结
真正工作中,推荐流程是:
git status
git switch main
git pull
git switch -c feature/my-task
# 修改代码
git status
git diff
git add <文件>
git diff --cached
git commit -m "清楚描述本次修改"
如果使用 Gerrit:
git push origin HEAD:refs/for/master
如果目标分支是 develop:
git push origin HEAD:refs/for/develop
核心思想:
主分支保持稳定。
任务分支独立开发。
提交前检查 diff。
评审通过后再合入目标分支。
23. 本节总结
这一节你学习了 Git 分支的基础能力:
-
分支是一条独立开发线
-
不要直接在主分支上开发
-
使用
git switch -c创建功能分支 -
使用
git switch切换分支 -
使用
git merge合并分支 -
使用
git log --oneline --graph --all查看分支图 -
使用
git branch -d删除已完成分支 -
Gerrit 中本地分支和目标评审分支不是一回事
你现在已经开始接近真实团队开发流程。
下一节建议学习:
Git 冲突解决:为什么会冲突、如何看冲突标记、如何正确解决 merge conflict。