变基提交
git rebase 是 Git 中一个用于 重写提交历史 的命令,通过将一系列提交移动到新的基准点(base)上,创建更线形的历史记录。
一、核心作用
1. 变基( Rebasing )
将当前分支的提交“重新播放”到目标分支的最新提交之后,形成线形历史。
git checkout feature
# 将 feature 分支的提交移动到 main 分支顶端
git rebase main
2. 历史线性化
消除不必要的合并提交,使提交历史呈直线型(更易追踪变更)。
二、与其他命令对比
git merge | git rebase | git cherry-pick | git merge --squash | |
|---|---|---|---|---|
| 历史记录形态 | 非线性 | 线形(重写历史) | 混合(新增提交) | 新增单一提交 |
| 是否保留提交历史 | ✅ 是 | ❌ | ❌ | ❌ |
| 是否产生合并提交 | ✅ 是 | ❌ | ❌ | ❌ 需手动提交 |
| 提交哈希变化 | ❌ 不变 | ✅ 全部改变 | ✅ 新提交 | ✅ 新提交 |
| 冲突处理次数 | 1 次(整体合并) | 没提交一次 | 按提交次数 | 1 次 |
| 是否适合公共分支 | ✅ | ❌ (危险) | ⚠️ 谨慎 | ✅ |
| 主要用途 | 安全合并 | 整理本地历史 | 精确移植提交 | 整理合成功能 |
| 选择 | 团队协作、主干开发 | 本地开发,准备 PR 前整理 | 紧急修复、跨分支布丁 | 功能分支太乱,只想保留结果 |
| 典型场景 | 合并公共分支 (如 main/dev) | 本地分支整理/同步上游变更 | 跨分支移植特定提交 | 将分支提交压缩为单个合并 |
1. 与 git merge 对比
| 维度 | git merge | git rebase |
|---|---|---|
| 历史记录 | 保留分支拓扑结构(有合并节点) | 创建线形历史(无合并节点) |
| 提交完整性 | 保留原始提交 | 重写提交(哈希值会改变) |
| 安全性 | 安全(不破坏历史) | 危险(改写共享历史) |
| 冲突解决 | 单次解决所有冲突 | 需为每一个提交解决冲突 |
| 命令示例 | git merge feature | git rebase main |
黄金法则
本地分支使用 rebase ,公共分支用 merge
2. 与 git cherry-pick 对比
| 维度 | git cherry-pick | git rebase |
|---|---|---|
| 粒度 | 单个或离散提交 | 连续提交次序 |
| 目的 | 选择性移植提交 | 整体迁移分支历史 |
| 地生机制 | 本质是复制提交 | 本质是 重放提交 |
| 命令示例 | git cherry-pick A..B | git rebase -i HEAD~3 (交互式) |
3. 与 git merge --squash 对比
| 维度 | git merge --squash | git rebase |
|---|---|---|
| 历史记录 | 压缩为一个提交 | 保留所有提交(但重写历史) |
| 历史影响 | 丢弃原分支提交细节 | 保留提交细节(但哈希值会变) |
| 后续操作 | 需手动提交 | 自动完成提交 |
| 命令示例 | git merge --squash feature | git rebase -i (可压缩提交) |
信息
两者都用于整个分支变更,但 --squash 是“破坏性”合并(丢失原提交信息)
4. 使用场景
- 同步主分支更新到本地开发分支 :
git rebase main - 合并功能分支到主分支 :
git merge - 将其他分支的单个修复应用到当前分支:
git cherry-pick - 将分支所有修改作为单个提交合并 :
git merge --squash - 清理本地提交 :
git rebase -i
三、图解
main: A → B → C
feature: A → B → D → E
| 命令 | 结果 |
|---|---|
git merge feature | A ➞ B ➞ C ➞ ( D ➞ E 合并提交) |
git rebase main | A ➞ B ➞ C ➞ D' ➞ E' (D/E 重写后接在 C 后) |
git cherry-pick D E | A ➞ B ➞ C ➞ D ➞ E (新增独立提交) |
git merge --squash | A ➞ B ➞ C ➞ F (F = D + E 的压缩提交) |
- 使用 merge
- 使用 rebase
- 使用 cherry-pick
- 使用 merge --squash