2016-11-29 9 views
1

Я хочу конвертировать окончание Windows/смешанной строки в историю репозитория git предприятия в окончание строк Unix, используя git filter-branch. Поскольку репозиторий содержит некоторые типы двоичных файлов определенного домена, файл .gitattributes достаточно проработан, поэтому я предпочел бы использовать собственный механизм git для преобразования EOL вместо сценариев dos2unix, таких как here.git filter-branch и gitattributes

мне удалось выполнить преобразование с использованием процедуры, которые я описал в https://github.com/cnaj/demo-crlf-rewrite/tree/so-question, а именно, чтобы сделать дерево-фильтр который добавляет .gitattributes, а затем выполняет git reset. Без сброса история останется неизменной. Однако, по-видимому, индекс по-прежнему находится в редакции HEAD во время операций фильтра, поэтому распознаются только файлы, которые изменены в отношении HEAD, и только эти файлы преобразуются в соответствии с .gitattributes (следовательно, фиксация «NUKE» в демо).

Мои вопросы:

  1. Является ли эта процедура безопасна для использования, или это просто случайный результат незарегистрированной (или непонятой) поведение?
  2. Что такое индекс git во время tree-filter операция? Могут ли команды, которые изменяют индекс, использовать в tree-filter (я не нашел явной документации по этой теме)?
  3. Вопрос с бонусом: что именно заставляет git забирать линии, завершающие конверсии в этой настройке? (У меня трудно понять, что происходит ...)

ответ

0

Из моего собственного опыта после получения torek's answer:

является ли эта процедура безопасна для использования, или это просто случайный результат незарегистрированного (или непонятых) поведения?

Эта процедура должна быть безопасной для использования в чувствительной к регистру POSIX-файловой системе. Однако его можно было бы упростить (см. https://github.com/cnaj/demo-crlf-rewrite).

Что такое индекс git в течение Дерево-фильтр операция? Могут ли команды, которые изменяют индекс, использовать в tree-filter (я не нашел явной документации по этой теме)?

Да.С каждым шагом tree-filter устанавливает индекс в содержимое текущей версии и проверяет его на временный каталог. После запуска фильтра различия между индексом и рабочей копией продвигаются в индекс, который затем становится новой версией.

Вопрос с бонусом: что именно заставляет git собирать линии, завершающие конверсии в этой настройке? (У меня трудно понять, что происходит ...)

Хотя фильтр-ветви задает индекс для каждой версии, которая обрабатывается, HEAD остается в первоначальной редакции, где фильтр-филиал был начат. Таким образом, команда git reset HEAD имела эффект удаления каждого файла из индекса. После этого все файлы считаются измененными, и индекс обновляется соответствующим образом, вызывая преобразование EOL в процессе.

0

Это:

Однако, по-видимому, индекс по-прежнему в ревизия во время операции фильтра, поэтому только те файлы, которые изменены по отношению к ГОЛОВАМ ...

совершенно неверно, но, к сожалению, эта проблема сложна.

Давайте начнем с основным фактом, что git filter-branch произведения копирования каждый фильтруются совершают (и аннотированный тегом, если с помощью --tag-name-filter). Если результирующая копия бит-бит-бит идентична исходной фиксации, копия завершается с тем же идентификатором хэша, и, следовательно, является оригиналом, в очень реальном смысле. В противном случае это новый фиксатор и заменяет первоначальную фиксацию.

Индекс Git играет несколько разных ролей, хотя основной из них - «построить следующую фиксацию». Следовательно, индекс действительно изменяется, так как git filter-branch выполняет итерацию по каждой исходной фиксации для ее копирования. Однако ...

а именно сделать дерево-фильтр который добавляет .gitattributes, а затем выполняет сброс GIT.

... есть проблема здесь. Если вы посмотрите на the filter-branch code, вы увидите, что он запускает git update-index в конце запуска фильтра дерева. Он не запускается git add, поэтому он зависит от результатов команд git diff-index и git ls-files.Все это делается во временном каталоге, который переопределяет нормальное рабочее дерево.

Здесь мы сталкиваемся в края моей личной Гит-фу :-) потому git add и т.п. вызова кода атрибута (в беличьей пути, с помощью функции unpack_trees, которая вызывается непосредственно из builtin/reset.c, и косвенно вызывается из diff_cache как вызванный от run_diff_index или index_differs_from для других) таким образом, который соответствует файлу .gitattributes в дереве. Однако представляется, что git update-index не (это основано на вашем собственном наблюдении, что ваши атрибуты не применяются).

К счастью, существует вероятное обходное решение. Если вы явно указали git add .gitattributes (вместо, или, возможно, прежде, если необходимо, запустите git reset или, возможно, еще один git checkout-index), который должен получить новый файл в индекс. Затем, если git update-index использует индексированную версию вместо временного древовидного файла (как представляется, на основе источника), он будет использовать тот, который вы намеревались использовать.

Последний:

Что именно вызывает мерзавца подобрать окончание строки преобразования в этой ситуации?

Это не очень хорошо документировано, и путь кода здесь, если вообще, еще сложнее.

В основном, все фильтры, включая преобразования текста/CRLF, применяются в двух точках: при перемещении файлов «из» из индекса в дерево работы или при перемещении файлов «в» с рабочего дерева на индекс.

Индекс также, однако, имеет ряд stat данных и флагов, так что Git только даже смотреть на (гораздо меньше копии в или из) файлов, которые, как представляется, скорее всего, будет отличаться в дереве, чем в индексная версия.

В индексе есть отдельный флаг, чтобы пометить файлы «грязные». Этот флаг устанавливается, когда фильтр изменяет файл во время проверки. Так как нет .gitattributes на начальном checkout, грязный флаг здесь не будет установлен. (Но существование этого флага делает любой файл, который делает фильтруется, гораздо медленнее работать. Таким образом, используя множество атрибутов делает Git гораздо медленнее, победив умный индекс кэширования.)

+0

Мне потребовалось некоторое время, чтобы обработать ваш комментарий :-) Спасибо, что указали мне на источник git! Действительно, 'git update-index' действительно вызывает преобразование атрибута, что происходит в' sha1_file.c': 'index_path()'. Файл атрибутов считывается из дерева работ. Однако 'diff-index' в' git-filter-branch.sh' не получает никаких изменений до тех пор, пока 'git reset' не станет эффективно индексировать все файлы, и в этот момент' update-index' делает преобразование , Выглядит вполне безопасно для меня, но завтра я попробую его в большом хранилище ... – tcernaj