我已经在功能分支上工作了几天,现在它已准备好合并到dev
。在处理此功能时,我已与dev
合并以接收修补程序。我的历史看起来像这样:
* E (feature1)
* D:merge with dev
| \
* C * B:patch (dev)
\ |
* A
我想将整个分支压缩成一个提交,与dev
合并,然后快进dev
。问题是,当E
合并到它们之间时,C
无法被E
压扁。唯一的选择似乎是压缩B
,C
和F
(调用新的提交dev
),在这种情况下,压缩的提交还将包括部分更改一个无关的补丁。合并到F
后,将有两个应用修补程序的提交:B
(应用修补程序并添加功能)和F
(仅应用修补程序)。此外,{{1}}现在将进行两次未经修改的更改。
有没有办法让我的历史变得干净整洁?我需要更改工作流程吗?
答案 0 :(得分:1)
Git不会跟踪提交中的更改。每个提交都包含repo中文件的完整副本。 “更改”是通过区分两个提交来确定的。
因此,简而言之,将E
,B
和C
压缩到提交F
然后将其合并到dev分支上绝对没有问题。 B
提交仍将存在于dev分支上。当git将F
与B
进行比较时,C
和E
引入的更改只会归因于F
。
当然,您可以使用git rebase
解决这个问题,但这会带来一系列令人头疼的问题。例如,由于git rebase
更改了您的分支历史记录(在dev的最新提交之上移动提交),如果存在冲突,则每次重新绑定时都必须重新解决这些冲突。如果您的问题需要一段时间才能解决,那么这个问题就会变得很快,需要几个rebase才能与dev保持同步。
为了证明这一切都是真的,你没有什么可担心的,我已经设置了一个示例GitHub repo:https://github.com/cyborgx37/sandbox
首先,我们拥有dev branch,其B
提交。
B:patch
|
A
然后我创建了feature1 branch,其中提交了C
,D
和E
。 (注意,因为D是一个合并,因此有两个父项,B
也出现在提交历史中)
E
|
D:merge with dev
|\
C \
| B
A
F
|
B:patch
|
A
我从dev创建了这个分支,然后使用
git merge --squash feature1
git commit -m "F"
将所有 feature1 的提交压缩为单个提交F
。
如果你检查diff for the F
commit,你会发现它没有“应用补丁”。由于B
already contains those changes和F
只是重复它们,因此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)
以下是我的操作:我将E
,B
和C
压缩到新的提交F
中,并显示F
的消息,说明它实现了feature1 (注意到目前为止它还添加了补丁)。然后我重新加入dev
。现在提交消息和历史记录都是正确的:F
包含补丁,但它没有添加它 - 它是由之前的提交添加的。
最后,我与dev
合并(使用--no-ff
强制进行合并提交。)
将来,我将避免与dev
和rebase合并。