In che modo git tiene traccia del codice sorgente spostato tra i file?

Apparentemente, quando spostate una funzione da un file di codice sorgente a un altro, il registro di revisione di git (per il nuovo file) può mostrare da dove proveniva originariamente quel frammento di codice (vedere ad esempio la sezione Cronologia di visualizzazione in questo tutorial ).

Come funziona?

Non li tiene traccia. Questa è la sua bellezza.

Git registra solo istantanee dell’intero albero del progetto: ecco come apparivano tutti i file prima del commit ed ecco come appaiono dopo. Come siamo arrivati ​​da qui a lì, a Git non interessa.

Ciò consente di scrivere strumenti intelligenti dopo che è già avvenuto un commit, per estrarre informazioni da quel commit. Ad esempio, il rilevamento del nome in Git viene eseguito confrontando tutti i file eliminati con tutti i nuovi file e confrontando le metriche di similarità a coppie. Se la metrica di somiglianza è maggiore di x , vengono considerate rinominate, se è compresa tra y e x ( y < x ), è considerata una modifica + modifica, e se è inferiore a y , sono considerate indipendenti. La cosa bella è che tu, come "commettere archeologo", puoi specificare dopo il fatto, quale dovrebbe essere x e y . Questo non funzionerebbe se il commit registrasse semplicemente "questo file è un rinominare di quel file".

Rilevare i contenuti spostati funziona in modo simile: taglia ogni pezzo in pezzi, calcola le metriche di somiglianza tra tutte le fette e puoi quindi dedurre che questa fetta che è stata cancellata qui e questa fetta molto simile che è stata aggiunta là sono in realtà la stessa fetta che è stata spostata da qui a lì.

Tuttavia, come menzionato da Tonfa nella sua risposta, questo è molto costoso, quindi non è normalmente fatto. Ma potrebbe essere fatto, ed è questo il punto.

BTW: questo è praticamente l'esatto contrario del modello di Operational Transformation utilizzato da Google Wave, EtherPad, Gobby, SubEthaEdit, ACE e Co.

È puramente euristico. Confronta la distanza tra i file e cerca di trovare i blocchi corrispondenti. Ma questa euristica viene implementata solo quando il codice viene copiato o spostato in un nuovo file (altrimenti sarebbe troppo costoso, controllando ogni coppia di file).