Отслеживайте файлы, но исключайте их из пакета git
У меня довольно сложный рабочий процесс. У меня есть две сети с воздушной связью. Я разрабатываю игровые книги в обеих сетях, поэтому у меня есть два независимых хранилища, управляемых git. В то же время большинство сборников можно использовать в обоих местах. Чтобы усложнить дело, это односторонний трансфер. Я могу перевести из сети A в B, но не из B в A.
У меня есть файлы шаблонов с информацией, относящейся к одной сети, но не относящейся к другой. Я разработал его так, чтобы имена файлов были такими же (как и имена переменных в шаблонах Jinja2). Я хочу иметь возможность создавать git-пакет, исключающий файлы, чтобы при извлечении из пакета в хранилище другой сети файлы не перезаписывались. Поскольку включение неверной информации в файлы шаблонов может привести к поломке всей среды, мне нужно отслеживать файлы шаблонов / переменных Jinja2 в Git.
У кого-нибудь есть рекомендации по рабочему процессу или команда git помимо использования.gitignore (потому что файлы должны отслеживаться, чтобы я мог откатиться в чрезвычайных ситуациях), которые помогут мне в этом?
1 ответ
Нет абсолютно тривиального способа сделать это.
По сути, файл отслеживается в Git, если и только если он находится в индексе. Индекс (обычно изначально) заполняется из некоторого коммита, так что это некоторый предыдущий коммит, который определяет, будет ли файл отслеживаться. Предположим, что существуют наборы коммитов T и U, которые похожи, за исключением того, что есть некоторые файлы, не входящие в коммиты U, которые находятся в коммитах T. Затем:
git checkout any-T-sub-i-commit
приводит к тому, что файл (ы) находятся в индексе (и, следовательно, отслеживаются), в то время как:
git checkout any-U-sub-j-commit
приводит к тому, что файл (ы) не входит в индекс (и, следовательно, не отслеживается).
То же самое относится к более общим способам для операций, таких как слияние: когда вы работаете с коммитами из набора T, вы работаете с теми, у которых есть файлы; когда вы работаете с коммитами из набора U, вы работаете с теми, в которых отсутствуют файлы. Если вы объединяете любой коммит T i с любым коммитом U j, то влияние на любой такой файл - будь то добавленный, удаленный или конфликтующий - зависит от того, находится ли фиксация слияния в наборе T или U, и конкретные изменения эти файлы в коммите T i относительно фиксации базы слияния.
Конечно, когда файлы перемещаются в индекс или выходят из него, Git также копирует или удаляет их из рабочего дерева одновременно (с обычной осторожностью, не удаляя несохраненные, но ценные данные). Таким образом, это означает, что файл рабочего дерева исчезнет и появится снова в зависимости от того, извлекаете ли вы T- коммит или U- коммит.
А пока давайте посмотрим, что такое пакет, хотя бы в абстрактном смысле. Суть пакета в том, что он содержит как минимум все данные, которые git fetch
или же git push
послал бы через провод, после git fetch
или же git push
коммуникационный процесс, который служит для минимизации этих данных. (Он может содержать дополнительные данные, которые будут просто игнорироваться.) Эти минимальные данные состоят из всех объектов, которые должны быть скопированы, - аннотированных тегов, фиксаций, деревьев и BLOB-объектов, а также имен ссылок и их значений.
Чтобы исключить некоторый набор файлов из комплекта, вам нужно связывать исключительно U- коммиты, а не T- коммиты. Это нормально, если это так: если вы дублируете все ветви и различаете T коммитов и U коммитов по именам веток, вы можете достичь этого довольно легко. Но следствием этого является то, что каждый раз, когда вы делаете новый T- коммит, вы должны сделать соответствующий U- коммит, и наоборот. Вы удвоили свою рабочую нагрузку.
Стандартная рекомендация, которая применяется к файлам конфигурации в целом, применима и к этому: никогда не фиксировать никакую конфигурацию. Зафиксируйте только образцы или конфигурации по умолчанию или шаблоны. Используйте какую-то оболочку для преобразования этих примеров конфигураций в реальные конфигурации. (Разумеется, обертка также может быть зафиксирована, если вы что-то пишете сами, например, сценарий оболочки или программа на Python или что-то в этом роде.) Теперь вы можете поддерживать и контролировать версию этих примеров / конфигураций по умолчанию. Клонирование репозитория позволяет получить образцы, а обновление из клона - git fetch
с последующим слиянием или перебазированием - обновляет образцы, но не затрагивает фактическую конфигурацию. В зависимости от того, насколько умна оболочка и что доступно в вашем выходном формате, 1 она может даже автоматически обнаруживать, что выборка / ввод по умолчанию изменился, и предупреждать или проваливать любые прогоны, которые используют предписанный инструмент (т.е. саму оболочку), до реальная конфигурация обновляется в соответствии с любыми необходимыми изменениями, исходящими из конфигурации примера / по умолчанию / шаблона.
Это все еще не тривиально - в частности, вам, возможно, придется написать оболочку и обучить пользователей правильному способу запуска вашей конкретной системы. Но это настолько близко к тривиальному, насколько вы, вероятно, достигнете.
1 В данном конкретном случае ваш вывод, скорее всего, представляет собой файлы YAML для ansible. Это означает, что вы можете скрыть все виды полезной информации образца / конфигурации по умолчанию, например, в комментариях.