2016-06-05 2 views
0

Когда вы меняете две версии, как я могу сделать git правильно следовать истории, где был заменен файл?Как сделать git правильно diff замененным файлом

Вот пример. Я создаю файл [commit], перемещаю его [commit], затем создаю другой файл с тем же именем [commit].

echo "original" > test.txt 
git add . 
git commit -m "First commit" 
mv test.txt test2.txt 
git add --all . 
git commit -m "Rename" 
echo "replace" > test.txt 
git add . 
git commit -m "Replace" 

Когда сравниваете между HEAD^^ и HEAD, как я могу сделать мерзавец понимать, что test.txt действительно новый файл? Лучшая команда, которую я мог найти, была чем-то вроде git diff -M100% -C100% HEAD^^, но это не дает результаты, которые я ищу.

git diff -M100% -C100% HEAD^^ 
diff --git a/test.txt b/test.txt 
index 4b48dee..6e8b374 100644 
--- a/test.txt 
+++ b/test.txt 
@@ -1 +1 @@ 
-original 
+replace 
diff --git a/test.txt b/test2.txt 
similarity index 100% 
copy from test.txt 
copy to test2.txt 

Есть ли лучшая команда для получения ожидаемого результата?

diff --git a/test.txt b/test.txt 
index 4b48dee..6e8b374 100644 
--- /dev/null 
+++ b/test.txt 
@@ -0,0 +1 @@ 
+replace 
diff --git a/test.txt b/test2.txt 
similarity index 100% 
copy from test.txt 
copy to test2.txt 

ответ

1

К сожалению, нет. Git всегда выполняет эвристическое обнаружение переименования и, по крайней мере, в настоящее время, независимо от пути родословной, который можно вычислить из DAG совершения, когда вы даете git diff, две коммиты просто сравнивают их напрямую. В этом случае он сравнивает HEAD^^ против HEAD, и оба имеют test.txt, а второй - test2.txt, поэтому его эвристика говорит, что, хотя test2.txt может быть или не быть копией какого-либо другого файла, test.txt не переименовывается.

(При сравнении HEAD^^ против HEAD^, нет в HEAD^ нет test.txt, поэтому его код обнаружения переименования будет увидеть, если возможно test2.txt соответствует предыдущей test.txt. Следовательно, если она сканируется по родословной пути, ведущего от HEAD^^ через HEAD^ к HEAD, его текущая эвристика будет обнаружить переименование, но это не так. Или, если бы у Git была возможность сделать сравнительное сравнение O (n) между всеми файлами, а не только те, у которых нет аналогов на «стороне» diff, который также мог бы открыть переименование, но опять же это не так.)

+0

Большое спасибо за прямой и сквозной ответ! Это заставляет меня задаться вопросом, сделал ли кто-нибудь скрипт либо пройти историю, либо провести дорогостоящее сравнение. – m35

+1

Майкл Хаггерти написал «git-imerge» как скрипт, который может выполнять итеративное слияние или переадресацию, которая обрабатывает историю при выполнении этих операций. Однако у него свои проблемы. См. Http://softwareswirl.blogspot.com/2013/05/git-imerge-practical-introduction.html. – torek

Смежные вопросы