Git не удается обнаружить переименование
Одна ветвь (refactoringBranch
) имела полную реструктуризацию каталога. Файлы перемещались хаотически, но содержимое сохранялось.
Я попытался объединиться:
git merge --no-ff -Xrename-threshold=15 -Xpatience -Xignore-space-change refactoringBranch
git статус показывает примерно половину переименования файлов. Но из 10000 файлов в проекте половина не была распознана как перемещенная.
Одним из примеров может быть:
# On branch master
# Changes to be committed:
# deleted: 404.php
# new file: public_html/404.php
...
# deleted: AnotherFile.php
# new file: public_html/AnotherFile.php
...
# renamed: contracts/css/view.css -> public_html/contracts/css/view.css
Предложения?
Предыстория
Рефакторинг был сделан за пределами git. Я сделал следующее:
- Создал
refactoringBranch
, начиная с master
.
- Отбросил измененную структуру внутри
refactoringBranch
, что означало, что у меня были изменения в каком-то другом каталоге и только что скопировали их поверх моего репозитория git.
- Добавлен и зафиксирован все, а затем попытался объединиться.
Это был мой рабочий процесс:
git checkout -b refactoringBranch
cp -R other/place/* ./
git add . -A
git commit -a -m "blabla"
git checkout master
git merge --no-ff -Xrename-threshold=15 -Xpatience -Xignore-space-change refactoringBranch
Вероятно, проблема возникает на шаге git add . -A
.
Потому что, если бы было обнаружено переименование, я бы предположил, что слияние будет безупречным.
Ответы
Ответ 1
Обнаружение переименования:
Мое лучшее предположение заключается в том, что обнаружение переименования терпит неудачу из-за очень большого количества кандидатов. Исходный код git немного трудно отслеживать в местах, но, похоже, существуют некоторые жестко заданные ограничения, используемые в конкретных этапах поиска алгоритма обнаружения переименования (см. diffcore-rename.c
), а также настраиваемый предел максимального количества пар для просмотра (ключи конфигурации diff.renameLimit
и merge.renameLimit
). Это может привести к сбою обнаружения, даже если вы настроили установленный лимит соответственно высоким. Сам настраиваемый предел зажимается до диапазона [1, 32767].
Возможно, вы можете обойти это, выполнив сначала шаг реструктуризации: переместите файлы с помощью git mv без внесения каких-либо изменений содержимого, чтобы соответствовать новому макету, зафиксировать это в новой ветке, а затем заменить его на свою окончательную версию, который должен иметь только изменения содержимого и без переименований. Переименование без изменений содержимого может быть обнаружено более надежно. Это практично, если реструктуризация, которую вы сделали, была довольно простой, и я не уверен, что она решит ошибки обнаружения переименования.
В качестве альтернативы, возможно, вы можете разделить изменения на отдельные коммиты с некоторыми простыми группировками файлов, чтобы в каждой фиксации было меньше кандидатов для определения переименования.
Слияние:
К сожалению, основываясь на новой ветке поверх мастера, вы даете git неверную информацию о слиянии. Независимо от того, правильно ли обнаружены переименования или нет, когда вновь созданная ветка будет объединена с мастером, она перезапишет все в главном, потому что с точки зрения git нет изменений в мастере, которые еще не были включены в новая ветка.
Ответ 2
OS X распознает регистр, но не чувствительна. Git чувствителен к регистру. Если вы изменили имя файла, и единственное изменение было изменением случая, переименуйте файл обратно так, как это было, а затем используйте git mv
для переименования.
Ответ 3
Вместо git status
попробуйте git commit --dry-run -a
, он лучше обнаруживает переименования.
Ответ 4
Вы можете вместо этого использовать git mv
: https://www.kernel.org/pub/software/scm/git/docs/git-mv.html.
По моему опыту это было намного надежнее.
Ответ 5
Вот отличный способ, чтобы git знал, что вы переименовываете файл.
git mv old-file-name.ts new-file-name.ts
Тогда Git подхватит эти изменения.
Наслаждаться.
Ответ 6
Всякий раз, когда мне приходилось переименовывать/перемещать файлы и забывать об этом явно GIT, я использовал
git add . -A
который автоматически обнаруживает файлы, перемещенные вокруг