Como o git detecta arquivos semelhantes, por sua detecção de renomeação?

A Wikipedia explica a detecção automática de renomeação:

Resumidamente, dado um arquivo na revisão N, um arquivo com o mesmo nome na revisão N − 1 é seu ancestral padrão. No entanto, quando não há um arquivo com nomes semelhantes na revisão N − 1, o Git procura por um arquivo que existia apenas na revisão N − 1 e é muito semelhante ao novo arquivo.

A detecção de renomeação aparentemente se resume a detecção de arquivo semelhante. Esse algoritmo é documentado em algum lugar? Seria bom saber que tipos de transformações são detectados automaticamente.

Git rastreia o conteúdo do arquivo, não nomes de arquivos. Então, renomear um arquivo sem alterar seu conteúdo é fácil para o git detectar. (O Git não rastreia, mas executa a detecção ; usar git mv ou git rm e git add é efetivamente o mesmo.)

Quando um arquivo é adicionado ao repository, o nome do arquivo está no object da tree. O conteúdo real do arquivo é adicionado como um object binário grande ( blob ) no repository. O Git não adicionará outro blob para arquivos adicionais que contenham o mesmo conteúdo. De fato, o Git não pode como o conteúdo é armazenado no sistema de arquivos com os dois primeiros caracteres do hash sendo o nome do diretório e o restante sendo o nome do arquivo dentro dele. Então, para detectar renomea é uma questão de comparar hashes.

Para detectar pequenas alterações em um arquivo renomeado, o Git usa certos algoritmos e um limite para ver se isso é uma renomeação. Por exemplo, dê uma olhada no sinalizador -M para git diff . Há também valores de configuração, como merge.renameLimit (o número de arquivos a serem considerados ao executar a detecção de renomeação durante uma mesclagem).

Para entender como o git trata arquivos similares (isto é, quais transformações de arquivo são consideradas como renomeações), explore as opções de configuração e os sinalizadores disponíveis, como mencionado acima. Você não precisa ser considerado com o como. Para entender como o git realmente realiza essas tarefas, observe os algoritmos para encontrar diferenças no texto e leia o código-fonte do git.

Algoritmos são aplicados apenas para propósitos de diff, merge e log – eles não afetam como o git os armazena. Qualquer pequena alteração no conteúdo do arquivo significa que um novo object é adicionado para ele. Não há delta ou diff acontecendo nesse nível. É claro, mais tarde, os objects podem ser empacotados onde os deltas são armazenados em arquivos de pacotes, mas isso não está relacionado à detecção de renomeação.

Existem muitos algoritmos que detectam semelhanças entre os textos e os sistemas de version control costumam usá-los para armazenar apenas a diferença entre duas versões. Ferramentas como o WinMerge são inteligentes o suficiente para detectar diferenças, mesmo dentro de linhas, então não vejo razão para que esses algoritmos não sejam usados ​​para essa detecção de renomeação.

Aqui está uma discussão sobre algoritmos para detectar textos semelhantes . Alguns desses algoritmos podem ser otimizados para linguagens naturais, enquanto outros podem funcionar melhor para o código-fonte, mas em essência eles são muito parecidos.