这是我之前提出的另一个问题的后续。
在编辑之前,最初创建的文件something
被重命名为somethingelse
,可以在此处观察到:
git mv something somethingelse
然后,文件somethingelse
然后在第二个VIM编辑之前将其重命名为something
:
git mv somethingelse something
基本上在代码的以下部分中:
# If you add something to the first line, the rename will not be detected by Git
# However, if you instead create 2 newlines and fill line 3 with new code,
# the rename gets detected for whatever reason
printf "nCOMMAND: vim somethingnn"
vim something
如果此时我将abc
添加到代码中,我们最终会以:
First line of code. abc
我认为这是第1行上的4个字节的添加,而这将最终出现:
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: something
deleted: somethingelse
那么,如果我们在第三行中添加新线并输入ABC(也应该是4个字节,请纠正我,如果错了):
First line of code.
abc
突然,git将检测重命名(编辑包含):
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: somethingelse -> something
@torek的一个很好的答案/评论在一定程度上解释了这一点,请考虑git diff
重命名检测git status
的treshold。
由于我们在两种情况下都添加了4个字节,但Git不应该表现出色,但是以不同的方式添加了4个字节,或者Newline与此有关?
git的"相似性索引"据我所知,计算没有记录在源以外的任何地方,从diffcore-delta.c。
开始要计算两个文件的相似性索引 s (source)和 d (目标),git:
- 读取两个文件
- 计算文件的所有块的哈希表 s
- 计算文件的所有块的第二个哈希表 d
这两个哈希表中的条目只是该哈希值实例的发生数量(另外,如下所述,块的长度)。
文件块的哈希值由:
计算- 从当前文件偏移(最初为零) 开始
- 读取64个字节或直到
'n'
字符,以先到者为准 - 如果文件被称为文本,并且在
'n'
之前有一个'r'
,请丢弃'r'
- 哈希使用链接文件中显示的算法
现在有两个 s 和 d 的哈希表,每个可能的哈希 h i i 出现<<em> s 和 n n time>(尽管代码都超过了零哈希值,但要么零)。如果 d 中的发生数量小于或与 s - i.e。, n n d ≤中的发生数量相同或相同n s - 然后 d d s s ; n d 时间。如果 d 中的出现数量超过 s 中的数字(包括 s 中的数字为零),则/em>具有"字面添加" n d - n s 出现哈希德块的出现, d 也复制了所有 n n s 原始出现。
每个hashed块保留其输入数字,并且这些块将副本数量或添加数量乘以"块"的添加数量。要获取复制或添加的字节。(删除,其中 d 缺少 s 中存在的项目,在这里仅具有间接效果:字节副本和添加计数变小,但GIT并未具体计算删除本身。)
在diffcore_count_changes
中计算的这两个值(src_copied
和literal_added
)已移交给diffcore-rename.c
中的函数estimate_similarity
。它完全忽略了literal_added
计数(此计数用于决定如何构建PackFile Deltas,但在重命名评分方面不使用)。相反,仅src_copied
数字很重要:
score = (int)(src_copied * MAX_SCORE / max_size);
其中 max_size
是两个输入文件中较大的字节中的大小 s 和 d 。
请注意,有一个较早的计算:
max_size = ((src->size > dst->size) ? src->size : dst->size);
base_size = ((src->size < dst->size) ? src->size : dst->size);
delta_size = max_size - base_size;
以及两个文件已更改 size '太多:
if (max_size * (MAX_SCORE-minimum_score) < delta_size * MAX_SCORE)
return 0;
我们甚至从未进入diffcore-delta.c
代码来哈希。minimum_score
这是转换为缩放数字的-M
或--find-renames
的参数。MAX_SCORE
是60000.0
(类型double
),因此,当您使用默认的-M50%
时,默认的minimum_score
为30000(60000的一半)。不过,除了cr-be-be-be-be-be-be饮食外,这种特殊的快捷方式不应影响更昂贵的相似性计算的结果。
[编辑:现在已经过时了:] 直到GIT版本2.18.0,无法控制git status
始终使用默认值。没有旋钮可以更改阈值(也没有重命名的订阅队列中允许的文件数)。如果有代码将进入此处,请设置DIFF选项的rename_score
字段。git status
。在GIT 2.18.0及以后,git status
具有与git diff
相同的--find-renames
选项。GIT配置中的status.renames
选项可实现任何默认检测,如果未设置,则git status
遵守diff.renames
设置;请参阅git config
文档和git status
文档。