我在分支foo
中有一个文件master
。它需要一些工作,所以我创建了分支bar
,我做了一些工作。事情看起来令人满意,所以我准备合并回master
。只有一个问题:我希望保留我在分支bar
中所做的所有更改以供将来参考,但并非所有更改都属于master
,而不是现在。但是如果我进行通常的合并,git将不会发现任何冲突 - 因为foo
中的文件master
尚未被编辑 - 并且只会进行合并。有没有办法强制git执行此合并,就像我需要解决的冲突一样?或者是否有其他方法可以将bar
中的选定更改放入master
?
答案 0 :(得分:2)
有几种选择。直接回答你问题的那个:
git merge --no-commit
将执行自动合并到索引然后停止,就像需要手动冲突解决一样。当然,没有冲突标记,也没有变化"未分级" /等待解决,但您可以在提交之前修改提交以查看您想要的内容。
最大的问题是,除了"它可能是一件混乱的事情",就git而言,bar
中的所有变化现在都在master
。由于您暗示您可能希望稍后进行其余更改,因此不太好。
你真正想要的是像
x --- O --- M <--(master)
\ /
A --- B <--(bar)
其中O
是原始分支点,A
具有您现在想要的更改,B
具有您稍后想要的更改。
(或者,如果你想避免合并提交,你会想要
x --- O --- A <--(master)
\
B <--(bar)
代替。)
如何最好地达到这个目标取决于你现在拥有的东西。如果bar
只有一次提交(或者,无论如何,如果你很高兴最终只有一个&#34;现在提交合并&#34;并且一个&#34;提交到保存以供日后使用#34;),如果在master
之后O
上没有提交,则可以执行以下操作:
从
开始x --- O <--(master)
\
AB <--(bar)
你做了
git checkout bar
git reset --mixed HEAD^
(假设bar
上只有一次提交;否则,请将HEAD^
替换为提交O
的SHA1值或您标记的标记{39} ;在提交O
)时实施。现在你有了
x --- O <--(master)(bar)
^HEAD
来自bar
的所有原始更改未在您的工作树中进行。由于所有更改都在一个文件中,因此我们需要使用补丁模式来有选择地添加更改
git add -p
# select the changes to merge
git commit
git stash
给你
x --- O <--(master)
\
A <--(bar)
\ ^HEAD
B <--{stash}
下一步
git checkout master
git merge bar
如果要进行合并提交(保留在bar
上进行更改的拓扑),请将--no-ff
传递给merge
命令。否则,因为我们假设主人没有与bar
分道扬,所以你只能快速离开
x --- O --- A <--(master)(bar)
\ ^HEAD
B <--{stash}
(相反,如果master
已分歧但您决定将历史记录线性化,则可以将A
重新定位到master
而不是合并...)< / p>
然后你可以做类似
的事情git branch --delete bar
git stash branch bar
结束于
x --- O --- A <--(master)
\
B <--(bar)
答案 1 :(得分:1)
如果我猜对了,您只希望将选择性更改从bar
合并到master
。在这种情况下,您可以使用cherry-pick
或rebase --onto
来完成此操作,只要您想要引入主分支的更改是在原子提交中。 (如果不是,你可能需要重写历史来做到这一点)
>>> git checkout bar
>>> git log --oneline
b00ac1e third
24097f8 second
ade3073 first
# Let's say you want to bring `third` and `second` commit into master but not first
# Use cherry-pick if you have few commits, that you want to transfer
>>> git checkout master
>>> git cherry-pick 24097f8 # sha id of `second` commit
>>> git cherry-pick b00ac1e # sha id of `third` commit
答案 2 :(得分:1)
You need to keep the changes that are supposed to be merged into master
and the changes in separate commits than the ones which are not to be merged into master
, but to be kept in bar
:
o [master]
\
A - B - C - D - E - F [bar]
^^^^^^^^^
to be merged
Note that the commits which are to be merged need to come first. If this is not the case you need to reorder them using git rebase -i master bar
.
In order to create a real merge commit (as opposed to fast-forwarding master
to C
) you need to do
$ git checkout master
$ git merge --no-ff <hash of commit C>
This should result in
o --------- G [master]
\ /
A - B - C - D - E - F [bar]
By omitting --no-ff
you would get
o - A - B - C [master]
\
D - E - F [bar]