Co to jest heurystyka git dla przypisywania modyfikacji treści do ścieżek plików?

Krótka wersja:

nie można się nad tym zastanawiaćgitkod źródłowy, gdzie mogę znaleźć pełny opis heurystykigit używa do kojarzenia kawałków treści z konkretnymi śledzonymi nazwami?

Szczegółowa wersja:

W poniższej interakcji demo powłoki (Unix) znajdują się dwa pliki,a ib, są ”git-commit„ted”, a następnie są modyfikowane, aby (efektywnie) przenieść większośćazawartość dobiw końcu oba pliki są ponownie zatwierdzane.

Kluczową sprawą jest to, że wyjście drugiegogit commit kończy się linią

rename a => b (99%)

nawet jeśli nie zmieniła się nazwa plików (w zwykłym znaczeniu) (!?!).

Ten krótki opis przed pokazaniem wersji demonstracyjnej może ułatwić śledzenie.

Zawartość plikówa ib są generowane przez połączenie zawartości trzech plików pomocniczych,../A, ../B, i../C. Symbolicznie, stanya ib może być reprezentowany jako

../A + ../C -> a
../B        -> b

tuż przed pierwszym zatwierdzeniem i

../A        -> a
../B + ../C -> b

tuż przed drugim.

OK, oto demo.

Najpierw wyświetlamy zawartość plików pomocniczych../A, ../B, i../C:

head ../A ../B ../C
# ==> ../A <==
# ...
# 
# ==> ../B <==
# ###
# 
# ==> ../C <==
# =================================================================
# =================================================================
# =================================================================
# =================================================================
# =================================================================
# =================================================================

(Linie zaczynające się od# odpowiadają wyjściu do terminala; rzeczywiste linie wyjściowe nie mają linii wiodącej#.)

Następnie tworzymy plikia ib, wyświetl ich zawartość i zatwierdź je

cat ../A ../C > a
cat ../B      > b
head a b
# ==> a <==
# ...
# =================================================================
# =================================================================
# =================================================================
# =================================================================
# =================================================================
# =================================================================
# 
# ==> b <==
# ###

git add a b
git commit --allow-empty-message -m ''
# [master (root-commit) 3576df7] 
#  2 files changed, 8 insertions(+)
#  create mode 100644 a
#  create mode 100644 b

Następnie modyfikujemy plikia ibi wyświetl ich nową zawartość:

cat ../A      > a
cat ../B ../C > b
head a b
# ==> a <==
# ...
#
# ==> b <==
# ###
# =================================================================
# =================================================================
# =================================================================
# =================================================================
# =================================================================
# =================================================================

Na koniec zatwierdzamy zmodyfikowanea ib; zanotuj wyjściegit commit:

git add a b
git commit --allow-empty-message -m ''
# [master 25b806f] 
#  2 files changed, 2 insertions(+), 8 deletions(-)
#  rewrite a (99%)
#  rename a => b (99%)

Zracjonalizowałem to zachowanie w następujący sposób.

Tak jak rozumiem,git traktuje informacje o strukturze katalogów (takie jak nazwy ścieżek śledzonych plików) jakowtórny informacje - lub metadane, jeśli chcesz - aby być powiązane zpodstawowa informacje, które śledzi, a mianowicie różne fragmenty treści.

Ponieważ zarówno zawartość, jak i nazwy (w tym nazwy ścieżek) plików mogą się zmieniać między zatwierdzeniami,git musi używać heurystyk do powiązania nazw ścieżek z kawałkami treści. Jednak heurystyki z natury nie gwarantują 100% czasu pracy. Niepowodzenie takiej heurystyki przybiera tutaj postać historii, która nie wiernie reprezentuje to, co faktycznie się wydarzyło (np. Zgłasza zmianę nazwy pliku, nawet jeśli nazwa pliku nie została zmieniona, w zwykłym znaczeniu).

Kolejnym potwierdzeniem tej interpretacji (mianowicie, że niektóre heurystyki są w grze) jest to, że AFAICT, jeśli rozmiar przeniesionego fragmentu nie jest wystarczająco duży, wynikgit commit nie będzie zawieraćrewrite/rename kwestia. (Na końcu tego posta zamieszczam demonstrację tego przypadku, FWIW.)

Moje pytanie brzmi: brak przejazdugitkod źródłowy, gdzie mogę znaleźć pełny opis heurystykigit używa do kojarzenia kawałków treści z konkretnymi śledzonymi nazwami?

To drugie demo jest identyczne z pierwszym pod każdym względem, z wyjątkiem pliku pomocniczego../C jest o jeden wiersz krótszy niż wcześniej.

head ../A ../B ../C
# ==> ../A <==
# ...
# 
# ==> ../B <==
# ###
# 
# ==> ../C <==
# =================================================================
# =================================================================
# =================================================================
# =================================================================
# =================================================================

cat ../A ../C > a
cat ../B      > b
head a b
# ==> a <==
# ...
# =================================================================
# =================================================================
# =================================================================
# =================================================================
# =================================================================
# 
# ==> b <==
# ###

git add .
git commit -a --allow-empty-message -m ''
# [master (root-commit) a06a689] 
#  2 files changed, 7 insertions(+)
#  create mode 100644 a
#  create mode 100644 b

cat ../A      > a
cat ../B ../C > b
head a b
# ==> a <==
# ...
# 
# ==> b <==
# ###
# =================================================================
# =================================================================
# =================================================================
# =================================================================
# =================================================================

git add .
git commit -a --allow-empty-message -m ''
# [master 87415a1] 
#  2 files changed, 5 insertions(+), 5 deletions(-)

questionAnswers(2)

yourAnswerToTheQuestion