2

У нас есть довольно большая база кода, включающая около 60000 коммитов. Мы хотим переформатировать все наши .java-файлы, сохраняя при этом историю git. Таким образом, подход, который мы использовали, - использовать фильтр-ветвь git -tree-filter для переформатирования всей базы кода, сохраняя при этом историю неповрежденной. Но есть несколько вопросов, на которые я не могу найти ответ.Реформат всей кодовой базы с git rewrite

  1. Когда я применяю --tree-фильтр и передать команду, которая переформатирует все файлы .java в корневом каталоге, то переписывание происходит, но в самом конце, я вижу все файлы .java в промежуточной области. Требуется ли фиксация на каждом этапе перезаписи или происходит автоматически?

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

  3. В целях переформатирования всей кодовой базы будет работать -index-filter?

UPDATE: Разъяснения

  • код базы составляет около 2,2 миллионов строк кода Java. Не делать переписку git может привести к тому, что примерно 10% -12% кодовой базы будет отнесено к неправильному автору. Это около 200 тыс. Строк кода Java, чего мы хотим избежать. Git rewrite заставляет его выглядеть так, как человек, внесший изменения, сделал это правильно.
+0

Непонятно, что вы подразумеваете под «в конце ... все файлы .java [находятся] в промежуточной области». Команда фильтра-ветви заканчивается, по существу, проверкой отфильтрованного результата, поэтому, конечно, область промежуточного этапа не пуста, если только фильтр не пуст. – torek

+0

Из любопытства, какой инструмент переформатирования вы планируете использовать? Джалопи или что-то еще? –

+0

Инструмент, с которым мы договорились, заключается в том, чтобы вызывать форматирование кода Eclipse (на самом деле исправленная версия его как последняя имеет ошибки, которые не сработают для нас) из [командной строки] (http://blogs.operationaldynamics.com/андрей/программное обеспечение/Java-гном/затмение-код формата, из-командной строки). Это немного медленнее, но каждый другой инструмент, который мы рассматривали в какой-то проблеме, что делает его неосуществимым для нас. – Karthik

ответ

1

Re 1: --tree-filter не требует отдельной фиксации: она просто выводит дерево, соответствующее некоторые совершают во временный каталог, запускает свой фильтр, а затем принимает результирующий каталог как новое дерево для нового коммита , Все изменения, в том числе созданные или удаленные файлы, приводят к другому «новому» фиксации, а в качестве примечаний к странице руководства, .gitignore и всем другим правилам игнорирования используются , а не (поэтому, если вы создаете файл .bak или что-то еще, и, как правило, просто .gitignore его, вы должны удалить его вручную в свой древовидный фильтр).

Вся эта работа выполняется в подкаталоге базы данных «rewrite» базы данных git, которую вы можете установить с помощью -d, но по умолчанию используется значение .git-rewrite. (Подкаталог для фильтров - все из них, включая фильтр дерева, - это $tempdir/t, но это не должно быть релевантным.) Это также делается со специальным временным индексом (область промежуточной области) ($tempdir/index).

Обратите внимание, что весь временный каталог удаляется к моменту выхода git filter-branch.


Re 2: Да, это возможно, чтобы сохранить чтобы быть фильтрованной ID, это в $ GIT_COMMIT (переменная окружения,) на протяжении всех серий фильтров. (Так как фильтры в основном eval ed, вы можете даже изменить среду, чтобы передать дополнительные переменные или изменить их, см. Скрипт ветвления фильтра).


Re 3: По существу, разница между --index-filter и --tree-filter что --tree-filter извлекает дерево во временный каталог, запускает свой фильтр, а затем сворачивается (потенциально модифицированное) дерево, чтобы сделать новое дерево для нового совершить. В отличие от этого, --index-filter загружает дерево в индексный файл; запускает ваш фильтр, который может изменять индекс; затем использует полученный индекс для создания нового дерева для нового коммита.

Иными словами, фильтр дерева фактически распаковывает и переупаковывает индекс. Вот почему индексный фильтр работает быстрее: он пропускает шаг unpack/repack. Если вы должны изменить фактические файлы, гораздо проще просто распаковать их все, изменить все и переупаковать их все. Вы могли бы получить некоторую скорость, если многие файлы не будут изменять, распаковывая только интересные, модифицируя их и переупаковывая измененный результат, но для этого вам нужно иметь довольно мелкие знания уровня git низкого уровня. (Это легко git checkout и git add каждый файл, как вы идете, но вы также должны выяснить, какие файлы должны быть изменены.)

1

Как автор the BFG (быстрее, проще альтернатива git-filter-branch), я расположен к упомянуть об этом, хотя это не из-за-коробки - переформатирование Java-источника.

Вы упомянули, что возобновление после отказа для операции ветвления git-фильтра будет полезно, и это, конечно, связано с тем, что ветвь git-фильтра настолько медленная. Операция no way to resume a git-filter-branch - но если бы это было быстрее, это не было бы такой большой проблемой. BFG может быть many hundred times faster, чем ветвь git-filter, поскольку он только очищает любую заданную версию файла один раз - в отличие от git-filter-branch, который каждый раз очищает один и тот же файл, каждый фиксация.

BFG поддерживает прямую замену текста в файлах, но, как я уже сказал, он не переформатирует Java-источник. Там будет два варианта получения, что для работы:

  1. Призовите BFG, как библиотеки, так как Christian Hoffmeister recently did - в вашем случае, переходящая в обычае TreeBlobModifier, который вызывает Jalopy или какой-либо другой Java исходного форматирования кода.
  2. Измените BFG так, чтобы он поддерживал обход, чтобы вызывать произвольные команды bash - немного как git-filter-branch--tree-filter или --index-filter - но все же я ожидал бы, скорее, быстрее.

Вариант 2 не будет таким сложным в реализации. Тем не менее, мне интересно, можете ли вы рассказать о том, почему вы хотите принять эту радикальную историю перезаписи? Есть ли действительно существенная польза от того, чтобы иметь совершенно отформатированную историю, по сравнению с хлопотами переписывания, и заставить всех адаптироваться к изменившейся истории? Почему бы просто не сделать одноразовое переформатирование вашей последней фиксации?

+0

Внутренне, мы пошли туда и обратно о том, нужно ли нам переписывать git или нет. Мы придумали много цифр и не выполнили переписывающий способ, чтобы неправильно относить 10% -12% кодовой базы к неправильному автору, и, следовательно, переписать это наш единственный вариант. – Karthik

+0

Я слышал много о BFG и рассматривал его в какой-то момент, но единственное, что меня останавливало, это то, что он не обрабатывал древовидный фильтр, который, как мне кажется, нам нужен здесь. – Karthik

+0

Нет способа «из коробки» возобновить ветвь фильтра, но теоретически это можно сделать (скопируйте скрипт фильтра-ветви, взломайте его совсем немного и т. Д. :-)). Это, вероятно, не было сделано, потому что переписывание истории болезненно, даже если все работает отлично. – torek