即使文件存在,也会在合并期间强制git重命名检测

时间:2014-04-10 06:49:00

标签: git merge rename

我目前正在对Java应用程序进行大规模重构,将服务类拆分为服务接口和服务实现,例如

package de.abc.def;
public class AuthenticationService {
    public void doStuff() {
        System.out.println("doing stuff");
    }
}

变为

package de.abc.def;
public interface AuthenticationService {
    void doStuff();
}

package de.abc.impl;
public class AuthenticationServiceImpl implements de.abc.def.AuthenticationService {
    @Override public void doStuff() {
        System.out.println("doing stuff");
    }
}

所有这些都在master中发生在几个不同的操作中(首先将AuthenticationService移动到新包并重命名,提交更改,然后使用重构来引入接口,从而在旧位置重新创建AuthenticationService.java ,并再次承诺) 当我现在尝试将对另一个分支中的服务类的更改合并到master中时,git会产生很多合并冲突 - 基本上我可以手动解决对服务类的每个更改。我认为/希望git会检测重命名操作并将对服务类所做的更改合并到服务实现中(它们与旧服务类几乎完全相同),但似乎git很高兴使用现有文件和试图合并它 - 完全失败。

有没有办法强制git首先考虑重命名?或者我是否必须重命名或移动所有服务接口,以便git找不到候选者(这是我想避免的......)?

由于

1 个答案:

答案 0 :(得分:2)

基于端点的Git合并(与合并库相比)。让我们绘制提交图:

... - B - R1 - R2   <-- HEAD=master
        \
          S1 - S2   <-- service

此处B是合并基础(两个分支发散的点),提交R1重命名文件,提交R2重新引入旧名称。

同时,提交S1S2service(服务类)分支上的普通非重命名提交。

当你在master并且git merge service时,git会在下面有效地执行此操作:

git diff -M B R2 > our_changes
git diff -M B S2 > their_changes
# now combine the two sets of changes and make a new commit

-M尝试检测重命名,但由于提交R2重新引入旧文件名而被愚弄。

有两种明显的(?)方法可以自动进行合并:

  1. 找到重命名,在service中创建相同的名称,并在那里进行提交S3,以便名称匹配(然后希望git不会意外地检测到比较中的{ {1}} B并弄得一团糟,或者;
  2. 逐步进行合并。
  3. 我怀疑(没有尝试)方法2会更好用,而且你已经完成了提交S3R1的工作,所以你也可以使用它。

    要执行此操作,请检查提交R2(您可以将此作为&#34;分离的HEAD&#34;提交,或为其创建分支 - 让我们调用它{{1所以你做R1),然后temp得到一个新的合并提交。这次,当git执行从git checkout -b temp master^git merge service的差异时,它应检测重命名,并将B分支中的更改应用于重命名的文件(这些当然是< em> old ,无意义的文件,但这几乎是你必须要做的事情,以便应用更改)。现在图表看起来像这样:

    R1

    您现在可以通过执行service R2 <-- master / ... - B - R1 ---- M1 <-- HEAD=temp \ / S1 - S2 <-- service 合并到temp。此合并的合并基础为master:git将查看git checkout master; git merge tempR1之间的更改,以及R1M1之间的更改,以及尝试将R1更改置于R2之上,进行新的合并提交R1 to M1

    R2

    M2&#34;捕获&#34;重命名(好吧,我们希望), R2 - M2 <-- HEAD=master / / ... - B - R1 ---- M1 <-- temp \ / S1 - S2 <-- service M1中的更改现在可能会出现在正确的(旧的,重构前)文件中。


    上面假设了一定数量的提交,但总体思路是:通过选择更早的&#34;端点&#34;来帮助git。对于合并,重命名检测将执行您想要的操作。为这些合并结果创建一个临时分支。然后使用合并结果作为第二次合并的输入。 (如果需要,请重复两次以上的合并。)记得在完成后删除临时分支名称。