如何强制git进入“合并冲突模式”?

时间:2017-05-03 14:14:24

标签: git merge

我在分支foo中有一个文件master。它需要一些工作,所以我创建了分支bar,我做了一些工作。事情看起来令人满意,所以我准备合并回master。只有一个问题:我希望保留我在分支bar中所做的所有更改以供将来参考,但并非所有更改都属于master,而不是现在。但是如果我进行通常的合并,git将不会发现任何冲突 - 因为foo中的文件master尚未被编辑 - 并且只会进行合并。有没有办法强制git执行此合并,就像我需要解决的冲突一样?或者是否有其他方法可以将bar中的选定更改放入master

3 个答案:

答案 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-pickrebase --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]