1. 程式人生 > >git-rebase 超級詳細講解,我竟然看完了

git-rebase 超級詳細講解,我竟然看完了

命令格式

我們先來看看git-rebase的命令格式:

git rebase [-i | --interactive] [options] [--onto <newbase>]  <upstream> [<branch>] git rebase [-i | --interactive] [options] –onto <newbase>  –root [<branch>] git rebase –continue | –skip | –abort

從命令格式,可以看到git-rebae命令至少需要一個引數,那就是<upstream>,這個引數可以是一個分支名稱,也可以是一次有效的commit。

一個小地方

在你決定學習這個命令,首先有一個小地方你應該注意,那就是如果git-rebase後面加上了引數<branch>,那麼 git-rebase會在任何其他動作之前先執行git checkout <branch>,如果沒有加引數<branch>,那麼git-rebase會針對當前分支來做動作。

命令用處

git-rebase命令主要用在從上游分支獲取最新commit資訊,並有機的將當前分支和上游分支進行合併。

這是隻言片語的介紹,可能讀者並不能瞭解它的用途和好處。

還是要用例子說話。我們假設主分支為master,在開發過程中生成一個新分支topic。master稱為topic的上游分支。

例子開始:

[[email protected] git-study]$ cd rebase [[email protected] rebase]$ ls [[email protected] rebase]$ vi roc.c [[email protected] rebase]$ cat roc.c int main() { printf(“master:001″); return 0; } [[email protected] rebase]$ git init Initialized empty Git repository in /rocrocket/career/programming/git-study/rebase/.git/ [

[email protected] rebase]$ git add . [[email protected] rebase]$ git commit -m “master:001″ Created initial commit 2d89602: master:001 1 files changed, 5 insertions(+), 0 deletions(-) create mode 100644 roc.c [[email protected] rebase]$ git log commit 2d89602d0c9955824df0d2c023e447f5d98d863a Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:26:40 2008 +0800

master:001 [[email protected] rebase]$

到此,我們已經在master分支完成了一個commit。

[[email protected] rebase]$ vi roc.c [[email protected] rebase]$ git commit -a -m “master:002″ Created commit 41b3d1c: master:002 1 files changed, 1 insertions(+), 0 deletions(-) [[email protected] rebase]$ cat roc.c int main() { printf(“master:001″); printf(“master:002″); return 0; } [[email protected] rebase]$ git log commit 41b3d1cfaae0184bb8e5f27a165d51cc23867413 Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:28:01 2008 +0800

master:002

commit 2d89602d0c9955824df0d2c023e447f5d98d863a Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:26:40 2008 +0800

master:001 [[email protected] rebase]$

到此為止,我們已經在master分支完成了兩次commit的提交。

現在的分支結構是這樣的,請讀者記清楚:

master:001 — master:002   (master)

好,我們繼續要做的事情就是建立一個新的分支topic。

[[email protected] rebase]$ git branch * master [[email protected] rebase]$ git branch topic [[email protected] rebase]$ git branch * master topic [[email protected] rebase]$ git checkout topic Switched to branch “topic” [[email protected] rebase]$ git branch master * topic [[email protected] rebase]$

好了,我們已經成功建立了topic分支,並且已經轉移到了topic分支。

接下來,topic上面的開發情況如下:

[[email protected] rebase]$ vi roc.c [[email protected] rebase]$ git commit -a -m “topic:001″ Created commit d599b54: topic:001 1 files changed, 1 insertions(+), 0 deletions(-) [[email protected] rebase]$ vi roc.c [[email protected] rebase]$ git commit -a -m “topic:002″ Created commit 3f4b17f: topic:002 1 files changed, 1 insertions(+), 0 deletions(-) [[email protected] rebase]$ cat roc.c int main() { printf(“topic :002″); printf(“topic :001″); printf(“master:001″); printf(“master:002″); return 0; } [[email protected] rebase]$ git log commit 3f4b17fe3b5d277771770c0515e75f04e783ad14 Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:49:24 2008 +0800

topic:002

commit d599b54336ad96b8e09ef92e371a09a25e6d0c11 Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:48:58 2008 +0800

topic:001

commit 41b3d1cfaae0184bb8e5f27a165d51cc23867413 Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:28:01 2008 +0800

master:002

commit 2d89602d0c9955824df0d2c023e447f5d98d863a Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:26:40 2008 +0800

master:001 [[email protected] rebase]$

可知,自從建立並切換到topic分支後,topic又進行了兩次commit提交,每次分別加入了一行程式碼。

此時,分支結構應該是這樣的:

    topic:001 --- topic:002 (topic) / master:001 --- master:002   (master)

這個圖已經很清晰了,可以看出分支的走向。

接下來,master分支也有自己的進度,如下:

[[email protected] rebase]$ git checkout master Switched to branch “master” [[email protected] rebase]$ git branch * master topic [[email protected] rebase]$ vi roc.c [[email protected] rebase]$ git commit -a -m “master:003″ Created commit 91a7ffc: master:003 1 files changed, 1 insertions(+), 0 deletions(-) [[email protected] rebase]$ vi roc.c [[email protected] rebase]$ git commit -a -m “master:004″ Created commit b81fbc3: master:004 1 files changed, 1 insertions(+), 0 deletions(-) [[email protected] rebase]$ cat roc.c int main() { printf(“master:001″); printf(“master:002″); printf(“master:003″); printf(“master:004″); return 0; } [[email protected] rebase]$ git log commit b81fbc3be5c7bd1fdef72820c29e2c67590f4b03 Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:55:23 2008 +0800

master:004

commit 91a7ffc73e6320a86b10849061efd672f47fd5bd Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:55:06 2008 +0800

master:003

commit 41b3d1cfaae0184bb8e5f27a165d51cc23867413 Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:28:01 2008 +0800

master:002

commit 2d89602d0c9955824df0d2c023e447f5d98d863a Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:26:40 2008 +0800

master:001 [[email protected] 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上場了: [[email protected] rebase]$ git checkout topic Switched to branch “topic” [[email protected] rebase]$ git branch master * topic [[email protected] 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 [[email protected] rebase]$

我們使用了git rebase master來完成我們的需求。如果你心細的話,你會看到它輸出了一些error,意思是說“補丁失敗”,這個error沒有關係,不影響git-rebase的正常工作的。

讓我們來看看git-rebase的魔力吧:

[[email protected] rebase]$ git branch master * topic [[email protected] rebase]$ git log commit 05de9849078541c86cf5182cd8c15fa22bd00f77 Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:49:24 2008 +0800

topic:002

commit 7e5a744ef9e0740b4a091e9c8baa859b14800b0b Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:48:58 2008 +0800

topic:001

commit b81fbc3be5c7bd1fdef72820c29e2c67590f4b03 Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:55:23 2008 +0800

master:004

commit 91a7ffc73e6320a86b10849061efd672f47fd5bd Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:55:06 2008 +0800

master:003

commit 41b3d1cfaae0184bb8e5f27a165d51cc23867413 Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:28:01 2008 +0800

master:002

commit 2d89602d0c9955824df0d2c023e447f5d98d863a Author: rocrocket <[email protected]> Date:   Mon Nov 17 15:26:40 2008 +0800

master:001

[[email protected] 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; } [[email protected] rebase]$

看到了吧!master分支剛才開發的master:003和master:004也已經悄悄的進入了topic分支的日誌裡了。而在roc.c檔案中也已經有了相應的開發程式碼。

這下,你是不是有一種豁然開朗的感覺?呵呵 來,看一下分支結構圖:

master:001 --- master:002 --- master:003 --- master:004---topic:001 --- topic:002 (topic)

master:001 --- master:002 --- master:003 --- master:004(master)

這就是git-rebase的魔力!看出神奇之處了麼? 如果忘了,就對比一下。這是執行git-rebase之前的分支結構圖:

      topic:001 --- topic:002 (topic) / master:001 --- master:002 --- master:003 --- master:004 (master)