使用Git中的Merge與Rebase與開源項目同步代碼
基于開源項目的開發有兩種主要工作模式。模式1是在從開源項目中拉出一個分支,在這個分支中開發新feature,完成后合并到upstream中。適用于本身是開源項目的developer。模式2是從開源項目中拉出分支后獨立發展,但定期從upstream拉更新(如重要版本升級時)。無論是哪種,都會面臨本地分支與upstream同步代碼的問題。為此,git主要提供了兩種方式:一種是merge, 一種是rebase。下面通過例子簡單過一下它們的基本流程。
假設開源項目的git地址為git://xxx.org/xxx/project。早先從它上面拉出代碼,作為git repository放在在本地的代碼管理服務器上(比如gerrit服務器)。而在本地的開發機上有本地服務器上該項目git的clone。這樣,在本地開發機上執行git remote -v結果類似于:
local ssh://jzj@gerrit3.company.com:xxxxx/xxx/project (fetch)
local ssh://jzj@gerrit3.company.com:xxxxx/xxx/project (push)
首先將開源項目git加入remote源列表,名稱暫定為upstream。
$ git remote add upstream git://xxx.org/xxx/project
再將新加源的信息同步下來:
$ git fetch
然后git remote -v結果就變成:
upstream git://xxx.org/xxx/project (fetch)
upstream git://xxx.org/xxx/project (push)
local ssh://jzj@gerrit3.company.com:xxxxx/xxx/project (fetch)
local ssh://jzj@gerrit3.company.com:xxxxx/xxx/project (push)
現在當前git已經與兩個源關聯上了。
接下來從upstream源新建分支,稱為upstream,它與開源項目git中的代碼一致:
$ git checkout remotes/upstream/master -b upstream
假設其中git log為:
Commit 2 from branch upstream 2015/1/3
Commit 1 from branch upstream 2015/1/1
再從local源拉出分支,稱為topic,它包含本地改動(比如新加feature):
$ git checkout remotes/local/master -b topic
當然,如果將來要提交到到gerrit服務器上,這兒用repo start topic .。假設其中log為:
Commit 1 from branch topic 2015/1/2
Merge方式是把branch A在branch B上沒有的commit合并成一個commit,然后打在branch B上。如果要讓topic分支同步upstream中的改動,執行下面命令:
$ git checkout topic
$ git merge upstream
如果想讓 upstream同步topic改動,把上面命令中分支名的位置換下就行。如果有沖突的話會讓你解決(通過git diff查看沖突),解決完了以后git add + git commit(或git commit -a)。完成后在topic分支的git log里看到的log有類似下面的結果:
Merge branch 'upstream' into topic
Commit 2 from branch upstream 2015/1/3
Commit 1 from branch topic 2015/1/2
Commit 1 from branch upstream 2015/1/1
兩個branch中的commit以時間順序排列,最頂上這個commit代表了這次merge的bundle commit。把它git reset掉的話所有原upstream上同步的改動都會消失。
Rebase方式是把branch A在branch B上沒有的commit挨個在branch B上再重新打一遍。通過git rebase的文檔,可以看到如果是git rebase upstream topic的話相當于git checkout topic + git rebase upstream。即把topic分支上的commit以upstream的HEAD為base重新打一遍,重復的commit會自動忽略。因此,如果是前面提到的工作模式1的話就用git rebase topic upstream,工作模式2的話就用git rebase upstream topic。一般為了避免whitespace帶來的錯誤,會加上--ignore-whitespace參數:
$ git rebase upstream topic --ignore-whitespace
更細粒度的rebase控制請參見-i參數。
在rebase過程中可能出現沖突,出現沖突時先用git diff看沖突情況。比如是a.c的話,解決沖突后執行:
$ git add a.c
然后執行下面命令繼續歡快地rebase:
$ git rebase --continue
完成后topic分支的git log里是類似于這樣的:
Commit 1 from branch topic 2015/1/2
Commit 2 from branch upstream 2015/1/3
Commit 1 from branch upstream 2015/1/1
可以看到,這里不是按時間順序的。topic分支的commit在上面,而upstream的commit在下面。如果是git rebase topic upstream的話順序就是相反的。最后,如果還需要讓upstream分支也同步topic分支的代碼。可以到upstream分支做一次fast- forward merge:
</div>
$ git checkout upstream
$ git merge topic
妥妥的。
同步完了之后,該git push就git push,該repo upload就repo upload,將同步的代碼更新到本地的代碼管理服務器上。
總結一下,從工作方式來說,merge與rebase最大的差別就是前者是把所有要打的commit作為一整個commit打到目標分支上,后者是一個個重新打(但注意打上去后<SHA1>不同了,也就是說,雖然內容相同,但此commit已經不是原來那個了)。從結果來看,merge后log中 commit是按時間順序的,最近的一個commit記錄了這次merge操作。rebase后log中不是按時間順序的,而是一個分支的commit在另一個分支的commit之后。總得來說,rebase比merge更靈活,更強大。但它的缺點是會改寫歷史。因此,不要對public的分支做 rebase,否則你會冒著被同事砍死的風險(因為他可能基于改寫前的歷史做了改動)。基本原則是,當從遠端同步代碼到本地時,用rebase。當本地完成feature開發,同步回遠端時用merge。
</div>
來自:http://blog.csdn.net/jinzhuojun/article/details/43988599
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!