git 的 merge、rebase、squash、revert、cherry-pick 分别在什么场景使用?
先理解原理和示例,再练习完整口述与追问。
回答要点
merge 保留分支历史并生成合并提交;rebase 把提交重放到新基底上,历史线性,但会改写提交,不能对已共享的分支随意使用;squash 把多个提交压成一个;revert 生成反向提交来撤销,适合已推送的公共分支;reset 移动分支指针,适合本地;cherry-pick 把指定提交应用到当前分支,常用于热修复。bisect 二分定位引入问题的提交。
原理拆解
git fetch 只更新远程跟踪分支,git pull 等于 fetch 加 merge(或配置为 rebase)。在自己的功能分支上 git rebase origin/main 可以在合并前同步主干、解决冲突;改写已推送的提交后需要 git push --force-with-lease,它会在远端被别人更新时拒绝覆盖,比 --force 安全。
git reset --soft/--mixed/--hard 分别保留暂存区与工作区、只保留工作区、全部丢弃。误操作后,git reflog 记录了 HEAD 的移动历史,可以找回“丢失”的提交。git stash 临时保存未提交的修改,git bisect start、bad、good 逐步缩小范围,可配合 git bisect run npm test 自动执行。
示例与推演
线上紧急修复:从 release 分支建 hotfix,修复后合并到 release 发布,再 git cherry-pick <修复提交> 到 main,避免把 main 上未发布的功能带上线。仓库迁移到新平台并保留全部分支与标签:git clone --mirror 旧地址,进入目录后 git push --mirror 新地址。
易错点
在公共分支上 rebase 后强推,会让同事的本地历史与远端分叉;revert 一个合并提交需要用 -m 1 指定保留的父提交,之后想重新合入该分支,需要先 revert 掉这次 revert。
参考回答可直接练习口述
merge 保留真实分支历史,rebase 把提交重放到最新主干上,历史更线性,但会改写提交,所以只在自己的分支上用,强推用 force-with-lease。合并前可以 squash 把零碎提交压成一个。已经推送到公共分支的问题用 revert 生成反向提交,本地还没推送的可以 reset。热修复用 cherry-pick 把单个提交带到其他分支,排查回归用 bisect 二分。误操作可以通过 reflog 找回。