分支管理
掌握 Git 分支的创建、切换、合并与变基,理解快进合并与三方合并的区别,学会用 rebase 重写历史。
分支基础
使用 git branch <name> 创建新分支,git switch <name> 或 git checkout <name> 切换分支,git branch -d <name> 删除已合并的分支。
$ git branch feature # 创建分支 $ git switch feature # 切换到 feature 分支 $ git branch -d feature # 删除已合并的分支
git branch 查看本地分支,git branch -a 查看所有分支(包括远程)。远程分支用红色标注,以 remotes/ 开头。当前所在分支前会有 * 标记。
$ git branch * main feature $ git branch -a * main feature remotes/origin/main remotes/origin/feature
git checkout -b 和 git switch -c 有什么区别?两者功能完全相同,都是创建并切换到新分支。git switch 是 Git 2.23(2019年)引入的新命令,专门用于分支切换,语义更清晰。推荐使用 git switch -c。
$ git checkout -b feature # 旧写法,依然有效 $ git switch -c feature # 新写法,推荐使用
合并与变基
git merge 是做什么的?git merge <branch> 将指定分支的更改合并到当前分支。合并时会自动寻找两个分支的共同祖先,进行三方比较后生成合并结果。
$ git switch main $ git merge feature # 将 feature 合并到 main
当被合并分支是当前分支的直接后续(即当前分支没有新提交)时,Git 只需将指针向前移动,不需要产生 merge commit。这种合并方式历史看起来是线性的。
# main 没有新提交,feature 是 main 的直接后续 $ git merge feature Updating a1b2c3d..e4f5g6h Fast-forward feature.js | 5 +++++ 1 file changed, 5 insertions(+)
当两个分支都有新的提交时,Git 会找到它们的共同祖先(base),然后对三个版本(base、当前分支、被合并分支)进行三方比较,自动合并并产生一个 merge commit。如果同一位置都有修改,则会产生冲突,需要手动解决。
--no-ff 参数有什么用?git merge --no-ff <branch> 禁止快进合并,即使可以快进也强制产生 merge commit。这样可以保留分支的存在痕迹,让历史更清晰地展示"这里有一个分支被合并了"。
$ git merge --no-ff feature Merge made by the 'ort' strategy. feature.js | 5 +++++ 1 file changed, 5 insertions(+)
git rebase 和 git merge 有什么区别?git merge 保留分支的分叉历史,产生 merge commit。git rebase 则将当前分支的提交"重新播放"到目标分支之上,使历史变成线性的。rebase 的历史更干净,但它改写了提交历史(commit hash 会变)。
# merge: 保留分叉 $ git merge feature # rebase: 线性历史 $ git rebase main
公共分支(如 main、develop)用 merge,因为公共分支的历史不应被改写。私有/特性分支用 rebase,可以保持提交历史整洁线性。简单来说:在你推送到远程之前,可以用 rebase 整理提交;一旦推送了,就用 merge。
永远不要对已经推送到远程的公共分支执行 rebase!因为 rebase 会重写 commit hash,其他协作者的历史将与你冲突,导致混乱。如果公共分支需要整合,请使用 merge。
git commit --amend 是做什么的?修改最近一次提交的消息或内容。如果你忘记添加某个文件或想修改 commit message,可以用 --amend。它会将暂存区的内容合并到上一次提交中,并允许你修改提交消息。
$ git add forgotten-file.js $ git commit --amend -m "更准确的提交消息"
git rebase -i 交互式变基有什么用?交互式变基允许你整理提交历史,常用操作包括:
pick— 保留该提交squash— 将该提交合并到前一个提交reword— 修改提交消息reorder— 调整提交顺序(通过移动行)drop— 丢弃该提交(删除该行)
$ git rebase -i HEAD~3 # 整理最近 3 个提交
git cherry-pick 是做什么的?git cherry-pick <commit-hash> 将指定的提交应用到当前分支。适用于只想要某个分支上的特定修改,而不需要合并整个分支的场景。
$ git cherry-pick a1b2c3d # 将 a1b2c3d 这个提交应用到当前分支
git reset --soft、--mixed、--hard 有什么区别?三者都移动分支指针,但影响范围不同:
# --soft: 只移动指针,工作区和暂存区不变 $ git reset --soft HEAD~1 # --mixed: 移动指针 + 取消暂存(默认模式) $ git reset --mixed HEAD~1 # 等同于 git reset HEAD~1 # --hard: 移动指针 + 丢弃所有修改(危险!) $ git reset --hard HEAD~1
git reset --hard 会永久丢弃所有未提交的修改和工作区文件变更,且无法通过常规方式恢复。使用前请确认你真的不需要这些更改。如果只是想撤销提交但保留修改,请使用 --soft 或 --mixed。
