git merge簡介
git merge的基本用法為把一個分支或或某個commit的修改合並到現在的分支上。
我們可以運行git merge -h和git merge --help查看其命令,後者會直接轉到一個網頁(git的幫助文檔),更詳細。
usage: git merge [options] [<commit>...]
or: git merge [options] <msg> HEAD <commit>
or: git merge --abort
-n do not show a diffstat at the end of the merge
--summary (synonym to --stat)
--log[=<n>] add (at most <n>) entries from shortlog to merge commi t message
--commit perform a commit if the merge succeeds (default)
-e, --edit edit message before committing
--ff allow fast-forward (default)
--ff-only abort if fast-forward is not possible
-s, --strategy <strategy>
merge strategy to use
-X, --strategy-option <option=value>
option for selected merge strategy
-m, --message <message>
merge commit message (for a non-fast-forward merge)
-v, --verbose be more verbose
-q, --quiet be more quiet
--abort abort the current in-progress merge
--progress force progress reporting
-S, --gpg-sign[=<key id>]
GPG sign commit
--overwrite-ignore update ignored files (default)
git merge [options] <msg> HEAD <commit> 這裏的 HEAD 其實就是分支名,用於說明把 HEAD 分支合並到當前分支。 --squash選項的含義是:本地文件內容與不使用該選項的合並結果相同,但是不保留待合並分支上的歷史信息,也不提交、不移動HEAD,因此需要一條額外的commit命令。其效果相當於將another分支上的多個commit合並成一個,放在當前分支上,原來的commit歷史則沒有拿過來。 判斷是否使用--squash選項最根本的標準是,待合並分支上的歷史是否有意義。 如果在開發分支上提交非常隨意,甚至寫成微博體,那麽一定要使用--squash選項。版本歷史記錄的應該是代碼的發展,而不是開發者在編碼時的活動。 只有在開發分支上每個commit都有其獨自存在的意義,並且能夠編譯通過的情況下(能夠通過測試就更完美了),才應該選擇缺省的合並方式來保留commit歷史。 --no-ff Create a merge commit even when the merge resolves as a fast-forward. This is the default behaviour when merging an annotated (and possibly signed) tag. 我們在將Develop分支發布到Master分支時,可能采用如下的命令: # 切換到Master分支 git checkout master # 對Develop分支進行合並 git merge --no-ff develop 這裏稍微解釋一下,上一條命令的--no-ff參數是什麽意思。 這個命令要通過git merge --help查看其命令,後者會直接轉到一個網頁,才能看到其詳細說明 默認情況下,Git執行"快進式合並"(fast-farward merge),會直接將Master分支指向Develop分支。 示圖1-1 示圖1-2 命令: git checkout master git merge robin_local 使用--no-ff參數後,會執行正常合並,在Master分支上生成一個新節點。為了保證版本演進的清晰,我們希望采用這種做法。關於合並的更多解釋,請參考Benjamin Sandofsky的《Understanding the Git Workflow》。 示圖2-1 示圖2-2 命令: git checkout master git merge robin_local 圖3 以下是一篇來自於哈佛大學關於git merge的文章
英文地址:http://www.eecs.harvard.edu/~cduan/technical/git/git-3.shtml
Merging
After you have finished implementing a new feature on a branch, you want to bring that new feature into the main branch, so that everyone can use it. You can do so with the git merge or git pull command.
The syntax for the commands is as follows:
git merge [head]git pull . [head]
They are identical in result. (Though the merge form seems simpler for now, the reason for the pull form will become apparent when discussing multiple developers.)
These commands perform the following operations. Let the current head be called current, and the head to be merged calledmerge.
- Identify the common ancestor of current and merge. Call it ancestor-commit.
- Deal with the easy cases. If the ancestor-commit equals merge, then do nothing. If ancestor-commit equals current, then do a fast forward merge.
- Otherwise, determine the changes between the ancestor-commit and merge.
- Attempt to merge those changes into the files in current.
- If there were no conflicts, create a new commit, with two parents, current and merge. Set current (and HEAD) to point to this new commit, and update the working files for the project accordingly.
- If there was a conflict, insert appropriate conflict markers and inform the user. No commit is created.
Important note: Git can get very confused if there are uncommitted changes in the files when you ask it to perform a merge. So make sure to commit whatever changes you have made so far before you merge.
So, to complete the above example, say you check out the master head again and finish writing up the new data for your paper. Now you want to bring in those changes you made to the headers.
The repository looks like this:
+---------- (D)
/ |
(A) -- (B) -- (C) -------------- (E)
| |
fix-headers master
|
HEAD
where (E) is the commit reflecting the completed version with the new data.
You would run:
git merge fix-headers
If there are no conflicts, the resulting respository looks like this:
+---------- (D) ---------------+
/ | \
(A) -- (B) -- (C) -------------- (E) -- (F)
| |
fix-headers master
|
HEAD
The merge commit is (F), having parents (D) and (E). Because (B) is the common ancestor between (D) and (E), the files in (F) should contain the changes between (B) and (D), namely the heading fixes, incorporated into the files from (E).
Note on terminology: When I say “merge head A into head B,” I mean that head B is the current head, and you are drawing changes from head A into it. Head B gets updated; nothing is done to head A. (If you replace the word “merge” with the word “pull,” it may make more sense.)
Resolving Conflicts
A conflict arises if the commit to be merged in has a change in one place, and the current commit has a change in the same place. Git has no way of telling which change should take precedence.
To resolve the commit, edit the files to fix the conflicting changes. Then run git add to add the resolved files, and rungit commit to commit the repaired merge. Git remembers that you were in the middle of a merge, so it sets the parents of the commit correctly.
如果沒有沖突的話,merge完成。有沖突的話,git會提示那個文件中有沖突,比如有如下沖突:
<<<<<<< HEAD:test.c
printf (“test1″);
=======
printf (“test2″);
>>>>>>> issueFix:test.c
可以看到 ======= 隔開的上半部分,是 HEAD(即 master 分支,在運行 merge 命令時檢出的分支)中的內容,下半部分是在 issueFix 分支中的內容。解決沖突的辦法無非是二者選其一或者由你親自整合到一起。比如你可以通過把這段內容替換為下面這樣來解決:
printf (“test2″);
這個解決方案各采納了兩個分支中的一部分內容,而且刪除了 <<<<<<<,=======,和>>>>>>> 這些行。
在解決了所有文件裏的所有沖突後,運行git add 將把它們標記為已解決(resolved)。
然後使用git commit命令進行提交,merge就算完成了
Fast Forward Merges
A fast forward merge is a simple optimization for merging. Say your repository looks like this:
+-- (D) ------ (E)
/ |
(A) -- (B) -- (C) |
| |
current to-merge
|
HEAD
and you run git merge to-merge. In this case, all Git needs to do is set current to point to (E). Since (C) is the common ancestor, there are no changes to actually “merge.”
Hence, the resulting merged repository looks like:
+-- (D) -- (E)
/ |
(A) -- (B) -- (C) |
|
to-merge, current
|
HEAD
That is, to-merge and current both point to commit (E), and HEAD still points to current.
Note an important difference: no new commit object is created for the merge. Git only shifts the head pointers around.
Common Merge Use Patterns
There are two common reasons to merge two branches. The first, as explained above, is to draw the changes from a new feature branch into the main branch.
The second use pattern is to draw the main branch into a feature branch you are developing. This keeps the feature branch up to date with the latest bug fixes and new features added to the main branch. Doing this regularly reduces the risk of creating a conflict when you merge your feature into the main branch.
One disadvantage of doing the above is that your feature branch will end up with a lot of merge commits. An alternative that solves this problem is rebasing, although that comes with problems of its own.
git merge簡介