Суть решения будет заключаться в использовании инструмента / метода, который автоматизирует массовое переименование.Вы можете использовать mv в сочетании с git add или просто git mv .В любом случае вам, возможно, придется предпринять дополнительные шаги, если вы используете нечувствительную к регистру файловую систему.Поэтому, прежде чем приступить к массовому переименованию, может быть полезно обсудить, как немного обрабатывается регистр.
Чувствительность к регистру
Некоторые системы (или комбинации система + файловая система - как вариант по умолчанию дляФайловая система HFS + в Mac OS X *) сохраняет регистр, но не учитывает регистр.В таких системах вам может потребоваться быть осторожным при создании переименований, которые включают только изменение регистра имени.Обычный обходной путь заключается в использовании временного имени, которое отличается более чем просто регистром, в качестве «моста» между двумя именами, которые отличаются только регистром (например, mv foo.JPG tmp && mv tmp foo.jpg
).
* Это возможноиспользовать чувствительные к регистру файловые системы в Mac OS X (включая регистрозависимый вариант HFS +).
С этого момента я буду считать файловую систему без учета регистра.
* * 1022Команда * mv в Mac OS X может обрабатывать переименования только с учетом регистра за один шаг.При запуске с параметром -i
он выдаст запрос «перезаписать?» И пропустит переименование, если указан параметр -n
.Он только успешно выполняет стандартную операцию «достаточно веревки, чтобы повеситься» во многих частях Unix-подобных систем.
Команда git mv немного более параноидальна в этой ситуации.Он отклоняет операцию (ошибка «пункт назначения существует»), если не указан параметр -f
/ --force
.
# this will succeed, though it may fail/prompt if mv is aliased to use -n/-i
mv foo.JPG foo.jpg
# this will succeed
mv -f bar.JPG bar.jpg
# this will succeed but give a warning
git mv -f quux.JPG quux.jpg
Параметры массового переименования
Переименование Perl
Требуемыйоперация достаточно проста, чтобы выполнить ее с помощью небольшого количества сценариев оболочки, но вы можете получить утилиту Perl rename (которую упоминает Джордан Льюис), если вам нужно сделать что-то более сложное.Вы можете попробовать переименовать из пакета Debian perl , или, если вы хотите использовать CPAN, вы можете установить File :: Rename , которая включает в себя программу rename .
ksh , bash , zsh , dash
-ef
, используемый ниже, не совместим с POSIX.Аналогично, хотя -e
указано в POSIX, оно не является чисто Bourne-совместимым.Оба они широко поддерживаются.
for f in *.JPG; do
ff="${f%.JPG}.jpg"
test -e "$f" || continue # possible when not using nullglob
test "$f" != "$ff" || continue # possible when using nocaseglob
if test -e "$ff" &&
! test "$f" -ef "$ff"; then # possible on a case sensitive filesystem
echo "skipping <$f>: destination <$ff> exists and is distinct" 1>&2
continue
fi
# "mv" with "git rm" and "git add"
mv -f "$f" "$ff" &&
git rm --cached "$f" &&
git add "$ff"
done
Последний раздел ( mv , git rm , git add ) можно заменитьпросто git mv :
# "git mv"
git mv -f "$f" "$ff"
Если вы очень обеспокоены тем, как может произойти сбой переименования в системах без учета регистра, вы можете использовать временное имя:
# temp-based "mv" with "git rm" and "git add"
t="$ff.tmp"; while test -e "$t"; do t="$t.tmp"; done
mv -n "$f" "$t" &&
mv -n "$t" "$ff" &&
git rm --cached "$f" &&
git add "$ff"
Или с git mv :
# temp-based "git mv"
t="$ff.tmp"; while test -e "$t"; do t="$t.tmp"; done
git mv "$f" "$t" &&
git mv "$t" "$ff"
zsh / zmv
Это нужно -f
для обоих zmv и git mv .
zsh -c 'autoload zmv && $0 $@' zmv -fp git -o 'mv -f' '(*).JPG' '$1 x.jpg'
Теперь, когда все они переименованы и обновлены в индексе Git, вы можете их зафиксировать.
Но смогут ли другие пользователи Git, использующие файловые системы, чувствительные к регистру, проверить их?
проверка git После переименования только для регистра
Если естьдругие пользователи вашей истории, вероятно, все еще будут иметь файлы JPG
, и когда они в конечном итоге получат (потомок) ваш коммит с файлами jpg
.Что с ними будет?
Независимо от того, что произойдет, нет необходимости «переименовывать в temp, commit, переименовывать в final, commit». git checkout не применяет коммиты в последовательности при переходе между коммитами.Это действительно работает путем «слияния» индекса и рабочего дерева из HEAD в новый коммит.Это фактически означает, что он «переходит» непосредственно к новому коммиту, перетаскивая несогласованные изменения, обнаруженные между HEAD и индексным / рабочим деревом.
Внутренне Git просматриваетимена как удаление и дополнение. Я не нашел никакой документации, описывающей поведение git checkout относительно порядка удалений и добавлений, поэтому я посмотрел на исходный код. git checkout обрабатывает все удаления перед любыми обновлениями / добавлениями (cmd_checkout -> switch_branches -> merge_working_tree (-> reset_tree) -> unpack_trees -> check_updates ).
Вы можете проверить это сразу после переименования:
git checkout HEAD~ # note: detached HEAD
# verify that the original names are back in place
git checkout - # back to your branch
# verify that the new names are in place again
Казалось, что git blame в файле указывает на вероятную фиксацию: Сделать распакованное дерево обновлять удаленные файлы перед любыми обновленными файлами , который впервые был выпущен в Git 1.5.6- rc0 (2008-06-18). Таким образом, хотя это недокументированное (?), Это поведение было реализовано специально для поддержки нечувствительных к регистру файловых систем.
Спасибо, Линус!