1. 程式人生 > >Git:真實merge

Git:真實merge

原帖收藏於IT老兵驛站

Git:真實merge。

前言

這裡準備碎片化地去解讀和理解Git的一些功能。關於git-merge的總結一直沒有做,但是幾乎每天都會遇到git-merge,而且會遇到很多隨著merge而產生的問題,所以只好碎片化地去做一做整理。

正文

git-merge有兩種merge方式,ff方式和true merge方式,關於ff的方式,另外一篇文章有講過,這裡不再贅述,這裡整理一下true merge,真實merge。

介紹

先摘錄一段:

TRUE MERGE
Except in a fast-forward merge (see above), the branches to be merged must be tied together by a merge commit that has both of them as its parents.

A merged version reconciling the changes from all branches to be merged is committed, and your HEAD, index, and working tree are updated to it. It is possible to have modifications in the working tree as long as they do not overlap; the update will preserve them.

When it is not obvious how to reconcile the changes, the following happens:

The HEAD pointer stays the same.

The MERGE_HEAD ref is set to point to the other branch head.

Paths that merged cleanly are updated both in the index file and in your working tree.

For conflicting paths, the index file records up to three versions: stage 1 stores the version from the common ancestor, stage 2 from HEAD, and stage 3 from MERGE_HEAD (you can inspect the stages with git ls-files -u). The working tree files contain the result of the “merge” program; i.e. 3-way merge results with familiar conflict markers <<< === >>>.

No other changes are made. In particular, the local modifications you had before you started merge will stay the same and the index entries for them stay as they were, i.e. matching HEAD.

If you tried a merge which resulted in complex conflicts and want to start over, you can recover with git merge --abort.

這裡是三個版本的關係,公共祖先的版本、HEAD(本地倉庫的版本)、MERGE_HEAD(另外一個分支想要merge過來的版本),所以叫3-way merge,三路合併。

關於HEAD、index、worktree、local repository、remote repository的關係,請參考這裡,這個挺重要,隨後要整理一下。

合併策略:

MERGE STRATEGIES

The merge mechanism (git merge and git pull commands) allows the backend merge strategies to be chosen with -s option. Some strategies can also take their own options, which can be passed by giving -X arguments to git merge and/or git pull.

resolve
This can only resolve two heads (i.e. the current branch and another branch you pulled from) using a 3-way merge algorithm. It tries to carefully detect criss-cross merge ambiguities and is considered generally safe and fast.

recursive
This can only resolve two heads using a 3-way merge algorithm. When there is more than one common ancestor that can be used for 3-way merge, it creates a merged tree of the common ancestors and uses that as the reference tree for the 3-way merge. This has been reported to result in fewer merge conflicts without causing mismerges by tests done on actual merge commits taken from Linux 2.6 kernel development history. Additionally this can detect and handle merges involving renames, but currently cannot make use of detected copies. This is the default merge strategy when pulling or merging one branch.

The recursive strategy can take the following options:

ours
This option forces conflicting hunks to be auto-resolved cleanly by favoring our version. Changes from the other tree that do not conflict with our side are reflected to the merge result. For a binary file, the entire contents are taken from our side.

This should not be confused with the ours merge strategy, which does not even look at what the other tree contains at all. It discards everything the other tree did, declaring our history contains all that happened in it.

theirs
This is the opposite of ours; note that, unlike ours, there is no theirs merge strategy to confuse this merge option with.

使用-X<option>引數,可以指定合併策略,上面摘錄了兩種,一種是resolve,一種是recursive,第一種策略看上去似乎是可以自動解決衝突,第二種是Git預設的merge策略,會產生一些少量的衝突,而不會進行錯誤的合併,它還有幾個選項,就是合併時,只選擇本地的(ours),或者只選擇別人的(theirs)。

參考

https://git-scm.com/docs/git-merge
https://stackoverflow.com/questions/3689838/whats-the-difference-between-head-working-tree-and-index-in-git