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

3
我在分支“master”中有一个名为“foo”的文件。这个文件需要一些工作,于是我创建了一个名为“bar”的新分支,进行了一些工作。事情看起来很令人满意,所以我准备合并回“master”。但是有一个问题:我想保留我在“bar”分支中做出的所有更改,以备将来参考,但并不是所有的更改都应该在现在合并到“master”。但是如果我按照通常的方式合并,git将不会发现任何冲突——因为“master”中的“foo”文件尚未被编辑——并且只会执行合并操作。是否有一种方法可以强制 git 将此合并视为需要解决的冲突?或者是否有其他方法只将选定的更改放入“master”中的“bar”分支中?
3个回答

6

有几个选项可供选择。直接回答你问题的一个是:

git merge --no-commit

会自动将合并操作执行到索引中,然后停止,就像需要手动解决冲突一样。当然,不会有冲突标记和任何“未暂存”/等待解决的更改,但是您可以在提交之前修改提交内容以满足您的需求。

这种方法最大的问题除了"做起来可能很混乱"之外,还包括对于Git而言,所有bar的更改现在都已计入master。由于您暗示稍后可能需要剩余的更改,这是不好的。

真正需要的是类似于:

x --- O --- M <--(master)
       \   /
         A --- B <--(bar)

其中,O 是原始分支点,A 包含你现在想要的更改,B 包含你以后想要的更改。

(或者,如果你想避免合并提交,你会选择

x --- O --- A <--(master)
             \  
              B <--(bar)

具体如何实现取决于您目前的状态。如果bar只有一个提交记录(或者,无论如何,如果您满意于最终只有一个“立即合并的提交”和一个“留待以后保存的提交”),并且在O之后的master上没有提交记录,则可以执行以下操作:

从下面开始:

x --- O  <--(master)
       \   
         AB <--(bar)

you do

git checkout bar
git reset --mixed HEAD^

(假设bar上真的只有一个提交;否则,请将HEAD^替换为类似于提交O的SHA1值或您在提交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上进行更改的拓扑结构),那么请在merge命令中传递--no-ff。否则,由于我们假设主分支没有与bar分支分岔,你将只获得一个快速前进的提交。
x --- O --- A <--(master)(bar)
             \             ^HEAD
              B <--{stash}

(反之,如果 master 已经分叉,但您决定线性化历史记录,则应将 A 变基到 master 而不是合并...)

然后你可以像这样做

git branch --delete bar
git stash branch bar

结束于
x --- O --- A <--(master)
             \
              B <--(bar)

"git add -p" 是我一直在寻找的将单个提交分成两个提交的理想工具,谢谢! - krubo

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

1

您需要将应合并到 master 的更改和不应合并到 master,但应保留在 bar 中的更改分别保存在不同的提交中:

o [master]
 \
  A - B - C - D - E - F [bar]
  ^^^^^^^^^
  to be merged

请注意,需要合并的提交需要先到达。如果不是这种情况,您需要使用git rebase -i master bar重新排序它们。
为了创建一个真正的合并提交(而不是将master快进到C),您需要执行以下操作。
$ git checkout master
$ git merge --no-ff <hash of commit C>

这应该导致
o --------- G [master]
 \         /
  A - B - C - D - E - F [bar]

通过省略--no-ff,您将得到:
o - A - B - C [master]
             \
              D - E - F [bar]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接