当我与dev合并时,如何压缩提交?

时间:2017-10-12 01:05:14

标签: git merge rebase git-rebase git-squash

我已经在功能分支上工作了几天,现在它已准备好合并到dev。在处理此功能时,我已与dev合并以接收修补程序。我的历史看起来像这样:

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

我想将整个分支压缩成一个提交,与dev合并,然后快进dev。问题是,当E合并到它们之间时,C无法被E压扁。唯一的选择似乎是压缩BCF(调用新的提交dev),在这种情况下,压缩的提交还将包括部分更改一个无关的补丁。合并到F后,将有两个应用修补程序的提交:B(应用修补程序并添加功能)和F(仅应用修补程序)。此外,{{1}}现在将进行两次未经修改的更改。

有没有办法让我的历史变得干净整洁?我需要更改工作流程吗?

3 个答案:

答案 0 :(得分:1)

Git不会跟踪提交中的更改。每个提交都包含repo中文件的完整副本。 “更改”是通过区分两个提交来确定的。

因此,简而言之,将EBC压缩到提交F然后将其合并到dev分支上绝对没有问题。 B提交仍将存在于dev分支上。当git将FB进行比较时,CE引入的更改只会归因于F

当然,您可以使用git rebase解决这个问题,但这会带来一系列令人头疼的问题。例如,由于git rebase更改了您的分支历史记录(在dev的最新提交之上移动提交),如果存在冲突,则每次重新绑定时都必须重新解决这些冲突。如果您的问题需要一段时间才能解决,那么这个问题就会变得很快,需要几个rebase才能与dev保持同步。

为了证明这一切都是真的,你没有什么可担心的,我已经设置了一个示例GitHub repo: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

我从dev创建了这个分支,然后使用

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

将所有 feature1 的提交压缩为单个提交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的方式。

答案 1 :(得分: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

答案 2 :(得分:0)

以下是我的操作:我将EBC压缩到新的提交F中,并显示F的消息,说明它实现了feature1 (注意到目前为止它还添加了补丁)。然后我重新加入dev。现在提交消息和历史记录都是正确的:F包含补丁,但它没有添加它 - 它是由之前的提交添加的。

最后,我与dev合并(使用--no-ff强制进行合并提交。)

将来,我将避免与dev和rebase合并。