Git Merge添加新文件而不是冲突标记-CONFLICT(重命名/添加) [英] Git Merge Adds New File Instead of Conflict Markers - CONFLICT (rename/add)

查看:538
本文介绍了Git Merge添加新文件而不是冲突标记-CONFLICT(重命名/添加)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在命令行上运行git merge origin master时,我没有得到通常的冲突标记<<<<<<,而是将冲突文件复制到本地环境中.

这与更改文件夹名称有关吗?

示例:

git fetch origin master && git merge origin master
CONFLICT (rename/add): Rename javascript/main.js->js/main.js in HEAD. js/main.js added in %commit-hash%
Adding as js/main.js~%commit-hash% instead

然后我的本地计算机上有2个文件:js/main.js& js/main.js~%commit-hash%

如何让git给我冲突标记而不是新文件?

&谁能阐明为什么会这样?

  • 注意:出于示例的原因,%commit-hash%只是实际提交哈希的占位符.

解决方案

TL; DR

尝试使用-X find-renames=<value>获得不同的重命名检测.或者,如果那行不通或您不喜欢该方法,请在必要时从存储在索引中的多个阶段中提取所有文件,然后使用git merge-file手动"创建冲突.

这是高级冲突:发生冲突的原因是多个不同文件的名称发生了变化,而不是一个文件中发生的冲突.

Git告诉了您确切的问题所在:

HEAD中重命名javascript/main.js->js/main.js ...

因此,当将当前提交或HEAD提交与您和他们开始的通用合并库进行比较时,Git发现 you 取了javascript/main.js并将该文件重命名为js/main.js

hash

中添加了

... js/main.js

无论他们是谁,都将文件javascript/main.js留在javascript/main.js中,然后创建了一个名为js/main.js new 文件.

因为只能有一个名为js/main.js 文件,所以Git必须做一些特别的事情.不能将您的 js/main.js(您从javascript/main.js重命名)放入js/main.js ,并且不能将新创建的js/main.js更改为js/main.js.因此,将他们的js/main.js放入了js/main.js~hash.

如何让git给我冲突标记而不是新文件?

也许您可以轻而易举地做到这一点,

首先,您必须确定Git对情况的分析是否正确. 是否您将javascript/main.js重命名为js/main.js?而且,他们做了什么 did : did 他们保留了原始的javascript/main.js并添加了一个新的和不同的js/main.js,或者他们实际上是重命名了他们的javascript/main.js只是Git没有意识到这一点,以为他们创建了一个与原始javascript/main.js无关的全新js/main.js?

如果问题是Git错误地检测到两个重命名,则可以尝试调整-X find-renames=<value>设置(在旧版本的Git中命名为-X rename-threshold=<value>).降低数字使Git更愿意将表面上不同的文件视为相同"文件.增大数字会使Git不太愿意将此类文件视为相同",以至于如果将其设置为100%,文件的内容必须完全匹配.

如果是这种情况,并且此过程顺利进行,则您可能会得到所需的内容,不需要任何其他棘手的内容.如果没有,那么:

手工做

如果Git是正确的,并且您的js/main.js确实 被重命名,而他们的js/main.js真正的 是新的,则不建议合并文件.但是,您可以使用git merge-file来执行 操作,该功能适用​​于工作树中的普通文件.首先,您需要将所有三个文件放入您的工作树中:

  • 合并基础版本,最初在合并基础提交中命名为javascript/main.js(无论其哈希ID是什么).
  • 当前提交中名为js/main.js--oursHEAD版本.
  • --theirs版本,也称为js/main.js,但在提交中.

使用Git宣布的两个名称,这三个版本中的两个已经在您的工作树中可用.

索引中的每个文件也应该有一个副本:合并库作为Stage-1条目存在,--oursHEAD版本作为Stage-2条目存在,而 version作为第3阶段条目存在.这意味着您可以使用git showgit checkout-index进行访问. (实际上,您可能可以使用git checkout-idnex --stage=all一次全部获取它们作为临时文件,但是我没有对此进行试验.)由于您仍然需要的是基本版本,因此可以使用:

git show :1:js/main.js > main.js.base

例如,

(假设使用Unix风格的外壳).

一旦在工作树中拥有所有三个文件,就可以运行:

git merge-file <head-version> <base-version> <their-version>

<head-version>中生成文件的冲突标记版本.假设您到目前为止已显示的名称,并将stage-1文件写入js/main.js.base,则应为:

git merge-file js/main.js js/main.js.base js/main.js.~<hash>

When running git merge origin master on the command-line I'm not getting the usual conflict markers <<<<<< but instead conflicting files are being copied down to my local environment.

Could this have something to do with the folder-name being changed?

Example:

git fetch origin master && git merge origin master
CONFLICT (rename/add): Rename javascript/main.js->js/main.js in HEAD. js/main.js added in %commit-hash%
Adding as js/main.js~%commit-hash% instead

Then I have 2x files on my local: js/main.js & js/main.js~%commit-hash%

How can I make git give me conflict markers to work with instead of a new file?

& Can anyone shed some light on why this happens?

  • note: %commit-hash% is just a placeholder for the actual commit-hash for sake of example.

解决方案

TL;DR

Try using -X find-renames=<value> to get different rename detection. Or, if that won't work or you don't like that method, extract all the files from the multiple stages stored in the index if necessary, and then use git merge-file to create the conflicts "by hand".

Long

This is a high level conflict: a conflict that occurs due to multiple different files with changing names, instead of a conflict that occurs within one single file.

Git has told you exactly what the problem is:

Rename javascript/main.js->js/main.js in HEAD ...

So when comparing the current or HEAD commit to the common merge-base from which both you and they started, Git finds that you took javascript/main.js and renamed that file to js/main.js.

... js/main.js added in hash

They, whoever they are, left file javascript/main.js in javascript/main.js, but then created a new file called js/main.js.

Because there can only be one file named js/main.js, Git has to do something special. It can't put your js/main.js (that you renamed from javascript/main.js) into js/main.js and put their newly-created but different js/main.js into js/main.js. So it has put their js/main.js into js/main.js~hash.

How can I make git give me conflict markers to work with instead of a new file?

Maybe you can do this trivially, and maybe not.

First, you have to decide whether Git's analysis of the situation is correct. Did you rename javascript/main.js to js/main.js? And, what did they do: did they keep their original javascript/main.js and add a new and different js/main.js, or did they actually rename their javascript/main.js and it's just that Git didn't realize this and thought they created a totally new js/main.js that was not related to the original javascript/main.js?

If the problem is that Git has mis-detected the two renames, you can try tweaking the -X find-renames=<value> setting (named -X rename-threshold=<value> in older versions of Git). Making the number lower makes Git more willing to treat apparently-different files as "the same" file. Making the number higher makes Git less willing to treat such files as "the same", to the point where if you set it to 100%, the files' contents must match exactly.

If all this is the case and this process goes well, you may get what you want and not need any further tricky bits. If not, well:

Doing it by hand

If Git is correct, and your js/main.js really is renamed while their js/main.js really is new, it may be inadvisable to combine the files. However, you can do this, using git merge-file, which works with ordinary files in the work-tree. First, you will need to get all three files into your work-tree:

  • The merge base version, originally named javascript/main.js in the merge base commit (whatever its hash ID is).
  • The --ours or HEAD version, named js/main.js in the current commit.
  • The --theirs version, also named js/main.js but in their commit.

Two of these three versions are already available in your work-tree, using the two names Git has announced.

There should also be a copy of each file in your index: the merge base is there as a stage-1 entry, the --ours or HEAD version is there as a stage-2 entry, and the --theirs version is there as a stage-3 entry. This means that you can use git show or git checkout-index to get to each. (In fact, you can probably use git checkout-idnex --stage=all to get all of them as temporary files all at once, but I have not experimented with this.) Since the one you still need is the base version, you could use:

git show :1:js/main.js > main.js.base

for instance (assuming a Unix-style shell).

Once you have all three files in your work-tree, you can run:

git merge-file <head-version> <base-version> <their-version>

to produce, in <head-version>, a conflict-marker-ized version of the file. Assuming the names you've shown so far, and writing the stage-1 file to js/main.js.base, that would be:

git merge-file js/main.js js/main.js.base js/main.js.~<hash>

这篇关于Git Merge添加新文件而不是冲突标记-CONFLICT(重命名/添加)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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