Применить автоматическое преобразование файлов (преобразование), начиная с прошлой ревизии, сохраняя историю
Для данного проекта (над которым я сейчас работаю исключительно) я бы хотел применить определенное автоматическое преобразование для некоторых файлов. Для этого обсуждения, давайте предположим, что я хочу изменить окончания строк со стиля Windows на стиль Unix для всех текстовых файлов. Я хочу, чтобы новый формат был эффективным, начиная с определенного пересмотра в прошлом, и проникал в историю.
Обычно я делаю следующее: я запускаю интерактивный ребаз и добавляю следующее после каждого коммита, начиная с желаемой начальной точки:
exec <transformation rule>
exec git commit -m "transform" && git revert --no-edit HEAD
Это приводит к transform
с последующей последовательностью оригинальных коммитов, каждый из которых окружен revert
а также transform
с последующим финалом revert
, Затем я выполняю вторую интерактивную ребазу и раздавливаю все тройки revert
-<original commit>
-transform
и удалите последний revert
, Первый transform
остается на месте, все остальные transform
а также revert
совершает исчезновение.
Этот ручной процесс дает (почти) желаемый результат (я не уверен насчет дат принятия новых коммитов), но мне было интересно, возможно ли автоматизировать это с помощью filter-branch
, fast-import
или, возможно, пользовательский инструмент, который я пропустил при беглом поиске.
1 ответ
Скорее всего filter-branch
это то, что вы хотите в этом случае.
Обновите немного больше объяснений: когда вы выполняете искажение источников, которые вы описали выше (когда я прочитал это полностью, я действительно хотел похвалить вашу изобретательность!), Вы должны рассмотреть данную серию коммитов, последовательность изменений, переходов, Вот почему вы должны ввести поддельные возвраты, которые вы должны раздавить при следующем взаимодействии. Таким образом вы избегаете конфликтов, и это больше всего восхищало меня.
В отличие от этого git filter-branch
дает другой "взгляд" на ту же последовательность фиксации. Каждый коммит в последовательности считается состоянием, а не переходом. И фильтр, который вы предоставляете, изменяет само состояние. Таким образом, вам вообще не нужно думать о конфликтах, они просто не могут прийти. Но, безусловно, вы должны применять одно и то же преобразование к каждому коммиту в последовательности.
Итак, ответ на ваш конкретный вопрос: если вы хотите преобразовать переводы строк из DOS в UNIX, вам просто нужно выполнить команду, подобную этой:
git filter-branch --tree-filter 'find . -type f -print0 | xargs -0 perl -pi -e "s,\r\n,\n,;"' HEAD
perl -pi -e 's,\n,\r\n,;'
это команда, которая делает преобразование, find
а также xargs
это метод для сбора всех файлов в текущем каталоге и передачи их perl
, Обратите внимание, что git
имеет свою магию CRLF (см. man git-config
за core.autocrlf
, core.safecrlf
а также .gitattributes
файл) и обычно вам не нужно обрабатывать CRLF вручную, правильной конфигурации достаточно для создания хранилища, подходящего как для Windows, так и для Unix-подобных систем.