【问题标题】:git rebase master feature gives (rename/delete) conflict, git rebase -i master feature does notgit rebase master 特性给出(重命名/删除)冲突, git rebase -i master 特性没有
【发布时间】:2014-04-09 01:16:46
【问题描述】:

我在 git 中遇到了一个奇怪的情况,其中我有一个功能分支修改了一些文件并删除了一个文件“foo.js”。当我通过“git rebase master feature”重新定位到master时,我遇到了以下类型的冲突:

CONFLICT (rename/delete): src/main/resources/com/blah/bar.js deleted in Change some js and renamed in HEAD. Version HEAD of src/main/resources/com/blah/bar.js left in tree.

奇怪的是,主分支和特性分支都没有修改过 bar.js,更不用说删除了。更重要的是,执行“Git Rebase -I主功能”导致在没有冲突(选择所有“选择”时)。

一个可能的重要线索是 foo.js 和 bar.js 是相似但不相同的文件,稍微修改的文件也类似于 foo.js 和 bar.js。我唯一能做出的疯狂猜测是,对相关 js 文件所做的一些更改以某种方式使 git 误以为分支功能中的违规提交包括删除 bar.js,然后重命名 foo.js(这是已删除)到 bar.js。这是可能的/预期的吗?有谁知道为什么会发生这种情况?仅供参考,我在 linux mint 16 上使用 git 版本 1.8.3.2。

【问题讨论】:

    标签: git rebase


    【解决方案1】:

    有点不寻常,但你的诊断是正确的。

    交互式变基使用一系列git cherry-pick 命令。非交互式变基使用git-merge-recursive(至少默认情况下;查看git-core 目录中的git-rebase--merge 脚本,无论它在您的系统上的什么位置,或者简单地记下-s <strategy>-s <strategy> 参数)来制作旧提交的每个新提交。正如-m / --merge 的文档所说(尽管它没有提到这是默认):

           Use merging strategies to rebase. When the recursive (default)
           merge strategy is used, this allows rebase to be aware of renames
           on the upstream side.
     
           Note that a rebase merge works by replaying each commit from the
           working branch on top of the <upstream> branch. Because of this,
           when a merge conflict happens, the side reported as ours is the
           so-far rebased series, starting with <upstream>, and theirs is the
           working branch. In other words, the sides are swapped.
    

    您可以通过使用 git diff -M --name-status1 来比较可疑提交对来确定。如果这显示bar.jsDeleted 和foo.jsR命名为bar.js,那就是罪魁祸首。

    令人讨厌的是,没有办法为合并设置重命名阈值。幸运的是,解决方法是简单地运行一个交互式 rebase,并且不对命令系列进行任何更改,您可以通过以下方式捷径:

    GIT_EDITOR=: git rebase -i ...
    

    或使用-p 选项来保留合并(如果您有合并,后者会有所不同,但具有执行“隐含交互”变基的副作用,它只是设置GIT_EDITOR=: 并关闭自动压缩) .


    1如果您已将diff.renames 配置为true,则不需要-M 选项(请参阅git config documentation)。合并递归在内部设置重命名但不复制检测,并设置“重命名限制”中的第一个适用:您配置的merge.renamelimit,如果有的话;你的diff.renamelimit,如果你有的话;或常量1000

    【讨论】:

    • 感谢您的确认。我看不到在所涉及的提交中的任何两个提交之间使用“git diff --name-status”进行任何重命名。是否有可能 git diff --name-status 隐藏了这个,但是为了识别冲突,有一个“隐藏的重命名”?
    • @jonderry:我忘了建议给git diff 提供-M 选项,如果你没有在你的git 配置中将diff.renames 设置为true,这很重要。 (如果你已经配置了diff.renames true,那么其他的就很奇怪了……)
    猜你喜欢
    • 2013-03-14
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    • 1970-01-01
    • 2012-08-11
    • 2017-07-27
    • 2011-12-16
    • 1970-01-01
    相关资源
    最近更新 更多