在分支中间修改提交,具有交互式变基需要解决冲突



例如,master 分支对以下人员创建的内容进行了 init 提交:

echo "init" > data

我创建了功能分支:

git checkout -b feature

然后是连续提交的更改:

for newLine in feature1 feature2; do echo "$newLine" >> data; git commit -am "$newLine" ; done

我想更改功能1提交:

git rebase -i master

使"编辑"功能1提交,更改数据文件并继续变基:

sed -i 's/feature1/F/g' data; git add data; git rebase --continue

但存在冲突:

init
<<<<<<< HEAD
F
=======
feature1
feature2
>>>>>>> f4ac9dc... feature2

是否有可能避免这种冲突。我只需要应用差异。结果将是:

init
F
feature2

不合适的解决方案:

git rebase -s recursive -X {ours,theirs} -i master

我能够想出一个自定义合并工具,该工具允许在以下假设下自动解决所描述场景的冲突:

  1. 修改更改和上游更改(如果有)仅限于更改的行(即不添加或删除任何行)。

  2. 冲突完全是由于变化的对接(即变化不得重叠)。

然后,可以通过将以后的更改转换为通过绝对行号表示的 ed 脚本并在文件的本地版本上运行该脚本来解决此类冲突。

下面的虚拟合并脚本实现了这个想法。

它必须按如下方式注册到 git:

git config mergetool.dummymerge.cmd 'dummymerge $BASE $LOCAL $REMOTE > $MERGED'
git config mergetool.dummymerge.trustExitCode true

使用它来自动解决所描述类型的冲突,如下所示:

git mergetool -t dummymerge

虚拟合并

#!/bin/bash
myname=$(basename "$0")
if [ $# -ne 3 ]
then
    echo "Usage: $myname base_rev rev1 rev2"
    exit 1
fi
diff -e "$1" "$3"|patch -e -o - "$2"

不;至少,避免或忽略这种冲突是不容易的。编辑太接近了。

(以下是对 git 默认行为的描述。Leon 的回答显示了通过定义自定义合并工具来解决这些限制的一种方法。

合并的工作原理是创建一个表示一个分支中更改的补丁(如diff -u),并将其(与patch一样)应用于另一个分支。为了应用补丁,上下文必须相同。(请参阅差异/补丁如何工作以及它们的安全性如何?上下文,即围绕差异中实际删除和插入的几行,告诉修补工具它正在修补文件的正确部分。

Git 不会删除与原始行中删除的行不完全匹配的行

,并且除了与原始行完全匹配的行之间之外,它不会插入行。因此,它不会在"F"之后插入"feature2",因为它在补丁中说"feature2"在"feature1"之后(而不是在"F"之后)。

合并时,每次冲突附近发生更改时,都必须解决此冲突。当您显然必须连续对几十个提交进行相同的更正时,这可能会变得乏味,但我不知道有什么好方法可以解决它。

在某些情况下,您可以使用不同的合并策略来使您的生活更轻松。使用此功能时要小心,因为某些策略不如默认策略保守,并且可能很乐意破坏您的代码。无论如何,我认为没有合并策略可以解决示例问题。

最新更新