Ртутная очистка хранилища, сохраняющая историю печи / фогбугза
Версия TL;DR: возможно ли реорганизовать репозиторий Mercurial, не нарушая историю Kiln/Fogbuz? Или я должен начать все заново?
У меня есть репозиторий, который представляет собой настоящий беспорядок, нуждается в серьезной очистке, и я пытаюсь выяснить, как лучше всего это сделать. Цель состоит в том, чтобы полностью удалить несколько файлов - они не должны появляться ни в каких фиксациях, никогда - перемещать несколько каталогов и разбивать один каталог на совершенно отдельный репозиторий. Я знаю, я знаю - вы не должны быть в состоянии изменить историю. В этом случае, однако, это либо история изменений, либо начало с нуля с новыми репозиториями.
Рассматриваемое хранилище управляется в Mercurial, а удаленное хранилище размещается в Kiln. Проблемы отслеживаются в Fogbugz. Благодаря некоторым правилам обработки ссылок коммитов любые ссылки в сообщении коммита на номер проблемы (дела), такие как Case 123
преобразуются в ссылки на рассматриваемый случай Фогбугца. В свою очередь, к упомянутому случаю к нему добавляется примечание с сообщением фиксации.
Текущая структура
Структура файла проекта в настоящее время выглядит примерно так:
- /
+- includes/
| +- functions-related-to-abc.php
| +- functions-related-to-xyz.php
| +- class-something.php
| +- classes-several-things.php
| +- random-file.php
| ...
|
+- development/
| +- a-plugin-folder/
| | +- some-file.php
| | +- file-with-sensitive-and-non-sensitive-info.php
| | ...
| |
| +- some-backend-functions-related-to-coding.php
| ...
|
+- index.php
+- test-config-file.php
...
Целевая структура
Структура, которую я хочу, выглядит примерно так:
- /
+- build/
+- doc/
+- src/
| +- functions/
| | +- abc.php // renamed from includes/functions-related-to-abc.php
| | +- xyz.php // renamed from includes/functions-related-to-xyz.php
| | ...
| |
| +- classes/
| | +- something.php // renamed from includes/class-something.php
| | +- several-things.php // renamed from includes/classes-several-things.php
| | ...
| |
| +- view/
| | +- random-file.php // formerly includes/random-file.php
| ...
|
| +- development/
| | +- some-backend-functions-related-to-coding.php
| | ...
| +- index.php
| ...
|
+- test/
...
a-plugin-folder
переехал бы в свое собственное, отдельное хранилище. test-config-file.php
больше не будет отслеживаться в хранилище вообще. В идеале, я также сделаю небольшую обрезку и переименование веток, пока я в этом.
В мире моей мечты, file-with-sensitive-and-non-sensitive-info.php
будет каким-то образом отслеживаться последовательно, но с конфиденциальной информацией (парой паролей) выдернутой в файл конфигурации, который не находится под контролем версий. Я понимаю, что это, вероятно, желаемое за действительное.
Мое текущее мышление
В настоящее время я думаю, что мой список пожеланий в принципе невозможен: с этого момента я могу создавать новые, правильно структурированные репозитории, но не могу сохранить свою историю изменений, а также внести радикальные структурные изменения, которые мне нужно сделать. С этой точки зрения я должен взять текущую кодовую базу, реорганизовать ее так, как я хочу, и зафиксировать ее как changeset 1 для двух новых репозиториев (корневого репозитория и репозитория плагинов). Я бы тогда просто сохранил копию старого репозитория где-нибудь для резервного копирования. Основные недостатки: (1) я теряю всю свою историю, и (2) перекрестные ссылки Килна и Фогбугца на исторические коммиты - это тост.
Мой вопрос
Итак, вот вопрос: есть ли способ сделать то, что я хочу - реструктурировать, вытащить несколько файлов и сделать все красиво, без потери всей моей истории?
Я рассмотрел использование hg convert
расширение, интенсивно используя filemap
, splicemap
, а также branchmap
опции. Проблемы, которые я вижу с этим подходом, включают: (1) нарушение всех предыдущих сборок, (2) отсутствие file-with-sensitive-and-non-sensitive-info.php
в предыдущих сборках вообще (или оставляя его, что побеждает точку), и (3) рендеринг многих из сообщений коммита дико некорректен в той степени, в которой они ссылаются на имена файлов или структуру репо. Другими словами, я не уверен, что этот вариант принесет мне большую пользу, в отличие от простого запуска чистых, правильно структурированных репозиториев.
Я также рассмотрел крайний вариант: написание собственного скрипта для создания нового репозитория путем прохождения каждого существующего коммита, извлечения конфиденциальной информации из file-with-sensitive-and-non-sensitive-info.php
переписывать сообщения коммитов в необходимом объеме и фиксировать исправленную версию всего. Это, теоретически, могло бы решить все мои проблемы, но ценой переосмысления колеса и, вероятно, занимать смешное количество времени. Я ищу что-то, что не эквивалентно написанию всего hg
расширение.
РЕДАКТИРОВАТЬ: я рассматриваю создание пустого хранилища, а затем написание сценария, который использует hg export
а также hg import
вносить наборы изменений по одному за раз, внося изменения, когда это необходимо, для удаления конфиденциальной информации, такой как пароли, из файлов. Есть ли причина, по которой это не сработает?
2 ответа
Я смог достичь своих целей. Вот что я в итоге сделал:
Во-первых, я "выровнял" (выпрямил) репозиторий, удалив все ветви и слияния и превратив репо в одну строку коммитов. Я должен был сделать это, потому что
hg histedit
- ключ ко всей очистке - не работает с историей, содержащей слияния. Это было хорошо для меня, потому что в этом конкретном хранилище не было действительно значимых ветвей или слияний, и в соответствующей истории есть только один автор. Возможно, я мог бы сохранить ветви и слить их снова, если это понадобится позже, но это было проще для моих целей. Для этого я использовалhg rebase
и расширение MQ. (Отдельное спасибо @tghw за этот чрезвычайно полезный ответ, который впервые помог мне понять, как на самом деле работает MQ.)Далее я использовал
hg convert
создать несколько репозиториев из исходного репозитория - по одному для каждой библиотеки / плагина, который мне нужно было поместить в собственный репозиторий, и один основной репозиторий для остальной части кода. В процессе я использовал--filemap
а также--branchmap
реорганизовать все по мере необходимости.В-третьих, я использовал
hg histedit
в каждом новом репозитории (1) очищать ненужные сообщения о фиксации по мере необходимости и (2) удалять конфиденциальную информацию.В-четвертых, я перенес все новые репозитории в Kiln, что автоматически связало их с кейсами FogBugz, используя те же правила, которые были у меня в отношении исходного репозитория (например,
Case 123
в сообщении о фиксации создает ссылку на FogBugz case # 123).Наконец, я "удалил" исходное хранилище в Kiln. На данный момент Kiln действительно и окончательно не удаляет репозитории, хотя я предложил вариант использования, чтобы сделать это возможным. Вместо этого он разделяет дела FogBugz и помещает "удаленный" репозиторий в холодное хранилище; администратор аккаунта может восстановить его, но в противном случае он невидим.
В общей сложности понадобилось около 10 часов, чтобы разбить исходный репозиторий на 6 частей и очистить каждую его часть. Часть этого была кривой обучения; Я мог бы сделать все это за 6 часов, если бы мне пришлось делать это снова. Долгий день, но оно того стоит ради кардинально улучшенной структуры репозитория и очищенного кода.
Сейчас все так, как и должно быть. Надеюсь, это поможет другим пользователям. Пожалуйста, не стесняйтесь оставлять комментарии, если у вас есть похожая проблема, и вы хотели бы получить дополнительную информацию из моего опыта.
Изменить: я в конечном итоге принял подход, отличающийся от описанного ниже. Мой другой ответ объясняет, что я в итоге делал. Тем не менее, я все еще очень заинтересован в плагине, подобном описанному ниже, поэтому я оставляю этот пост для справки, если найду время, чтобы сделать это, или кто-то еще захочет взять проект.
Я решил, что это возможно, используя импорт, экспорт и некоторые исправления в соответствующих точках в истории хранилища.
Алгоритм
Краткая версия алгоритма выглядит следующим образом:
- Создать новый репозиторий
Переберите ревизии существующего репозитория, выполнив следующие действия:
- Экспорт набора изменений из старого репозитория
- Импортируйте набор изменений в новый репозиторий, не фиксируя его
- Внесите необходимые изменения в сообщение фиксации и / или конфиденциальные файлы.
- Зафиксируйте набор изменений в новом хранилище, сохранив (возможно измененное) сообщение о фиксации и другие метаданные.
Поменять старые и новые репозитории
Предостережения:
- Очевидно, что, как и во всех исторических изменениях, это работает только для непубличных репозиториев, которые не были извлечены третьими лицами.
- Шаг 2 может и должен быть в значительной степени автоматизирован для пакетной обработки наборов изменений без редактирования.
- Необходимо будет остановить выполнение всякий раз, когда требуются изменения.
Заставить это работать
У меня есть очень простое доказательство концептуального пакетного файла, который доказывает, что это может работать.
Я работаю над плагином Mercurial, чтобы сделать это как можно проще. Тем не менее, я все еще открыт для лучших предложений, если у кого-то есть.