Применить автоматическое преобразование файлов (преобразование), начиная с прошлой ревизии, сохраняя историю

Для данного проекта (над которым я сейчас работаю исключительно) я бы хотел применить определенное автоматическое преобразование для некоторых файлов. Для этого обсуждения, давайте предположим, что я хочу изменить окончания строк со стиля 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-подобных систем.

Другие вопросы по тегам