git rebase master功能给(重命名/删除)冲突,git rebase -i master功能没有 [英] git rebase master feature gives (rename/delete) conflict, git rebase -i master feature does not

查看:1113
本文介绍了git rebase master功能给(重命名/删除)冲突,git rebase -i master功能没有的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个奇怪的情况,我用git修改了一些文件并删除了一个文件foo.js。当我通过git rebase master feature重新绑定到master上时,我遇到了以下类型的冲突:

  CONFLICT(重命名/删除):删除了src / main / resources / com / blah / bar.js改变一些js并在HEAD中重命名。 src / main / resources / com / blah / bar.js的版本HEAD留在树中。 

奇怪的是,master分支和feature分支都没有修改bar.js,更不用说删除它了。更重要的是,执行git rebase -i master feature不会产生冲突(当选择所有pick时)。 bar.js类似但不完全相同的文件,稍有修改的文件也与foo.js和bar.js类似。我可以做出的唯一一个疯狂的猜测是,对相关js文件所作的一些更改让混淆的git认为分支功能中的违规提交包括删除bar.js,然后重命名为foo.js(这是删除)bar.js.这是可能的/预期的吗?有谁知道为什么会发生这种情况? FYI,我在Linux mint 16上使用git 1.8.3.2版本。 有点不寻常,但你的诊断是正确的。

交互式重新组织使用一系列 git cherry-pick 命令。非交互式数据库使用 git-merge-recursive (默认情况下至少;请参阅 git-rebase - merge 脚本放在 git-core 目录中,或者只是记录 -s<策略> 参数转换为 git rebase )来从旧的提交进行新的提交。正如 -m / - merge 的文档所述(尽管它没有提及这是默认):


 使用合并策略来重新绑定。当使用递归(默认)
合并策略时,这允许rebase在上游侧知道重命名


请注意,通过在< upstream>顶部的
工作分支中重播每个提交,科。正因为如此,当合并冲突发生时,
报告为我们的一方是
到目前为止的重新贷款系列,从< upstream>开始,他们是
工作分支。换句话说,双方交换。


您可以使用 git diff -M --name-status 1 来比较可疑提交对。如果这显示 bar.js D eleted并且 foo.js 作为 R 转化为 bar.js ,这是罪魁祸首。



令人烦恼的是,没有办法设置合并的重命名阈值。幸运的是,解决方法只是运行一个交互式重定位,并不对命令系列进行任何更改,您可以通过这种方式快速切换:

  GIT_EDITOR =:git rebase -i ... 

或者使用 -p 选项来保留合并(后者是不同的如果你有合并,但有副作用做一个隐含的交互式rebase,它只需设置 GIT_EDITOR =:

1 也会关闭autosquash)如果您将 diff.renames 配置为 true -M 选项$ c>(参见 git config 文档)。合并递归在内部设置重命名而不是复制检测,并将重命名限制设置为适用的第一个:您配置的 merge.renamelimit ,如果您有一个;你的 diff.renamelimit ,如果你有的话;或常量 1000


I encountered a strange situation with git in which I had a feature branch that modified some files and deleted one file "foo.js". When I rebased onto master via "git rebase master feature", I encountered the following type of conflict:

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.

The odd thing is that neither neither the master branch nor the feature branch had even modified bar.js, let alone deleted it. What's more, executing "git rebase -i master feature" results in no conflict (when choosing all "pick").

One possible important clue is that foo.js and bar.js are similar but not identical files, and the slightly modified files are also similar to foo.js and bar.js. The only wild speculation that I can make is that some of the changes made to related js files somehow confused git into thinking that the offending commit in branch feature consisted of a delete of bar.js followed by a rename of foo.js (which was deleted) to bar.js. Is this possible/expected? Does anyone have any idea why this could happen? FYI, I'm using git version 1.8.3.2 on linux mint 16.

解决方案

That is a bit unusual, but your diagnosis is correct.

An interactive rebase uses a series of git cherry-pick commands. A non-interactive rebase uses git-merge-recursive (by default at least; see the git-rebase--merge script in the git-core directory, wherever that is on your system, or simply note the -s <strategy> argument to git rebase) to make each new commit from an old one. As the documentation for -m / --merge says (although it fails to mention that this is the default):

       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.

You can tell for sure by using git diff -M --name-status1 to compare the suspect commit pair. If this shows bar.js as Deleted and foo.js as Renamed to bar.js, that's the culprit.

Annoyingly, there is no way to set the rename threshold for merge. Fortunately the workaround is simply to run an interactive rebase and make no changes in the command series, which you can short-cut by doing:

GIT_EDITOR=: git rebase -i ...

or by using the -p option to preserve merges (the latter is different if you have merges, but has the side effect of doing an "implied interactive" rebase, which simply sets GIT_EDITOR=: and also turns off autosquash).


1The -M option is not required if you have configured diff.renames to true (see git config documentation). Merge-recursive internally sets the rename but not copy detection, and sets the "rename limit" the first of whichever of these applies: your configured merge.renamelimit, if you have one; your diff.renamelimit if you have one; or the constant 1000.

这篇关于git rebase master功能给(重命名/删除)冲突,git rebase -i master功能没有的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆