试图理解``git diff''和`git mv'重命名检测机制



这是我之前提出的另一个问题的后续。

在编辑之前,最初创建的文件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_copiedliteral_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_SCORE60000.0(类型double),因此,当您使用默认的-M50%时,默认的minimum_score为30000(60000的一半)。不过,除了cr-be-be-be-be-be-be饮食外,这种特殊的快捷方式不应影响更昂贵的相似性计算的结果。

[编辑:现在已经过时了:] git status始终使用默认值。没有旋钮可以更改阈值(也没有重命名的订阅队列中允许的文件数)。如果有代码将进入此处,请设置DIFF选项的rename_score字段。直到GIT版本2.18.0,无法控制git status。在GIT 2.18.0及以后,git status具有与git diff相同的--find-renames选项。GIT配置中的status.renames选项可实现任何默认检测,如果未设置,则git status遵守diff.renames设置;请参阅git config文档和git status文档。

相关内容

  • 没有找到相关文章