[英]Git merge only commits within branch
考慮下面的這棵樹。 請原諒這個蹩腳的圖表,但我想你明白了。
我有一個MASTER
分支和一個MY BRANCH
。 我從MASTER
創建了一個PATCH
分支並在這個分支上進行修復。 然后我合並修復到兩個MASTER
和MY BRANCH
。 當我這樣做時, MY BRANCH
也會隨之提交C
& D
。
MASTER----A----B----C----D-------------MERGE
\ \ /
\ PATCH----E----F
\ \
MY BRANCH----G----H-------MERGE
如何僅將補丁中的提交合並到MASTER
和MY BRANCH
?
正如 RomainValeri 指出的那樣,可以更好地繪制圖形。 我將借用他的變體開始,但在您嘗試進行任何合並之前先繪制我們擁有的內容:
E---F <<< patch
/
A---B---C---D <<< master
\
G---H <<< my-branch
名稱patch
是指現有的提交F
,名稱master
和my-branch
是指現有的提交H
。
您遇到的問題是因為git merge
基於提交圖而不是分支名稱工作。 名稱找到提交,就目前而言是可以的,但是如果您運行git merge <commit F>
,結果將包括提交F
,其中將包括提交E
,其中將包括提交D
,其中將包括提交C
,這將包括提交B
,依此類推。
也就是說,提交F
任何成功合並都會自動包括導致並包括F
本身的每個提交。
您可以使用git cherry-pick
來復制單個提交。 請記住,提交是一個快照,即所有文件的完整集合。 但是每個提交也有一個父提交。 1如果將提交E
中的快照與其父提交D
的快照進行比較,您將看到提交E
更改。 如果您將提交F
的快照與其在提交E
父快照進行比較,您將看到您在提交F
所做的更改。 挑選本質上允許您在其他地方“重播”這些更改。
這導致人們經常提出的建議,在這里使用cherry-pick。 如果您創建一個名為patch2
的新分支,從提交H
開始,並將E
和F
復制到新的和改進的提交E'
和F'
,其中E'
和F'
出現在提交H
,您將得到:
E---F <-- patch
/
A---B---C---D <-- master
\
G---H <-- my-branch
\
E'-F' <-- patch2
您現在可以將原始補丁合並到master
並將新的和不同的(據說改進的) patch2
分支合並到my-branch
。
有一個更好的方法! 好吧,無論如何,經常。 讓我們退后一步問:你為什么首先要寫提交E
和F
?
有可能是修復提交A
或提交B
或兩者中的錯誤。 或者它可能添加了提交B
缺少的功能。 無論如何,您相信它可以在不提交C
和D
的情況下應用。
你現在應該做的是證明這一點。 創建一個新分支patch2
但不要將其指向現有提交H
。 改為在提交B
啟動它。 然后將E
和F
復制到新改進的E'
和F'
,給出:
E--F <-- patch
/
C--D <-- master
/
A--B--E'-F' <-- patch2
\
G--H <-- my-branch
請注意,所有現有的提交仍然存在,完全相同。 (你還沒有在任何地方合並任何東西。)但是如果patch2
真的有效,我們現在可以扔掉名為patch
的分支,放棄提交EF
:
E--F [abandoned]
/
C--D <-- master
/
A--B--E'-F' <-- patch2
\
G--H <-- my-branch
現在我們已經完成了,讓我們停止繪制它們,並將現有分支patch2
重命名為patch
:
C--D <-- master
/
A--B--E'-F' <-- patch
\
G--H <-- my-branch
復制的(櫻桃挑選的或重新定位的)提交E'-F'
現在處於我們可以運行git checkout master; git merge patch
git checkout master; git merge patch
和git checkout my-branch; git merge patch
git checkout my-branch; git merge patch
。 當我們這樣做時,我們會得到兩個合並提交:
C--D--M1 <-- master
/ /
A--B--E'-F' <-- patch
\ \
G--H--M2 <-- my-branch
這些合並按您喜歡的方式運行:它們只將補丁帶入分支,而不是任何其他與補丁無關的提交。
如果您要修復錯誤或添加共享功能,請在圖表中找到錯誤或功能可以到達的最早提交。 在這種情況下,那是在提交B
。 (也許可以將它放在提交A
,如果是這樣,您可以改為這樣做。但是,如果錯誤或功能需要提交B
一部分,則提交B
是您可以走的最遠的地方。)
這樣做的原因是生成的補丁可以干凈地合並到該點“下游”的任何提交。 在這種情況下,你想合並補丁放到提交D
,在master
,下游B
,並進入H
,在my-branch
,下游B
。 由於patch
在提交F'
處位於B
下游,因此將patch
合並到任何分支都將引入提交B
。 但是提交B
是分支patch
有用的第一個地方。 任何尖端不在B
下游的分支根本不能使用補丁! 因此,通過在可能使用的第一個位置之后立即放置補丁本身,所有其他可以使用補丁的分支都可以輕松干凈地使用補丁。
使用rebase
或cherry-pick
手動將E
和F
應用到MYBRANCH
或僅以E
和F
開始正確創建PATCH
分支。
您可以使用范圍來指定目標分支上的哪些提交:
git checkout my-branch
git cherry-pick master..patch
其中master..patch
意味着:
一切patch
減號一切已知的master
作為旁注,對更好的樹模式的建議
E---F <<< patch
/ \
A---B---C---D-------I <<< master
\
G---H <<< my-branch
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.