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.