git apply -p(前导斜杠删除)对重命名不起作用吗? [英] Does git apply -p (leading slash removal) not work for renames?

查看:135
本文介绍了git apply -p(前导斜杠删除)对重命名不起作用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是来自的简单差异文件git diff --no-index --no-prefix dir1 dir2> dir.diff

  diff --git dir1 / file1.txt dir2 / file1.txt 
索引45b983b..ce01362 100644
--- dir1 / file1.txt
+++ dir2 / file1.txt
@@ -1 +1 @@
-hi
+ hello
diff --git dir1 / file2.txt dir2 / file2_rename.txt
相似性索引100%
从dir1 / file2.txt
重命名为dir2 / file2_rename。 txt
差异--git dir1 / file3.txt dir1 / file3.txt
删除文件模式100644
索引b1a17ba..0000000
--- dir1 / file3.txt
+++ / dev / null
@@ -1 +0,0 @@
-zzz
diff --git dir2 / file4.txt dir2 / file4.txt
新文件模式100644
索引0000000..f761ec1
--- / dev / null
+++ dir2 / file4.txt
@@ -0,0 +1 @ @
+ bbb

如您所见,file1.txt被修改,file2.txt被重命名,file3删除.txt,并添加file4.txt。


现在,当我尝试应用补丁时:

  cp -r dir1 dir_work 
cd dir_work
git apply -v ../dir.diff

我明白了以下详细输出,表明修补程序在file2重命名时失败:(修补程序在没有file2的情况下完美运行)

 正在检查修补程序file1.txt ... 
正在检查补丁dir1 / file2.txt => dir2 / file2_rename.txt ...
错误:dir1 / file2.txt:没有这样的文件或目录
正在检查修补程序file3.txt ...
正在检查修补程序file4.txt ...

因此,对于file1,file3,file4,前导目录( dir1 /... dir2 /...)被剥离了( -p1 git应用默认),但不用于重命名?如何删除文件2的前导目录?

解决方案

此处的问题是检测文件重命名的代码以及旧名称和新名称使用以下两行:


 从dir1 / file2.txt重命名
重命名为dir2 / file2_rename.txt


其中包括 dir1 / dir2 / 部分,但不是 a / b / 部分。即使您没有在 git diff 命令中使用-无前缀,这仍然是正确的。 / p>

最后, git适用 -p1 选项,通常只剥离 a / b / ,现在剥离 dir1 / other 差异行中的$ c>和 dir2 / ,但对这两行没有任何作用。在内部, git apply 剥离的前缀比 git apply 的前缀少:

 静态整数gitdiff_renamesrc(struct gitdiff_data * state,
const char * line,
struct patch * patch)
{
patch-> ; is_rename = 1;
free(patch-> old_name);
patch-> old_name = find_name(状态->根,行,NULL,
状态-> p_value?状态-> p_value-1:0,0);
返回0;
}

不使用 git diff -无前缀 git适用-p2 ,因此Git会删除 one 这两个名称中的组件。因此,在 apply 步骤上使用 -p2 而不是可能会有所帮助。 -prefix 放在 git diff 命令上。


Here is a simple diff file from git diff --no-index --no-prefix dir1 dir2 > dir.diff:

diff --git dir1/file1.txt dir2/file1.txt
index 45b983b..ce01362 100644
--- dir1/file1.txt
+++ dir2/file1.txt
@@ -1 +1 @@
-hi
+hello
diff --git dir1/file2.txt dir2/file2_rename.txt
similarity index 100%
rename from dir1/file2.txt
rename to dir2/file2_rename.txt
diff --git dir1/file3.txt dir1/file3.txt
deleted file mode 100644
index b1a17ba..0000000
--- dir1/file3.txt
+++ /dev/null
@@ -1 +0,0 @@
-zzz
diff --git dir2/file4.txt dir2/file4.txt
new file mode 100644
index 0000000..f761ec1
--- /dev/null
+++ dir2/file4.txt
@@ -0,0 +1 @@
+bbb

As you can see, file1.txt is modified, file2.txt is renamed, file3.txt is deleted, and file4.txt is added.

Now when I try to apply the patch:

cp -r dir1 dir_work
cd dir_work
git apply -v ../dir.diff

I get the following verbose output, indicating the patch failed on file2 rename: (patch works perfectly without file2)

Checking patch file1.txt...
Checking patch dir1/file2.txt => dir2/file2_rename.txt...
error: dir1/file2.txt: No such file or directory
Checking patch file3.txt...
Checking patch file4.txt...

So for file1, file3, file4, the leading directories (dir1/... and dir2/...) were stripped (-p1 is git apply default), but not for the rename? How can I strip the leading directory for file2?

解决方案

The problem here is that the code that detects the file rename, and the old and new names, uses the two lines:

rename from dir1/file2.txt
rename to dir2/file2_rename.txt

which as you can see include the dir1/ and dir2/ parts, but not an a/ nor b/ part. This would still be true even if you hadn't used --no-prefix in the git diff command.

In the end, git apply's -p1 option, which would normally strip just a/ and b/, is now stripping dir1/ and dir2/ from the other diff lines, but does not do anything with these two lines. Internally, git apply strips one fewer prefixes than git apply does in general:

static int gitdiff_renamesrc(struct gitdiff_data *state,
                             const char *line,
                             struct patch *patch)
{
        patch->is_rename = 1;
        free(patch->old_name);
        patch->old_name = find_name(state->root, line, NULL,
             state->p_value ? state->p_value - 1 : 0, 0);
        return 0;
}

Using git diff without --no-prefix and git apply -p2, Git will thus strip one component from these two names. So it may help to use -p2 on the apply step, instead of --no-prefix on the git diff command.

这篇关于git apply -p(前导斜杠删除)对重命名不起作用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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