from: http://blog.microsuncn.com/?p=1989
git-rebase命令主要用在从上游分支获取最新commit信息,并有机的将当前分支和上游分支进行合并。下面看个例子。我们假设主分支为master,在开发过程中生成一个新分支topic。master称为topic的上游分支。
例子开始:
[git-tester@microsuncn git-study]$ cd rebase
[git-tester@microsuncn rebase]$ ls
[git-tester@microsuncn rebase]$ vi roc.c
[git-tester@microsuncn rebase]$ cat roc.c
int main()
{
printf(“master:001″);
return 0;
}
[git-tester@microsuncn rebase]$ git init
Initialized empty Git repository in /git-tester/career/programming/git-study/rebase/.git/
[git-tester@microsuncn rebase]$ git add .
[git-tester@microsuncn rebase]$ git commit -m “master:001″
Created initial commit 2d89602: master:001
1 files changed, 5 insertions(+), 0 deletions(-)
create mode 100644 roc.c
[git-tester@microsuncn rebase]$ git log
commit 2d89602d0c9955824df0d2c023e447f5d98d863a
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:26:40 2008 +0800
master:001
[git-tester@microsuncn rebase]$
到此,我们已经在master分支完成了一个commit。
[git-tester@microsuncn rebase]$ vi roc.c
[git-tester@microsuncn rebase]$ git commit -a -m “master:002″
Created commit 41b3d1c: master:002
1 files changed, 1 insertions(+), 0 deletions(-)
[git-tester@microsuncn rebase]$ cat roc.c
int main()
{
printf(“master:001″);
printf(“master:002″);
return 0;
}
[git-tester@microsuncn rebase]$ git log
commit 41b3d1cfaae0184bb8e5f27a165d51cc23867413
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:28:01 2008 +0800
master:002
commit 2d89602d0c9955824df0d2c023e447f5d98d863a
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:26:40 2008 +0800
master:001
[git-tester@microsuncn rebase]$
到此为止,我们已经在master分支完成了两次commit的提交。
现在的分支结构是这样的:
master:001 — master:002 (master)
继续要做的事情就是建立一个新的分支topic。
[git-tester@microsuncn rebase]$ git branch
* master
[git-tester@microsuncn rebase]$ git branch topic
[git-tester@microsuncn rebase]$ git branch
* master
topic
[git-tester@microsuncn rebase]$ git checkout topic
Switched to branch “topic”
[git-tester@microsuncn rebase]$ git branch
master
* topic
[git-tester@microsuncn rebase]$
已经成功建立了topic分支,并且已经转移到了topic分支。
接下来,topic上面的开发情况如下:
[git-tester@microsuncn rebase]$ vi roc.c
[git-tester@microsuncn rebase]$ git commit -a -m “topic:001″
Created commit d599b54: topic:001
1 files changed, 1 insertions(+), 0 deletions(-)
[git-tester@microsuncn rebase]$ vi roc.c
[git-tester@microsuncn rebase]$ git commit -a -m “topic:002″
Created commit 3f4b17f: topic:002
1 files changed, 1 insertions(+), 0 deletions(-)
[git-tester@microsuncn rebase]$ cat roc.c
int main()
{
printf(“topic :002″);
printf(“topic :001″);
printf(“master:001″);
printf(“master:002″);
return 0;
}
[git-tester@microsuncn rebase]$ git log
commit 3f4b17fe3b5d277771770c0515e75f04e783ad14
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:49:24 2008 +0800
topic:002
commit d599b54336ad96b8e09ef92e371a09a25e6d0c11
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:48:58 2008 +0800
topic:001
commit 41b3d1cfaae0184bb8e5f27a165d51cc23867413
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:28:01 2008 +0800
master:002
commit 2d89602d0c9955824df0d2c023e447f5d98d863a
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:26:40 2008 +0800
master:001
[git-tester@microsuncn rebase]$
可知,自从建立并切换到topic分支后,topic又进行了两次commit提交,每次分别加入了一行代码。
此时,分支结构应该是这样的:
topic:001 — topic:002 (topic)
/
master:001 — master:002 (master)
这个图已经很清晰了,可以看出分支的走向。
接下来,master分支也有自己的进度,如下:
[git-tester@microsuncn rebase]$ git checkout master
Switched to branch “master”
[git-tester@microsuncn rebase]$ git branch
* master
topic
[git-tester@microsuncn rebase]$ vi roc.c
[git-tester@microsuncn rebase]$ git commit -a -m “master:003″
Created commit 91a7ffc: master:003
1 files changed, 1 insertions(+), 0 deletions(-)
[git-tester@microsuncn rebase]$ vi roc.c
[git-tester@microsuncn rebase]$ git commit -a -m “master:004″
Created commit b81fbc3: master:004
1 files changed, 1 insertions(+), 0 deletions(-)
[git-tester@microsuncn rebase]$ cat roc.c
int main()
{
printf(“master:001″);
printf(“master:002″);
printf(“master:003″);
printf(“master:004″);
return 0;
}
[git-tester@microsuncn rebase]$ git log
commit b81fbc3be5c7bd1fdef72820c29e2c67590f4b03
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:55:23 2008 +0800
master:004
commit 91a7ffc73e6320a86b10849061efd672f47fd5bd
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:55:06 2008 +0800
master:003
commit 41b3d1cfaae0184bb8e5f27a165d51cc23867413
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:28:01 2008 +0800
master:002
commit 2d89602d0c9955824df0d2c023e447f5d98d863a
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:26:40 2008 +0800
master:001
[git-tester@microsuncn rebase]$
可以看到,master分支也完成了两次commit提交,每次分别添加了一行代码。
到此时,分支结构为:
topic:001 — topic:002 (topic)
/
master:001 — master:002 — master:003 — master:004 (master)
到这个时候,实验样本已经基本搭建完毕,git-rebase就要派上用场了!
假设topic和master是一个项目的两个分支,master当然是主分支,而topic是旁路分支。在软件开发的大部分情况中,旁路分支是要遵从主分支的。所以说,现在topic分支想将master分支开发的最新代码导入到topic分支中,而且要求此动作不影响master主分支的开发,也就是说要暗中完成。git-rebase上场了:
[git-tester@microsuncn rebase]$ git checkout topic
Switched to branch “topic”
[git-tester@microsuncn rebase]$ git branch
master
* topic
[git-tester@microsuncn rebase]$ git rebase master
First, rewinding head to replay your work on top of it…
Applying topic:001
error: patch failed: roc.c:1
error: roc.c: patch does not apply
Using index info to reconstruct a base tree…
Falling back to patching base and 3-way merge…
Auto-merged roc.c
Applying topic:002
[git-tester@microsuncn rebase]$
使用了git rebase master来完成需求。如果心细的话,你会看到它输出了一些error,意思是说“补丁失败”,这个error没有关系,不影响git-rebase的正常工作的。
来看看git-rebase的细节:
[git-tester@microsuncn rebase]$ git branch
master
* topic
[git-tester@microsuncn rebase]$ git log
commit 05de9849078541c86cf5182cd8c15fa22bd00f77
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:49:24 2008 +0800
topic:002
commit 7e5a744ef9e0740b4a091e9c8baa859b14800b0b
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:48:58 2008 +0800
topic:001
commit b81fbc3be5c7bd1fdef72820c29e2c67590f4b03
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:55:23 2008 +0800
master:004
commit 91a7ffc73e6320a86b10849061efd672f47fd5bd
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:55:06 2008 +0800
master:003
commit 41b3d1cfaae0184bb8e5f27a165d51cc23867413
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:28:01 2008 +0800
master:002
commit 2d89602d0c9955824df0d2c023e447f5d98d863a
Author: git-tester <microsuncn@gmail.com>
Date: Mon Nov 17 15:26:40 2008 +0800
master:001
[git-tester@microsuncn rebase]$ cat roc.c
int main()
{
printf(“topic :002″);
printf(“topic :001″);
printf(“master:001″);
printf(“master:002″);
printf(“master:003″);
printf(“master:004″);
return 0;
}
[git-tester@microsuncn rebase]$
看到了吧!master分支刚才开发的master:003和master:004也已经悄悄的进入了topic分支的日志里了。而在roc.c文件中也已经有了相应的开发代码。
看一下分支结构图:
topic:001 --- topic:002 (topic) / master:001 --- master:002 --- master:003 --- master:004 (master)
对比一下。这是执行git-rebase之前的分支结构图:
topic:001 — topic:002 (topic)
/
master:001 — master:002 — master:003 — master:004 (master)
git-rebase还有很多其他用法,我们会在以后的章节中继续讲解。:) 今天这个例子非常重要,后续有关git-rebase的例子都会已此例子为基础。