1. 程式人生 > >【git】git分支的合並

【git】git分支的合並

stat diff 出錯 傳輸 .html read 簡單 流程 保存

原文:

http://gitbook.liuhui998.com/3_3.html http://gitbook.liuhui998.com/5_3.html 一、如何分支的合並 在git中,可以使用git merge 和git rebase兩個命令來進行分支的合並。 git merge 和git rebase在大體上都差不多,下文主要以git merge來例來講解分支的合並流程。 如果你想了解分支合並的更多內容,請閱讀《git merge簡介》,《git rebase簡介(基本篇)》和《git rebase簡介(高級篇)》。 git merge命令示例: $ git merge branchname 這個命令把分支"branchname"合並到了當前分支裏面。 如有沖突(沖突--同一個文件在遠程分支和本地分支裏按不同的方式被修改了);那麽命令的執行輸出就像下面一樣 $ git merge next 100% (4/4) done Auto-merged file.txt CONFLICT (content): Merge conflict in file.txt Automatic merge failed; fix conflicts and then commit the result. 在有問題的文件上會有沖突標記,在你手動解決完沖突後就可以把此文件添 加到索引(index)中去,用git commit命令來提交,就像平時修改了一個文件 一樣。 如果你用gitk來查看commit的結果,你會看到它有兩個父分支:一個指向當前的分支,另外一個指向剛才合並進來的分支。 二、解決合並中的沖突
如果執行自動合並沒有成功的話,git會在索引和工作樹裏設置一個特殊的狀態, 提示你如何解決合並中出現的沖突。 有沖突(conflicts)的文件會保存在索引中,除非你解決了問題了並且更新了索引,否則執行 git commit都會失敗: $ git commit file.txt: needs merge 如果執行 git status 會顯示這些文件沒有合並(unmerged),這些有沖突的文件裏面會添加像下面的沖突標識符: <<<<<<< HEAD:file.txt Hello world ======= Goodbye >>>>>>> 77976da35a11db4580b80ae27e8d65caf5208086:file.txt 你所需要的做是就是編輯解決沖突,(接著把沖突標識符刪掉),再執行下面的命令: $ git add file.txt $ git commit 註意:提交註釋裏已經有一些關於合並的信息了,通常是用這些默認信息,但是你可以添加一些你想要的註釋。 上面這些就是你要做一個簡單合並所要知道的,但是git提供更多的一些信息來 幫助解決沖突。 三、撒銷一個合並
如果你覺得你合並後的狀態是一團亂麻,想把當前的修改都放棄,你可以用下面的命令回到合並之前的狀態: $ git reset --hard HEAD 或者你已經把合並後的代碼提交,但還是想把它們撒銷: $ git reset --hard ORIG_HEAD 但是剛才這條命令在某些情況會很危險,如果你把一個已經被另一個分支合並的分支給刪了,那麽 以後在合並相關的分支時會出錯。 關於撤銷的更多內容請參考《git reset簡介》 四、快速向前合並 還有一種需要特殊對待的情況,在前面沒有提到。通常,一個合並會產生一個合並提交(commit), 把兩個父分支裏的每一行內容都合並進來。 但是,如果當前的分支和另一個分支沒有內容上的差異,就是說當前分支的每一個提交(commit)都已經存在另一個分支裏了,git 就會執行一個“快速向前"(fast forward)操作;git 不創建任何新的提交(commit),只是將當前分支指向合並進來的分支。 五、在合並過程中得到解決沖突的協助
git會把所有可以自動合並的修改加入到索引中去, 所以git diff只會顯示有沖突的部分. 它使用了一種不常見的語法: $ git diff diff --cc file.txt index 802992c,2b60207..0000000 --- a/file.txt +++ b/file.txt @@@ -1,1 -1,1 +1,5 @@@ ++<<<<<<< HEAD:file.txt +Hello world ++======= + Goodbye ++>>>>>>> 77976da35a11db4580b80ae27e8d65caf5208086:file.txt 回憶一下, 在我們解決沖突之後, 得到的提交會有兩個而不是一個父提交: 一個父提交是當前分支提交前的HEAD,; 另外一個父提交是被合並分支的HEAD, 被暫時存在MERGE_HEAD. 在合並過程中, 索引中保存著每個文件的三個版本. 三個"文件暫存(file stage)"中的每一個都代表了文件的不同版本: $ git show :1:file.txt # 兩個分支共同祖先中的版本. $ git show :2:file.txt # HEAD中的版本. $ git show :3:file.txt # MERGE_HEAD中的版本. 當你使用git diff去顯示沖突時, 它在工作樹(work tree), 暫存2(stage 2)和暫存3(stage 3)之間執行三路diff操作, 只顯示那些兩方都有的塊(換句話說, 當一個塊的合並結果只從暫存2中得到時, 是不會被顯示出來的; 對於暫存3來說也是一樣). 上面的diff結果顯示了file.txt在工作樹, 暫存2和暫存3中的差異. git不在每行前面加上單個‘+‘或者‘-‘, 相反地, 它使用兩欄去顯示差異: 第一欄用於顯示第一個父提交與工作目錄文件拷貝的差異, 第二欄用於顯示第二個父提交與工作文件拷貝的差異. (參見git diff-files中的"COMBINED DIFF FORMAT"取得此格式詳細信息.) 在用直觀的方法解決沖突之後(但是在更新索引之前), diff輸出會變成下面的樣子: $ git diff diff --cc file.txt index 802992c,2b60207..0000000 --- a/file.txt +++ b/file.txt @@@ -1,1 -1,1 +1,1 @@@ - Hello world -Goodbye ++Goodbye world 上面的輸出顯示了解決沖突後的版本刪除了第一個父版本提供的"Hello world"和第二個父版本提供的"Goodbye", 然後加入了兩個父版本中都沒有的"Goodbye world". 一些特別diff選項允許你對比工作目錄和三個暫存中任何一個的差異: $ git diff -1 file.txt # 與暫存1進行比較 $ git diff --base file.txt # 與上相同 $ git diff -2 file.txt # 與暫存2進行比較 $ git diff --ours file.txt # 與上相同 $ git diff -3 file.txt # 與暫存3進行比較 $ git diff --theirs file.txt # 與上相同. 還有,git log和gitk命令也為合並操作提供了特別的協助: $ git log --merge $ gitk --merge 這會顯示所有那些只在HEAD或者只在MERGE_HEAD中存在的提交, 還有那些更新(touch)了未合並文件的提交. 你也可以使用git mergetool, 它允許你使用外部工具如emacs或kdiff3去合並文件. 每次你解決沖突之後, 應該更新索引: $ git add file.txt 完成索引更新之後, git-diff(缺省地)不再顯示那個文件的差異, 所以那個文件的不同暫存版本會被"折疊"起來. 六、多路合並 你可以一次合並多個頭, 只需簡單地把它們作為git merge的參數列出. 例如, $ git merge scott/master rick/master tom/master 相當於: $ git merge scott/master $ git merge rick/master $ git merge tom/master 七、子樹 有時會出現你想在自己項目中引入其他獨立開發項目的內容的情況. 在沒有路徑沖突的前提下, 你只需要簡單地從其他項目拉取內容即可. 如果有沖突的文件, 那麽就會出現問題. 可能的例子包括Makefile和其他一些標準文件名. 你可以選擇合並這些沖突的文件, 但是更多的情況是你不願意把它們合並. 一個更好解決方案是把外部項目作為一個子目錄進行合並. 這種情況不被遞歸合並策略所支持, 所以簡單的拉取是無用的. 在這種情況下, 你需要的是子樹合並策略. 這下面例子中, 我們設定你有一個倉庫位於/path/to/B (如果你需要的話, 也可以是一個URL). 你想要合並那個倉庫的master分支到你當前倉庫的dir-B子目錄下. 下面就是你所需要的命令序列: $ git remote add -f Bproject /path/to/B (1) $ git merge -s ours --no-commit Bproject/master (2) $ git read-tree --prefix=dir-B/ -u Bproject/master (3) $ git commit -m "Merge B project as our subdirectory" (4) $ git pull -s subtree Bproject master (5) 子樹合並的好處就是它並沒有給你倉庫的用戶增加太多的管理負擔. 它兼容於較老(版本號小於1.5.2)的客戶端, 克隆完成之後馬上可以得到代碼. 然而, 如果你使用子模塊(submodule), 你可以選擇不傳輸這些子模塊對象. 這可能在子樹合並過程中造成問題. 譯者註: submodule是Git的另一種將別的倉庫嵌入到本地倉庫方法. 另外, 若你需要修改內嵌外部項目的內容, 使用子模塊方式可以更容易地提交你的修改.

【git】git分支的合並