我研究了什么是git merge操作以及當它發現無法自動解決的沖突時它會做什么。
如果我可以手動解決沖突,我可以選擇要保存的內容和要更改的內容。
另一方面,我們有快進合并,如果一個分支是另一個的直接祖先,另一方面,不是快進合并而是自動解決。
在這里,我發現很難理解 Git 如何處理這兩種情況:我已經看到它自動選擇要更改的內容,但我怎么知道它是否按照我的意愿做事?
例如,在test我使用file.txt的分支上,而在master分支上我有另一個版本的file.txt。
這兩個分支共享一個共同的祖先。
我執行git checkout master然后我想與test.
為此,我將數字git merge test. 那會發生什么呢?
master有完全不同的內容master包含test在file.txt版本中不存在的文本master文本比里面的file.txt少test
我的問題涉及一個通用案例:我如何在運行之前理解git merge testGit 將如何處理這些合并?
也許這取決于我開始時當前所在的分支git merge?
uj5u.com熱心網友回復:
讓我們看看我是否可以在一個簡短的帖子中涵蓋所有內容:
Git 有多種合并策略。當您跑步時,
git merge您可以選擇一種策略,例如git merge -s resolve other或git merge -s octopus br1 br2 br3。標準策略是ours,recursive,resolve,subtree,octopus, 現在是新的ort.幾乎所有的實際作業都是由該策略完成的。因此,在決定合并的操作方式之前,您必須知道將使用哪種策略。
大多數合并的默認策略是
recursive并且可能很快會變成ort. 這兩個主要用于相同的作業,除了ort應該更快并且更好地處理一些棘手的情況。(注意:這是目標狀態,而不是當前狀態,這就是為什么它還不是默認狀態。)但是,如果您將多個“頭”(確實git merge是提交)賦予,則默認值為octopus。
除了ours策略(不需要合并基礎,我認為不需要計算一個)和octopus策略(使用替代的合并基礎計算),這些合并必須找到(單一的)合并基礎提交。為了找到那個提交,Git 使用了擴展到 DAGs的最低公共祖先演算法。您可以手動運行它:
git merge-base --all HEAD otherbranch
例如。但作為一個“全”選項的存在意味著,和維基百科的鏈接明確,從該演算法的輸出可能會超過一個承諾。
如果只有一個合并基地,一切都很好。如果沒有,每個策略都必須對此有所作為。(章魚策略會做任何事情,因為它首先沒有使用這個演算法;我從來沒有深入研究過這個問題的底部,因為我很警惕Balrogs的錯誤。)該resolve策略使用了一個簡單但可怕的方法答案:它在(明顯)隨機選擇一個并使用它。recursive然而,默認策略只是簡單地合并合并基(不使用章魚演算法,而是使用ort試圖改進的略有 Balrog 纏身的遞回方法;我等著看結果......)。
跳過一些遞回合并細節(但請注意,這就是“遞回”合并驅動程式條目的內容),我們繼續前進:該subtree策略實際上只是recursive偽裝的演算法,因此它處理這些與-s recursive. 該ours策略忽略所有其他輸入:其最終提交只是HEAD提交的內容,具有額外的父項,因此合并基礎問題變得無關緊要。如前所述,章魚一開始就沒有使用git merge-base --all。因此,如果我們需要遞回合并,執行它的策略會合并合并基礎并提交結果(包括任何合并沖突,這是 Balrog 對您的任務造成嚴重破壞的主要地方)。這個合并的結果 然后是合并操作的新合并基礎。
所以,這讓我們得到了一個單一的合并基礎,要么扔掉額外的 ( -s resolve) 要么合并它們(其他所有東西,除了-s oursand -s octopus,它們甚至不在這里)。我們現在正好有三個提交要考慮進行合并:B,合并基礎;L,“本地”或--ours提交;和R,“遠程”或“其他”或--theirs提交。可以假設這些提交具有某種先行/后繼關系,1但它不再重要:各種雙頭合并演算法現在準備考慮三種可能的情況:2
- 乙= R。如果合并基礎提交是“他們的”提交,則無事可做。Git 說
Already up to date.和不做。 - 乙= L。如果合并基礎是“我們的”(HEAD)提交,則可以進行快進。如果允許或需要,Git 會去做。這種情況下不可能發生沖突;見下文。
- B?L,B?R。需要“真正的合并”。
為了執行真正的合并,Git 執行以下內部化變體:
- 運行:這是“我們改變的”;
git diff --find-renames B L - 運行:這是“他們改變的”;
git diff --find-renames B R - 結合這些變化。
The combine changes step is where merge conflicts can occur. They do occur if:
- lines affected in diff #1 overlap lines affected in diff #2, but the changes to those lines are not identical, or
- lines affected in the two diffs abut (as jthill noted).
Overlap is allowed if and only if the two diffs make the same change to those lines.
If we force a "real merge" where a fast-forward is allowed (see #2), this means B = L, so the diff from B to L is empty. An empty diff never conflicts with another empty diff, nor with any non-empty diff: the result of combining is to take all of their changes.
If we *do *have conflicts, the -X ours or -X theirs flags, if specified, now come into play: these resolve the conflict by favoring ours or theirs. For these cases, the merge is not stopped.
If we have rerere enabled and there are now conflicts that have recorded resolutions, Git will take the recorded resolution. For these cases, however, the merge is stopped: you must inspect the result yourself. Presumably this therefore happens after the -X cases, but I have not tested that.
If there are unresolved conflicts, the merge stops here, unfinished. It is your job to clean up any messes left behind (in your working tree and/or Git's index). Otherwise, unless --squash and/or --no-commit were specified, Git goes on to make the new merge commit.
如果合并停止MERGE_HEAD,除非--squash指定,否則另一個頭的(或頭的)哈希 ID 將寫入偽參考。這確保下一個git commit將正確結束合并。
1如果他們沒有,我們必須提供--allow-unrelated-histories,在這種情況下,合并基礎是在兩個分支提示提交之前的虛擬空提交。相同的代碼用于cherry-pick 和revert,其中某些先行/后繼關系可能不會有意保持,因此不會檢查;此描述僅用于git merge目的。
2可以預先檢查R ? L,但我認為 Git 實際上不會。無論哪種方式,效果都應該相同。
uj5u.com熱心網友回復:
我怎么能理解,事先運行 git merge test,Git 將如何處理這些合并?
你不能事先理解它,但你可以在不實際提交合并的情況下進行合并,因此你可以研究結果。說啊
git --no-ff --no-commit merge test
然后環顧四周。
uj5u.com熱心網友回復:
在運行之前
git merge test,我如何理解Git 將如何處理這些合并?
在一些罕見的(基本上從來沒有無意產生的)情況下,基本操作下面會有額外的準備作業,或者整個事情可以在微不足道的“快進”情況下被回避,但是:看看git merge test將使用什么, 說
git diff ...test # diffs on test since histories diverged
git diff test... # diffs in checkout since test history diverged
這些是 Git 將合并的兩組差異。
Git 有一個默認的自動合并,它應用所有不重疊或不鄰接任何不同變化的大塊頭,但重疊或鄰接的變化塊不能可靠地自動合并,沒有人想出如何推匯出“正確”的將軍結果,所以你必須解決這個問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/354937.html
