2013-07-15 84 views
14

當我從團隊中的其他人修改某個文件時從GitHub中獲取時,Git命令顯示Git無法修復未解決的衝突。我打開Perforce或Visual Studio 2012來解決衝突,圖形工具顯示我沒有衝突,並且可以快速執行合併。Git如何決定衝突?

Git是否有獨立於您設置的mergetool/difftool的內部衝突檢測/合併工具?

還是它使用您配置的工具來自動合併和檢測無法解決的衝突?

我的場景很奇怪,Git顯示它不能automerge,但圖形工具沒有顯示任何問題。

+0

你的問題並不是獨一無二的,我也經常親自體驗過這一點,但從未花時間去研究爲什麼會發生這種情況。 – 2013-07-16 05:12:57

+1

我從來沒有遇到過這個問題 - 如果你能發佈這種情況發生在一個公共的git主機上,這會有很大的幫助,例如。 Github上。 – Chronial

+0

在[VonC's answer](http://stackoverflow.com/questions/4920885/what-c​​onstitutes-a-merge-conflict-in-git/4921705#4921705)to [什麼構成Git中的合併衝突?](http他解釋說,Git使用「一種經典的3路合併算法」。請參閱答案瞭解更多詳情。 – 2013-07-27 16:48:47

回答

7

Git有一個獨立於difftool的內部合併系統。反正你可以使用-s選項指定merge strategy,從手動:

-s <strategy> 
--strategy=<strategy> 

使用給定的合併策略;可以多次提供,以按照他們應該嘗試的順序指定它們。如果沒有-s 選項,則使用內置策略列表(git 合併單個頭時合併遞歸,否則爲git merge-octopus )。

合併大量樹木時,策略從簡單的FastForward轉換爲Octopus。 請檢查此asnwer以瞭解不同的merge策略如何工作。

無論如何,你的情況很奇怪。也許你的IDE使用的是不同的合併策略,所以當它打開時,合併是正確的。

2

是的,許多IDE和合並工具都會在git上自動執行衝突解決方案。

如在git help merge-file中看到的,git的文本文件的庫存衝突解決算法非常簡單:如果它們改變相鄰行,則diff chunk衝突。如果git無法以這種方式自動解決衝突,那麼它會將文本衝突標記置於自RCS時代以來已經標準化的格式,並且IDE可以拾取並處理它(即使它不瞭解GIT):

 
<<<<<<<< Version identifier 1 
Foo 
======= 
Bar 
>>>>>>>> Version identifier 2 

我不使用Visual Studio,但快速谷歌告訴我,它有一個automatic conflict resolution功能。 (我使用kdiff3我自己,它有its own自動衝突解決算法)

1

發佈here是我見過的關於git合併策略的最佳答案。是的,你可以選擇你想要哪一個你想要的-s option

但你的問題是爲什麼其他工具如Visual Studio合併時,git不能。 Visual Studio可以有一個相當積極的合併策略 - 「自動合併功能通常不會使用來自舊版本的任何內容,因爲自動合併功能的默認設置支持最新文件」,請參閱here瞭解更多信息。

要了解有關VS 2012附帶的合併工具的更多信息,請參閱this posting,其中Brian Harry將他們認爲是「合併時最小的衝突」視爲主要特徵的方式。

至於Perforce,我懷疑他們有一個類似的合併策略 - g4 p4連接器必須使用perforce合併策略來弄清楚,我相信他們更積極。

「我們的」可能是git中類似的積極合併策略。

但是,它的長短之處在於,每個產品都在使用他們自己的合併策略,其中一些或多或少具有攻擊性。這取決於您的使用情況和需求。

6

作爲Atropo states in his answer

GIT中有一個內部合併系統是獨立的difftool

因此,Git會自行決定更改何時會導致衝突,而不是使用任何外部差異或合併工具(可能使用自己的衝突檢測和解決策略)。

根據VonC's answerWhat constitutes a merge conflict in Git?(重點煤礦):

我不認爲合併算法有什麼特別的使用Git:這是一個典型的3-way merge algorithmnot the Codeville one),可用於with several strategies (默認:遞進,或解析或章魚)。 結果是fairly simply merge processdescribed here
然後將任何可視化需求委託給第三方合併/差異工具。

維基百科的文章中,他鏈接到解釋了3-way merge正是如此(重點煤礦):

的三路合併爲一個文件「A」和文件「B之間的自動差異分析後進行',同時也考慮兩個文件的起源或共同的祖先。這是一種粗略的合併方法,但是真正廣泛適用,因爲它只需要一個共同的祖先來重構要合併的更改。

三向合併使用已更改文件的祖先來標識已在派生版本的一個或兩個中都未更改的內容塊。兩個塊都沒有改變的塊保持不變。僅在一個衍生版中更改的塊使用更改後的版本。 如果兩個衍生產品中的塊都發生了更改,則如果兩側的內容相同,則使用更改的版本,但如果更改不同,則會將其標記爲衝突情況並留給用戶解決

三維合併是通過無處不在的diff3程序實現的,它是允許從基於文件鎖定的修訂控制系統切換到基於合併的修訂控制系統的核心創新。它被Concurrent Versions System(CVS)廣泛使用。

文章還談到Recursive three-way merges,這是我看到的Git用了很多:

廣泛使用的三方基於合併版本控制工具造就了情況下,頭腦簡單的三路合併會導致虛假的衝突,有時會默默地重新恢復已恢復的更改。這種情況的例子包括criss-cross merges和三向重命名衝突。

三路合併的問題出現在兩個派生狀態沒有獨特的最新共同祖先(LCA)的情況下。爲了解決這些問題,遞歸三路合併通過首先合併非獨特的祖先來構建虛擬祖先。該技術由Git版本控制工具使用。

遞歸三路合併只能在工具具有關於要合併的導數的總祖先DAG(有向無環圖)知識的情況下使用。因此,它不能用於衍生工具或合併未完全指定其父項的情況。