Как записать всю историю git файла, который переименован / перемещен, используя его старый путь? - PullRequest
1 голос
/ 25 марта 2019

Если файл, A, редактируется один или несколько раз, затем переименовывается / перемещается в B и редактируется один или несколько раз как B, выдавая следующую команду git с использованием его нового имени / пути..

git log --follow -- B

... показывает всю историю.

Тем не менее, когда я смотрю на старую (выпущенную / поддерживаемую) ветвь того же проекта, где файл все еще называетсяA и я хочу зарегистрировать изменения, внесенные в него в master, я мог бы подумать, что выдача следующего на master ...

git log --follow -- A

... покажет мне все изменения.Но это не так.Последняя фиксация, отображаемая в журнале, - это изменение, соответствующее переименованию с A на B.Изменения, внесенные в B, не отображаются.

т.е. --follow следует только после переименования «назад» из более нового имени в более старое, но не «вперед».

На данный моментЯ должен сначала определить, что последний отображаемый коммит - это переименование, найти новое имя и снова ввести git log --follow с новым именем (и, возможно, повторить это несколько раз, если файл перемещался несколько раз с момента сохранениярелиз.

Как найти всю историю, не выпуская вручную несколько раз git log --follow?

1 Ответ

2 голосов
/ 25 марта 2019

К сожалению, git log сам строго работает в обратном направлении , как Git всегда делает.Git буквально не может работать вперед, потому что то, что Git сохранил , равно назад: каждый коммит запоминает хэш-идентификатор своего родительского коммита, но, поскольку все коммиты замораживаются во времени, когда они создаются, они не могут запомнить хеш-идентификаторыих детей, которые были созданы позже.

Что git log (и что-то вроде команды старшей сестры / рабочей лошадки git rev-list) может сделать это один раз сделать обратный обход, вычисляяиз того, какие коммиты идут раньше других, затем выведите в обратном порядке.Команда git log --reverse делает это.Но, увы, обнаружение переименования происходит только во время обратного (который Git является вперед) обхода и не может быть втиснуто в более позднюю распечатку вперед (который Git является назад).

Это не встроено в Git, но выможно использовать git rev-list, чтобы выполнить сторнирование, сохранить результат, а затем выполнить собственную прогулку вперед, выполняя git diff --name-status для каждой пары коммитов в поисках операций переименования.Обратите внимание, что это все еще немного сложно, так как теперь ветви действительно разветвляются, а слияния действительно объединяются - во внутреннем обратном обходе Git происходит слияние ветвей, а слияния ветвятся.:-) Предположим, у нас есть:

  tag:abc
     |
     v
...--o--o--*--o--o--o   <-- tip1
         \
          o--*--o----o   <-- tip2

Вы хотите начать с тега abc, который находится слева, и "работать вперед".Git хочет начать с tip1, фиксация вправо вдоль верхней строки или с tip2, фиксация вправо в нижней строке.

коммиты, отмеченные * переименовывают ваш файлA на какое-то новое имя.В том, что вверху, новое имя B, а в том, что внизу, новое имя C.

. Если вы начинаете Git с tip2, вы должны искать C,Git замечает переименование в * и с тех пор налево ищет A.Если вы запускаете Git с tip1, вы должны искать B, таким же образом.

Если вы создали листинг «вперед», переходя назад от tip1 к некоторой точке перед тегомabc, все будет в порядке: в этом списке нет ответвлений, поскольку ни один из коммитов, ведущих к tip2, не включен.Но затем предположим, что кто-то добавляет слияние к tip1 и еще один коммит:

  tag:abc
     |
     v
...--o--o--*--o--o--o--M--o   <-- tip1
         \            /
          o--*--o----o   <-- tip2

Теперь путь от abc до tip1 включает оба переименовывает.Если вы начинаете с tip1, вы должны дать git log --follow имя, которое тот, кто слил, решил сохранить, будь то B или C.Поскольку git log -- B или git log -- C (в зависимости от того, какое имя подходит) делает упрощение истории , Git собирается пройти только одну из двух ног позади M - либо верхнююили в нижнем ряду, в зависимости от того, какой файл имеет соответствующий файл - и когда вы работаете вперед с abc, вам придется выбрать одну из двух ветвей для совместной работы или сделать что-то необычное, чтобы вызнать, чтобы проверить на A -получает- B вдоль вершины , а также проверить на A -попад- C вдоль дна .(Git ничего необычного не делает.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...