## git merge 將分支合并到你的當前分支
一旦某分支有了獨立內容,你終究會希望將它合并回到你的主分支。 你可以使用?`git merge`?命令將任何分支合并到當前分支中去。 我們那上例中的“removals”分支為例。假設我們創建了一個分支,移除了一些文件,并將它提交到該分支, 其實該分支是與我們的主分支(也就是“master”)獨立開來的。 要想將這些移除操作包含在主分支中,你可以將“removals”分支合并回去。
~~~
$ git branch
* master
removals
$ ls
README hello.rb more.txt test.txt
$ git merge removals
Updating 8bd6d8b..8f7c949
Fast-forward
more.txt | 1 -
test.txt | 1 -
2 files changed, 0 insertions(+), 2 deletions(-)
delete mode 100644 more.txt
delete mode 100644 test.txt
$ ls
README hello.rb
~~~
### 更多復雜合并
當然,合并并不僅僅是簡單的文件添加、移除的操作,Git 也會合并修改 —— 事實上,它很會合并修改。 舉例,我們看看在某分支中編輯某個文件,然后在另一個分支中把它的名字改掉再做些修改, 最后將這倆分支合并起來。你覺得會變成一坨 shi?我們試試看。
~~~
$ git branch
* master
$ cat hello.rb
class HelloWorld
def self.hello
puts "Hello World"
end
end
HelloWorld.hello
~~~
首先,我們創建一個叫做“change_class”的分支,切換過去,從而將重命名類等操作獨立出來。我們將類名從 “HelloWorld” 改為 “HiWorld”。
~~~
$ git checkout -b change_class
M hello.rb
Switched to a new branch 'change_class'
$ vim hello.rb
$ head -1 hello.rb
class HiWorld
$ git commit -am 'changed the class name'
[change_class 3467b0a] changed the class name
1 files changed, 2 insertions(+), 4 deletions(-)
~~~
然后,將重命名類操作提交到 “change_class” 分支中。 現在,假如切換回 “master” 分支我們可以看到類名恢復到了我們切換到 “change_class” 分支之前的樣子。 現在,再做些修改(即代碼中的輸出),同時將文件名從?`hello.rb`?改為?`ruby.rb`。
~~~
$ git checkout master
Switched to branch 'master'
$ git mv hello.rb ruby.rb
$ vim ruby.rb
$ git diff
diff --git a/ruby.rb b/ruby.rb
index 2aabb6e..bf64b17 100644
--- a/ruby.rb
+++ b/ruby.rb
@@ -1,7 +1,7 @@
class HelloWorld
def self.hello
- puts "Hello World"
+ puts "Hello World from Ruby"
end
end
$ git commit -am 'added from ruby'
[master b7ae93b] added from ruby
1 files changed, 1 insertions(+), 1 deletions(-)
rename hello.rb => ruby.rb (65%)
~~~
現在這些改變已經記錄到我的 “master” 分支了。請注意,這里類名還是 “HelloWorld”,而不是 “HiWorld”。 然后我想將類名的改變合并過來,我把 “change_class” 分支合并過來就行了。 但是,我已經將文件名都改掉了,Git 知道該怎么辦么?
~~~
$ git branch
change_class
* master
$ git merge change_class
Renaming hello.rb => ruby.rb
Auto-merging ruby.rb
Merge made by recursive.
ruby.rb | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
$ cat ruby.rb
class HiWorld
def self.hello
puts "Hello World from Ruby"
end
end
HiWorld.hello
~~~
不錯,它就是發現了。請注意,在這部操作,我沒有遇到合并沖突,并且文件已經重命名、類名也換掉了。挺酷。
### 合并沖突
那么,Git 合并很有魔力,我們再也不用處理合并沖突了,對嗎?不太確切。 不同分支中修改了相同區塊的代碼,電腦自己猜不透神馬的情況下,沖突就擺在我們面前了。 我們看看兩個分支中改了同一行代碼的例子。
~~~
$ git branch
* master
$ git checkout -b fix_readme
Switched to a new branch 'fix_readme'
$ vim README
$ git commit -am 'fixed readme title'
[fix_readme 3ac015d] fixed readme title
1 files changed, 1 insertions(+), 1 deletions(-)
~~~
我們在某分支中修改了 README 文件中的一行,并提交了。我們再在 “master” 分支中對同個文件的同一行內容作不同的修改。
~~~
$ git checkout master
Switched to branch 'master'
$ vim README
$ git commit -am 'fixed readme title differently'
[master 3cbb6aa] fixed readme title differently
1 files changed, 1 insertions(+), 1 deletions(-)
~~~
有意思的來了 —— 我們將前一個分支合并到 “master” 分支,一個合并沖突就出現了。
~~~
$ git merge fix_readme
Auto-merging README
CONFLICT (content): Merge conflict in README
Automatic merge failed; fix conflicts and then commit the result.
$ cat README
<<<<<<< HEAD
Many Hello World Examples
=======
Hello World Lang Examples
>>>>>>> fix_readme
This project has examples of hello world in
nearly every programming language.
~~~
你可以看到,Git 在產生合并沖突的地方插入了標準的與 Subversion 很像的合并沖突標記。 輪到我們去解決這些沖突了。在這里我們就手動把它解決。如果你要 Git 打開一個圖形化的合并工具, 可以看看?[git 合并工具](http://git-scm.com/docs/git-mergetool)?(比如 kdiff3、emerge、p4merge 等)。
~~~
$ vim README here I'm fixing the conflict
$ git diff
diff --cc README
index 9103e27,69cad1a..0000000
--- a/README
+++ b/README
@@@ -1,4 -1,4 +1,4 @@@
- Many Hello World Examples
-Hello World Lang Examples
++Many Hello World Lang Examples
This project has examples of hello world in
~~~
在 Git 中,處理合并沖突的時候有個很酷的提示。 如果你執行?`git diff`,就像我演示的這樣,它會告訴你沖突的兩方,和你是如何解決的。 現在是時候把它標記為已解決了。在 Git 中,我們可以用?`git add`?—— 要告訴 Git 文件沖突已經解決,你必須把它寫入緩存區。
~~~
$ git status -s
UU README
$ git add README
$ git status -s
M README
$ git commit
[master 8d585ea] Merge branch 'fix_readme'
~~~
現在我們成功解決了合并中的沖突,并提交了結果
> **簡而言之**?使用?`git merge`?將另一個分支并入當前的分支中去。 Git 會自動以最佳方式將兩個不同快照中獨特的工作合并到一個新快照中去。