目录
简单变基操作
复现
先复现一个变基操作的现场,具体做法如下:
(1)创建一个testrebase目录,在该目录下执行git init命令,初始化一个本地仓库,如图:
(2)在testrebase目录下创建新文件readme,并执行git add和git commit提交到本地仓库默认master分支下,如图:
此时分支示意图如下:
(3)创建分支experiment,并切换到该分支,添加新文件experiment,执行git add和git commit提交到该分支下,如图:
此时分支示意图如下:
(4)再回到master分支,创建新文件master,同样执行git add和git commit提交到该分支下,如图:
此时分支示意图如下:
变基
现在想将experiment分支的提交通过变基操作合并到master分支上,具体做法如下:
(1)在experiment分支下,执行git rebase master命令,如图:
命令很简单,但对Gi来说,它首先找到两个分支experiment(当前分支)和master(要并入的分支)的共同祖先,也就是分支示意图中的root-commit,然后拿到当前所在分支experiment,每次提交引入的更改(differ),也就是7b872ea相对root-commit的更改,把这些更改保存为临时文件。
(2)切换到master分支下,执行合并操作,如图:
对Git来说,它会将之前保存更改的临时文件全部重现到master分支下完成合并。这就完成了变基操作,分支示意图如下:
此时两个分支同时指向最后合并后的commit。当然这里就可以删除experiment分支了。变基不同于普通的合并,普通合并后,分支示意图应该是如下情况:
两个分支指向是不同的。
更复杂的变基
复现
先复现如下的分支变基现场:
然后通过变基操作将client的commit-2和commit-3合并到master中。复现全部命令如下:
$ git init
Initialized empty Git repository in C:/Users/********/Desktop/testrebase/.git/
$ git add root
$ git commit -m "add root"
[master (root-commit) cfd9cc4] add root
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 root
$ git checkout -b server
Switched to a new branch 'server'
$ git add c1
$ git status
On branch server
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: c1
$ git commit -m "add c1"
[server 8c68059] add c1
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 c1
$ git checkout -b client
Switched to a new branch 'client'
$ git add c2
$ git commit -m "add c2"
[client aa0646f] add c2
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 c2
$ git add c3
$ git commit -m "add c3"
[client 1485d1b] add c3
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 c3
$ git checkout master
Switched to branch 'master'
$ git add c4
$ git commit -m "add c4"
[master 441d858] add c4
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 c4
$ git add c5
$ git commit -m "add c5"
[master db76cb5] add c5
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 c5
$ git checkout server
Switched to branch 'server'
$ git add c
c6 c7
$ git add c*
$ git commit -m "add c6 and c7"
[server f045a09] add c6 and c7
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 c6
create mode 100644 c7
各分支下的工作区如图:
master:
server:
client:
变基
随便在哪个分支下,执行git rebase --onto master server client命令,然后切换到master分支,执行合并就完成了将c2和c3文件合并到master分支下了,如图:
注意到server和client分支的共同祖先中的c1文件并没有合并到master分支中,这太神奇了。对于上面的
git rebase --onto master server client
命令,Git首先切换到client分支,并找到client和server分支的共同祖先commit-1,然后从共同祖先以来client分支上做的更改在master分支上重现,也就是commit-2和commit-3。此时如果还想把server分支的所有更改并入master,直接执行如下命令即可:
注意,命令行切换到了server分支。此时sever分支工作区如图:
master分支工作区这时候还没有变化,需要切换到master分支,并执行如下合并操作:
到这里三个分支都会指向最终的合并结果,现在就可以删除server和client分支了,如图:
变基操作建议
对本地尚未推送到远程服务器的更改进行变基操作,可以简化提交历史,但绝不能对已推送到远程服务器的公开提交进行变基操作,这会遭到同事的唾弃和鄙视。