2017-10-12 233 views
1

我在功能分支上工作了幾天,現在已準備好併入dev。在處理此功能時,我已合併dev以接收修補程序。我的歷史是這樣的:當我與開發人員合併時,如何壓縮提交?

* E (feature1) 
* D:merge with dev 
| \ 
* C * B:patch (dev) 
    \ | 
    * A 

我想整支擠進了一個提交,合併與dev,然後快進dev。問題是,E不能因爲它們之間的合併而與C壓縮。唯一的選擇似乎是壓縮EBC(稱爲新的提交F),在這種情況下,壓扁的提交還將包含作爲不相關補丁一部分的更改。一旦合併到dev中,將會有兩個應用修補程序的提交:F(應用修補程序並添加功能)和B(僅適用修補程序)。此外,F現在將進行兩個未更改的更改。

有沒有一種方法可以讓我的歷史保持清潔和乾淨?我需要改變我的工作流程嗎?

+0

推薦的工作流程更改:絕不合並開發。取而代之的是它。你應該可以通過簡單地在'dev'上做一個rebase來解決這個問題。 – o11c

+0

同意(兩種)。將嘗試 – lfk

+0

@ o11c - 重新調整您的分支歷史記錄。雖然我碰巧是一個粉絲,但有時候會有點危險,特別是如果你不知道自己在做什麼。此外,在發生衝突時,重新組裝會變得非常煩人,因爲每次重新綁定時都必須重新解決衝突,而通過合併,您可以解決一次衝突,然後繼續前進。 – JDB

回答

0

Git不跟蹤提交中的更改。每次提交都包含回購中文件的完整副本。 「變更」是通過比較兩個提交來確定的。

因此,在短,但絕對與擠壓EBC到提交F,然後合併結果表明,到Dev分支沒有問題。提交分支上的B提交仍然存在。當git將FB進行比較時,只有CE引入的更改將歸於F

當然,您可以通過使用git rebase來解決這個感知問題,但它帶來了一系列令人頭痛的問題。例如,由於git rebase會更改您的分支歷史記錄(將您的提交移至dev的最新提交之上),如果存在衝突,則每次重新綁定時都必須重新解決這些衝突。如果您的問題需要一段時間才能解決,那麼速度會變得很快,需要幾次重新設置才能與開發者保持同步。


只是爲了證明這是所有真實的,你有什麼好擔心的,我已經建立的示例GitHub庫:https://github.com/cyborgx37/sandbox

首先,我們有dev branch,它具有B提交。

B:patch 
| 
A 

然後,我創建了feature1 branch,其中有犯CDE。 (需要注意的是,因爲d是一個合併,從而具有兩個父母,B也顯示了在提交歷史)

E 
| 
D:merge with dev 
|\ 
C \ 
| B 
A 

最後,還有的dev-with-feature1 branch

F 
| 
B:patch 
| 
A 

我創造了這個岔開開發的,然後使用

git merge --squash feature1 
git commit -m "F" 

所有的特徵1的承諾擠進單個提交,F

如果您檢查diff for the F commit,您會看到它不會「應用修補程序」。由於B already contains those changesF只是重複它們,所以git不會將它們與F關聯起來。

從另一個角度看,here's the blame

initial  hello! 
B:patch  patch! 
F   new feature!!! 

Git不會跟蹤提交的變化。它存儲您的完整項目狀態。 「變更」是通過將提交與其父(或前任)提交進行比較來確定的。因爲B有修補程序,所以git會將其與B相關聯。所以,預計補丁也將在F之內。它不會在F的唯一方法是如果您刪除了該修補程序。

+0

這樣想一想:F的提交消息表示它實現了feature1。但實際上,當你從F ^移動到F時,你也會得到補丁。基本上,提交信息在說謊。 – lfk

+0

也許我的理解不正確。你打算從開發分支中刪除'B'嗎?如果沒有,那麼沒有問題。 'F' *應該包含'B',因爲'F'在'B'之後。 'F'將包含所有文件狀態的完整副本,因此當您嘗試確定'F'引入的更改時,git會將'F'與'B'進行比較並給出差異。由於補丁已經在'B'中,git不會認爲它屬於'F'。 – JDB

+0

@Farshid - 想想git就像一個充滿zip文件的文件夾。每個zip文件都有一個日期戳,所以你可以跟蹤訂單。每個zip文件都包含該日期出現的完整源代碼。如果您想知道在特定日期推出的內容,請將當天的zip與前一個zip進行比較。這基本上就是git的工作方式......每個提交都是所有文件狀態的完整副本,而不是**變更記錄。 – JDB

0

如果我理解正確,您希望將承諾E的全部內容應用爲B之上的單個提交。

如果這是你想要實現的,你可以使用git checkout E .什麼(不要忘了"."):

# go to your `dev` branch : 
git checkout dev 

# get the *content* of E (here comes the ".") : 
git checkout E . 

# all the content of E should appear as modifications staged for commit : 
git status -sb 

# you can double check that the content is to your liking : 
git diff --cached # --cached means 'compare with the index' 
gitk --cached  # as opposed to 'compare with what is on the disk' 

# commit 
git commit 
+0

這是一個非常有趣的方法。我可以看到至少有一個問題:你會知道合併後的結果是否在開發後才起作用,而不是合併(或重新綁定)開發,測試它然後快速轉發。當然,如果它不起作用,你不必在開發中提交它。但另一個問題是您無法創建合併提交,這有助於保持良好的歷史記錄。 – lfk

0

這裏就是我所做的:我壓扁EBC到一個新的提交F ,其中F表示它實現了feature1(注意到目前爲止它還添加了該補丁)。然後我重新登錄到dev。現在提交消息和歷史記錄是正確的:F包含該補丁,但它沒有添加它 - 它是由以前的提交添加的。

最後,我合併dev(與--no-ff強制合併提交)。

未來,我將避免與dev和rebase合併。

相關問題