Получение Git для просмотра переименованных и отредактированных файлов
Вопросы о переименовании файлов в Git имеют спросил, но я не могу решить решение моей конкретной проблемы.
Я переместил и отредактировал несколько файлов (я не использовал git mv
- к сожалению, сейчас слишком поздно для этого). Теперь я хочу так, когда мой коллега вытащит из моего репозитория, внеся свои собственные изменения в те же файлы (без их перемещения), он успешно объединяет мои изменения с ним в новом месте файла. Чтобы успешно объединиться, Git явно должен знать, что это одни и те же файлы.
Является ли Git достаточно умным, чтобы справиться с этим самостоятельно? Кажется, трудно поверить. И если да, то как я могу быть уверен, что конкретный ход файла будет поднят на Git - даже если содержимое изменилось?
Ответы
Ответ 1
Git фактически не отслеживает переименования в репозитории, он использует эвристику diff, чтобы определить, переименован ли файл в другой. То есть, если вы git mv
файл и затем полностью замените его, он не считается переименованием, и вам не нужно использовать git mv
для обнаружения переименований.
Например:
% mv d.txt e.txt
% git rm d.txt
rm 'd.txt'
% git add e.txt
% git commit -m"rename without git mv"
[master f70ae76] rename without git mv
1 file changed, 0 insertions(+), 0 deletions(-)
rename d.txt => e.txt (100%)
% git diff --summary --find-renames HEAD~1 HEAD
rename d.txt => e.txt (100%)
Аналогично, git mv
не означает, что файл будет переименован, он все равно будет использовать алгоритм diff:
% git mv e.txt f.txt
% echo "Completely replacing f.txt" > f.txt
% git add f.txt
% git commit -m"git mv doesn't help here"
[master 068d19c] git mv doesn't help here
2 files changed, 1 insertion(+), 14 deletions(-)
delete mode 100644 e.txt
create mode 100644 f.txt
% git diff --summary --find-renames HEAD~1 HEAD
delete mode 100644 e.txt
create mode 100644 f.txt
Ответ 2
По умолчанию git будет проверять наличие переименований всякий раз, когда файл был удален между коммитами - нет необходимости указывать его вручную. Если вы действительно перемещаете файл (с git mv, а не вручную удаляя его и добавляя его снова), он игнорирует подсказку. По соображениям производительности эвристика не работает все время - если вы перемещаете файл в сторону, а затем добавляете новый с исходным именем, этот ход не может быть обнаружен.
Обратите внимание, что логически git сохраняет только дерево, как оно существовало в каждой ревизии: оно не хранит информацию отслеживания изменений, внесенных между версиями.
Если вы хотите увидеть, что обнаружено, вы можете использовать переключатель -M
(--find-renames
) в git diff
для отображения переименований. Этот переключатель также включает эвристику, которая полезна, если у вас есть фиксация, которая не вызывает их.
Этот эвристический подход является хорошей причиной (если вам нужен другой), чтобы сохранить мелкие и автономные комманды, поскольку это облегчает работу git.
Ответ 3
git diff
не собирал, что я переименовал файлы и изменил их содержимое. Мой сценарий состоял в том, что у меня были файлы A, B, C и вставлен новый B, поэтому старый B теперь был C, а старый C теперь D. git diff
говорил мне, что B и C теперь совершенно разные!
Решение, которое я использовал, было утомительным и ручным, но выполнило эту работу.
- Переименовал файлы, насколько мог. То есть B в Bnew, от C до B, от D до C.
- Был ли diff, чтобы не проверять ошибок.
- Согласен с этим.
- Используется
git mv
, чтобы вернуть файлы к новым именам. B - C, C - D.
- Согласен с этим.
- Другой переименовал и перенял их как новые файлы. То есть Bnew to B.