问题描述
这是来自的简单差异文件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 /
和 dir2 /
部分,但不是 a /
或 b /
部分。即使您没有在 git diff
命令中使用-无前缀
,这仍然是正确的。 / p>
最后, git适用
的 -p1
选项,通常只剥离 a /
和 b /
,现在剥离 dir1 / $ c 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:
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(前导斜杠删除)对重命名不起作用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!