外观
05 · 分支切换与合并
分支是贴在 commit 上的指针。开分支很便宜;真正贵的是合并时的冲突和「合完发现合错了」。
git branch
作用: 列出、创建、重命名、删除本地分支;设置上游。默认不切换过去。
改动范围: 只动分支指针(删除/重命名)。不改工作区,除非你删的是当前分支(Git 会拒绝)。
典型场景: 看自己有哪些分支、开一个功能分支名、删掉已合并的旧分支、看每个分支跟踪谁。
常用写法:
bash
git branch # 本地分支
git branch -a # 含远程跟踪分支
git branch -vv # 跟踪关系、ahead/behind
git branch feature/login # 基于当前 HEAD 建分支,人还留在原地
git branch feature/login main # 基于 main 建
git branch -m feature/logn feature/login # 重命名
git branch -d feature/login # 安全删除:未合并会拒绝
git branch -D feature/login # 危险:未合并也删
git branch -u origin/feature/login # 给当前分支设上游删除远程分支不是 git branch,是:
bash
git push origin --delete feature/login不要这样用: branch -D 删还没 merge、也没 push 的分支。指针没了,提交变成 dangling——短期内 reflog 还在,但自己增加了急救步骤。
做错了怎么办: 删错本地分支:
bash
git reflog
git switch -c feature/login a1b2c3d见 急救手册 · 删错分支。
git switch
作用: 切换当前分支(移动 HEAD 和工作区,使文件变成该分支尖端的样子)。
改动范围: HEAD + 工作区 + 暂存区(会尽量带着你未提交的改动走;带不过去会拒绝切换)。
典型场景: 去做另一个需求;从 main 拉出新分支并立刻开工;参观某次历史(游离)。
常用写法:
bash
git switch main
git switch -c feature/login # 创建并切过去
git switch -c feature/login main # 基于 main 创建并切换
git switch - # 回到上一个分支
git switch --detach a1b2c3d # 游离,只看不改远程已有、本地还没有:
bash
git fetch origin
git switch feature/login # 现代 Git 会自动跟踪 origin/feature/login不要这样用: 工作区很脏时强行切到差异很大的分支。Git 会拒绝并提示先 commit / stash。不要为了切过去就 reset --hard。
做错了怎么办: 切错分支,git switch - 回去。带着未提交改动切走了:改动还在工作区,再切回来即可。若 Git 拒绝切换,按提示 stash 或 commit,见 08 章。
git checkout(旧而全能)
作用: 同时承担「切分支」和「恢复文件」两件事。正因为全能,才容易在恢复文件时写成切分支。
改动范围: 取决于参数。
bash
git checkout main # 等同 switch
git checkout -b feature/login # 等同 switch -c
git checkout -- src/login.ts # 等同 restore src/login.ts
git checkout a1b2c3d -- src/login.ts # 取出历史版本的该文件(工作区+暂存区)新仓库建议用 switch / restore。读老脚本时按上表翻译。
git merge
作用: 把另一个分支的提交合进当前分支。能快进就快进;不能就做一次合并提交(两个父提交)。
改动范围: 本地历史 + 工作区(有冲突时)。不自动推远程。
典型场景:
main合入已审查完的feature/login。- 功能分支定期把
main合进来,减少最后一次冲突。 - 需要保留「这是一次功能合并」的节点时用
--no-ff。
常用写法:
bash
git switch main
git merge feature/login
git merge --no-ff feature/login # 即使能快进也建合并提交
git merge --squash feature/login # 把对方所有改动捏成暂存区,自己再 commit(历史变一条)
git merge --abort # 冲突或后悔:回到 merge 前三种结果:
| 结果 | 含义 |
|---|---|
| Fast-forward | 当前分支尖端是对方的祖先,指针直接前移,无新提交 |
| Merge commit | 两边都有独有提交,生成一个双亲提交 |
| Conflict | 同一处被两边改过,停下来等人解决,见 09 章 |
不要这样用:
- 在错误的当前分支上 merge(先
status/branch --show-current)。 - 冲突解决到一半执行
reset --hard想「清一下」,把已解决和未解决一起丢掉。应使用--abort。 - 把已推送的公共历史用 merge 搞乱后,试图
reset+ force push 抹掉。
做错了怎么办:
- 还没 push:
git merge --abort(若还在合并中)或git reset --hard ORIG_HEAD(合并已完成但后悔;先确认工作区没有其它宝贝)。 - 已经 push:
git revert -m 1 <merge_sha>撤销合并。见 急救手册。
git mergetool
作用: 用配置好的外部工具打开冲突文件。
bash
git mergetool不配工具就不必用,手工编辑冲突标记同样有效,见 09 章。
推荐的功能分支节奏
bash
git switch main
git pull --ff-only
git switch -c feature/login
# ... 多次 commit ...
git fetch origin
git merge origin/main # 或 rebase,见第 06 章
git push -u origin HEAD
# PR 合并后
git switch main
git pull --ff-only
git branch -d feature/login
git push origin --delete feature/login # 若托管平台没自动删--ff-only 让 main 拒绝意外的本地分叉,避免在默认分支上长出「只有你自己知道的合并提交」。
上一章:04 · 历史 · 下一章:06 · 变基、拣选与改写历史