git diff -M 如何工作?
How does git diff -M work?
我目前正在尝试了解 git diff -M<limit>
的工作原理。
我发现,git diff
通过计算相似度分数来检查两个文件(例如修订版 1 中的 fileA
,修订版 2 中的 fileC
)的相似程度。如果相似度得分 >= limit
,fileA
已重命名为 fileC
,这可能已被修改(如果得分 < 100%)。
然后我问自己,如果目录中有更多具有相同 sha1-hash 的文件怎么办? git
如何知道哪个是重命名(和更改)的版本?
为了找出答案,我尝试了以下方法:
首先,我创建了两个包含 7 行的文件 ("a"、"b"、"c"、"d"、"e"、"f" , "g")
vi fileA
vi fileB
然后我将它们添加到存储库并提交:
git add fileA fileB
git commit -m "Added fileA and fileB"
[master ffc8964] Added fileA and fileB
2 files changed, 6 insertions(+)
create mode 100644 tests/fileA
create mode 100644 tests/fileB
接下来,我使用 git mv
将 fileA
重命名为 fileC
,并删除了 fileB
和 fileC
中的第一行。之后我提交了更改
git mv fileA fileC
vi fileB
vi fileC
git commit -a -m "Renamed and changed files"
[master 57ff82a] Renamed and changed filed
2 files changed, 2 deletions(-)
rename tests/{fileA => fileC} (85%)
fileB
和 fileC
现在看起来像这样:
b
c
d
e
f
g
我现在期望的是 fileB
和 fileC
的校验和相等:
git hash-object fileB fileC
9fbb6235d2d7eb798268d4537acebea297321241
9fbb6235d2d7eb798268d4537acebea297321241
确实是:-)
那么 git diff
现在应该如何知道重命名的文件是什么?由于 fileC 已更改,commit
生成了一个新的 blob,并且 fileC
和 fileA
的校验和也不同(很明显)。
我试过了:
git diff -M80% HEAD master~1
然而,输出让我感到困惑:-(
diff --git a/tests/fileC b/tests/fileA
similarity index 85%
rename from tests/fileC
rename to tests/fileA
index 9fbb623..f9d9a01 100644
--- a/tests/fileC
+++ b/tests/fileA
@@ -1,3 +1,4 @@
+a
b
c
d
diff --git a/tests/fileB b/tests/fileB
index 9fbb623..f9d9a01 100644
--- a/tests/fileB
+++ b/tests/fileB
@@ -1,3 +1,4 @@
+a
b
c
d
显然 git diff
发现 fileA
已重命名为 fileC
。
但是怎么办? git 是否保存了 fileA
和 fileC
之间的某种联系?
没有保存这样的连接。当删除一个文件并添加另一个文件时,可以检测到重命名。 Git 看到 fileC
是新添加的,并检查了所有已删除的文件,看是否可能是重命名。在这里,唯一删除的文件是 fileA
,因此检查速度相当快。
注意:它只需要遍历已删除的文件,否则你不会重命名,你会得到一个副本。副本也可以被检测到,其工作方式大致相同,但它们由单独的选项 (-C
) 涵盖。
我目前正在尝试了解 git diff -M<limit>
的工作原理。
我发现,git diff
通过计算相似度分数来检查两个文件(例如修订版 1 中的 fileA
,修订版 2 中的 fileC
)的相似程度。如果相似度得分 >= limit
,fileA
已重命名为 fileC
,这可能已被修改(如果得分 < 100%)。
然后我问自己,如果目录中有更多具有相同 sha1-hash 的文件怎么办? git
如何知道哪个是重命名(和更改)的版本?
为了找出答案,我尝试了以下方法:
首先,我创建了两个包含 7 行的文件 ("a"、"b"、"c"、"d"、"e"、"f" , "g")
vi fileA
vi fileB
然后我将它们添加到存储库并提交:
git add fileA fileB
git commit -m "Added fileA and fileB"
[master ffc8964] Added fileA and fileB
2 files changed, 6 insertions(+)
create mode 100644 tests/fileA
create mode 100644 tests/fileB
接下来,我使用 git mv
将 fileA
重命名为 fileC
,并删除了 fileB
和 fileC
中的第一行。之后我提交了更改
git mv fileA fileC
vi fileB
vi fileC
git commit -a -m "Renamed and changed files"
[master 57ff82a] Renamed and changed filed
2 files changed, 2 deletions(-)
rename tests/{fileA => fileC} (85%)
fileB
和 fileC
现在看起来像这样:
b
c
d
e
f
g
我现在期望的是 fileB
和 fileC
的校验和相等:
git hash-object fileB fileC
9fbb6235d2d7eb798268d4537acebea297321241
9fbb6235d2d7eb798268d4537acebea297321241
确实是:-)
那么 git diff
现在应该如何知道重命名的文件是什么?由于 fileC 已更改,commit
生成了一个新的 blob,并且 fileC
和 fileA
的校验和也不同(很明显)。
我试过了:
git diff -M80% HEAD master~1
然而,输出让我感到困惑:-(
diff --git a/tests/fileC b/tests/fileA
similarity index 85%
rename from tests/fileC
rename to tests/fileA
index 9fbb623..f9d9a01 100644
--- a/tests/fileC
+++ b/tests/fileA
@@ -1,3 +1,4 @@
+a
b
c
d
diff --git a/tests/fileB b/tests/fileB
index 9fbb623..f9d9a01 100644
--- a/tests/fileB
+++ b/tests/fileB
@@ -1,3 +1,4 @@
+a
b
c
d
显然 git diff
发现 fileA
已重命名为 fileC
。
但是怎么办? git 是否保存了 fileA
和 fileC
之间的某种联系?
没有保存这样的连接。当删除一个文件并添加另一个文件时,可以检测到重命名。 Git 看到 fileC
是新添加的,并检查了所有已删除的文件,看是否可能是重命名。在这里,唯一删除的文件是 fileA
,因此检查速度相当快。
注意:它只需要遍历已删除的文件,否则你不会重命名,你会得到一个副本。副本也可以被检测到,其工作方式大致相同,但它们由单独的选项 (-C
) 涵盖。