Короткий ответ - просто "нет". :-) По сути, вы должны запустить git log --follow
и найти изменение имени самостоятельно, если вообще можете его найти, а затем вручную использовать правильное имя.
Настоящая проблема здесь заключается в том, что каждый коммит является полным, но независимым снимком всех ваших файлов:
Commit 9620e34
содержит один файл, a.txt
. Это все, что у него есть. У него нет b.txt
. (Ну, у него могут быть другие файлы, которые не являются ни a.txt
, ни b.txt
; из вышеизложенного я не могу сказать, так ли это.)
Commit 13973ff
имеет полную (но другую) копию a.txt
.
Commit cb4ce19
имеет полную копию b.txt
и a.txt
вообще не существует. Копия b.txt
в cb4ce19
соответствует 100%, копия a.txt
в 13973ff
, но это два разных имени файла.
Последний коммит, 45c5d11
, имеет полную (но различную) копию b.txt
.
Когда вы используете git log
, git log
выполняет проход по коммитам, один коммит в время, начинающееся там, где вы сейчас находитесь (или где вы указываете) и работающее в обратном направлении. При желании он может сравнивать каждый коммит со своим (единственным) родителем, 1 с родительским коммитом слева и дочерним коммитом справа. Сравнение двух снимков - diff - выдает в качестве выходных данных рецепт: Выполните эти действия, и вы измените файлы левого снимка так, чтобы они соответствовали файлам правого снимка. Обычно это довольно близко к тому, что кто-то на самом деле делал, или даже к тому, что он делал. Иногда это совсем не то, что они делали, но он выдает тот же результат .
С --name-status
, git log
печатает только имя файла и букву состояния, а не полный рецепт. 2 Если в рецепте указано «переименовать этот файл», вы получите R
букву и индекс сходства (в процентах): 100 означает совпадение файлов, 100% идентичные слева и справа стороны. Этот тип соответствия намного быстрее, чем приблизительный, поэтому, когда вы делаете переименование, не изменяя также и содержимое файла, как в этом случае, будет приятно Git. (Иногда было бы неплохо, если бы Git было к вам лучше.)
Добавление опции --follow
включает Git обнаружение переименования механизм. Он может включаться или не включаться для других операций - вы можете настроить git diff
для управления этим, например, при запуске git diff
без указания -M
, чтобы включить его вручную, но это гарантирует, что он включен для этого особый вид git log
. Для поиска переименований необходимо запустить детектор переименования. Детектор переименования является вычислительно дорогим (хотя и гораздо менее подходящим для 100% совпадений), поэтому git log
операции, которые ему не нужны, обычно вообще не используют его.
Однако реализация --follow
, довольно неряшливо: внутренне Git отбирает каждый коммит до одного интересующего файла в дочернем коммите, а затем сравнивает этот файл с его аналогом в родительском коммите. Если файл не в родительском файле, Git вызывает детектор переименования для этого одного файла (а не для всех файлов, как обычно), чтобы проверить, может ли он найти соответствующий -content-but-Different-name в родительском файле. 3 Если это так, он просто меняет имя , которое ищет, сообщая вам об этом переименовании. С этого момента, помните, git log
работает в обратном направлении - он начинает искать старое имя вместо нового.
Когда вы используете git show
, вы указываете напрямую к некоторому коммиту . Он не попадает туда, начиная с последнего коммита и работая в обратном направлении, как это делает git log
. Он начинается прямо с коммита, который вы называете. У этого коммита есть родительский идентификатор ha sh (хранится в метаданных коммита), поэтому git show
может git diff
родитель и потомок, если вы используете его как git show <hash>
; эта фиксация имеет моментальный снимок, и git show
может извлечь и отобразить один файл, если вы используете его как git show <hash>:<path>
. Но он не пошел назад от коммита, в котором вы сейчас находитесь, к указанному вами коммиту, поэтому он не знает, может ли приведенный здесь path
соответствовать какому-то другому, path
в указанном вами коммите.
Git, вероятно, должна иметь команду для отслеживания имени файла: вы бы указали ему необязательную начальную точку, по умолчанию HEAD
, a имя пути и целевой коммит; и это даст результат выполнения эквивалента git log --follow
для этого имени и обнаружения переименований до достижения цели, или выдаст ошибку - или, возможно, просто выведет исходный путь - если он никогда не достигнет этого целевого коммита. Это была бы полезная сантехническая команда. (Вероятно, он также должен иметь несколько путей, и детектор переименования git log
должен быть расширен и использован для реализации этой команды.) Но он не существует.
1 Когда git log
достигает коммита слияния , который, по определению, является одним с двумя или более родителями, git log
обычно просто вообще не выполняет никакого сравнения. При использовании --follow
он несколько меняет стратегии, но --follow
плохо работает при слияниях.
2 Он также фактически находит изменения, выходящие за рамки того, что необходимо чтобы получить письмо о статусе, так как поиск рецепта изменения медленный.
3 При просмотре слияний я не уверен что детектор переименования делает. У него есть все родители, но код здесь очень короток и труден для подражания. В любом случае есть только одна глобальная переменная, содержащая имя, за которым следует подпись, поэтому, если имя отличается у двух разных родителей, код буквально не может обработать это правильно, для любого разумного определения «правильно».