git rebase
与 git merge
解决了相同的问题。都是将一个分支的提交合并到另一分支上,那它们有哪些不同喃?
git merge
master
分支合入到 feature
分支
git checkout feature
git merge master
// 或者
git merge master feature
git merge
的优势是它保留了分支的结构与历史提交目录,但同时这也导致了提交历史会被大量的 merge
污染
git rebase
rebase
命令是一个经常听到,但是大多数人掌握又不太好的一个命令。rebase
合并往往又被称为 「变基」
它是将把所有的提交压缩成一个 patch
。然后把 patch
添加到目标分支里。rebase
与 merge
不同的是,rebase
通过为原始分支中的每个提交创建全新的 commits
来重写项目历史记录
以 master
分支为基,对 feautre
分支进行变基:
git checout feature
git rebase master
git rebase
的优势是可以获得更清晰的项目历史。首先,它消除了 git merge
所需的不必要的合并提交;其次,正如你在上图中所看到的,rebase
会产生完美线性的项目历史记录,你可以在 feature
分支上没有任何分叉的情况下一直追寻到项目的初始提交。
但是, rebase
会丢失合并提交的上下文, 使我们无法看到真实的更改是何时合并到目标分支上的
交互式 Rebase
这个命令比 git rebase
更为强大,它将会在 commits
移动到新分支时更改这些 commits
,通常,这用于在合并 feature
分支到 master
之前清理其杂乱的历史记录。
git checkout feature
git rebase -i master
这将打开一个文本编辑器,列出即将移动的所有提交:
pick 6633b5a Message for commit #1
pick 3a03f0d Message for commit #2
pick 657897b Message for commit #3
它清晰地展示了分支在 rebase
后的样子。通过重新调整,提交历史可以变成任何你想要的样子。
消除这种无意义的提交使你的功能历史更容易理解。这是 git merge
根本无法做到的事情。
至于 commits
条目前的 pick
、fixup
、squash
等命令,在 git 目录执行 git rebase -i
即可查看到,大家按需重排或合并提交即可,注释说明非常清晰,在此不做过多说明
git merge vs git rebase
git merge:
- 记录下合并动作,很多时候这种合并动作是垃圾信息
- 不会修改原
commit ID
- 冲突只解决一次
- 分支看着不大整洁,但是能看出合并的先后顺序
- 记录了真实的
commit
情况,包括每个分支的详情
git rebase:
- 改变当前分支
branch out
的位置 - 得到更简洁的项目历史
- 每个
commit
都需要解决冲突 - 修改所有
commit ID
我的建议
随着团队增长,通过 merge
策略很难管理和追踪到每个提交。为了提交历史更清晰、更易于理解,使用 rebase
是一个明智、高效的选择。
下面是针对不同环境的建议,可以最大限度地发挥 rebase
的优势:
**本地开发:**如果你没有和别人协同工作,你应该使用 rebasing
而不是 merging
,这样历史记录会很清晰。如果你已经从仓库拉取了你的个人 fork
,并且不准备和别的开发者一起工作,在分支 push
前 rebase
也是可以的。
你的代码准备好了被 review
:你创建了 pull request
。别人正在 review
你的代码,可能把它拉到了本地 review
。如果这样,你最好别 rebase
你的代码。你应该创建一个 “rework”
提交来更新你的 feature
分支。它会让 pull request
的可塑性更强,也能避免历史突然丢失。
review
已经完成并且已经准备好了合并到目标分支。恭喜!你就要删除你的 feature
分支了。由于别的开发者不需要拉取、合并这些更改,这是你清理记录的好机会。你可以改写记录,折叠原始提交、“pr rework”
提交和 "merge"
提交,使之成为一整个清晰的提交。作为可选,你还可以给这些提交创建一个明确的 merge
,这样做实际上很有用。它会记录 feature
并入 master
的时间。