我遇到了一个奇怪的情况,我在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 master feature”不会产生冲突(选择所有“pick”时)。
一个可能的重要线索是foo.js和bar.js是相似但不相同的文件,稍微修改过的文件也类似于foo.js和bar.js.我可以做的唯一疯狂猜测是,对相关js文件进行的一些更改在某种程度上混淆了git,认为分支功能中的违规提交包括删除bar.js,然后重命名为foo.js(这是删除)到bar.js.这是可能/预期的吗?有谁知道为什么会发生这种情况?仅供参考,我在linux mint 16上使用git版本1.8.3.2。
答案 0 :(得分:3)
有点不寻常,但你的诊断是正确的。
交互式rebase使用一系列git cherry-pick
命令。非交互式rebase使用git-merge-recursive
(默认情况下至少;请参阅git-rebase--merge
目录中的git-core
脚本,无论您的系统位于何处,或只需记下-s <strategy>
git rebase
)的参数,用于从旧的提交中进行每次新提交。正如-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-status
1 来比较可疑提交对来确定。如果这显示bar.js
为D
eleted,foo.js
为R
,bar.js
已广告GIT_EDITOR=: git rebase -i ...
,那就是罪魁祸首。
令人讨厌的是,无法为合并设置重命名阈值。幸运的是,解决方法只是运行交互式rebase并且不对命令系列进行任何更改,您可以通过执行以下操作来简化:
-p
或使用GIT_EDITOR=:
选项来保留合并(如果你有合并,后者是不同的,但是有一个副作用是做一个“隐含的交互式”rebase,它只是设置-M
而且关闭autosquash)。
1 如果您已将diff.renames
配置为true
,则不需要merge.renamelimit
选项(请参阅git config
documentation)。 Merge-recursive在内部设置重命名但不设置复制检测,并将“重命名限制”设置为以下任何一个适用的第一个:您配置的diff.renamelimit
,如果有的话;你的1000
如果有的话;或常数{{1}}。