В проекте присутствует файл super.config. В нем содержатся много разных настроек проекта. Например, конфигурация взаимодействия со сторонним сервисом и уровень логирования. Система контроля версий — git.
В чем проблема:
- Этот файл должен находиться под версионным контролем, так как в нем содержатся «общие» настройки. Ну и сама структура файла ценна.
- Каждый разработчик меняет уровень логирования под свои нужды и не хочет, чтобы эти изменения попадали в коммиты, и тем более в интеграционный репозиторий.
- В этом файле периодически меняются общие настройки, и разработчик хочет их получать (pull) и публиковать (commit)
Возможные решения:
- Хранить исходные тексты приложения и его настройку отдельно. Но жизнь боль, и не всегда это можно сделать. Причины на это разные: от технических до (
некомпетентных людей) административных. - Пошаманить с загрузкой конфигурации. Например, под версионным контролем хранить default.super.config, а super.config исключить. Приложение должно сначала грузить свойства из default.super.config, а потом, если он есть, из super.config. Причем значения из последнего перекрывают значения из дефолтного.
- Просто не добавлять изменения локального конфига в индекс.
Плюсы:
- Простота.
- Если нужно закоммитить изменения в конфиге, то это делается по фрагментно (git add -p).
Минусы:
- Не сделаешь git add.
- Постоянно «маячат» какие-то изменения. Разработчик каждый раз их анализирует, проверяя все ли закоммитил.
- Переключение (checkout) на ветку с другим конфигом возможно только с ключом -m или через stash (ключ -f убивает изменения в рабочей копии).
- Pull изменений конфига приводит к ошибке. Прежде чем получить изменения, локальные придется убрать на полку.
Исключить конфиг из-под версионного контроля.
Не сработает. Только untracked файлы можно исключать из-под версионного контроля.
- Убедить git, что файл конфига не меняется. Как это сделать:
git update-index --assume-unchanged super.conf
Плюсы:
- git add . не добавит лишнего.
- «Чистый» статус.
Минусы:
- Git не сможет переключиться на ветку с другим конфигом, получить или закоммитить изменения конфига. При этом сообщения в консоли могут вводить в заблуждение: git status пишет «nothing to commit, working directory clean», а git pull — «Your local changes to the following files would…».
Для того чтобы разрешить эту ситуацию, придется открыть git глаза обратной командой git update-index --no-assume-unchanged super.conf. И все равно, далее придется воспользоваться полкой. - Посмотреть, на что git закрывает глаза можно командой git ls-files -v | grep -e "^[hsmrck]" (не, ну все же понятно).
Как бы поступил я:
Если конфиг меняется крайне редко, то --assume-unchanged выглядит подходящим решением. Иначе просто не обращал бы внимания на изменения.
А вообще, надо хранить настройки отдельно.
Ресурсы по теме
Комментарии (10)
poxu
29.09.2015 15:42Я не совсем понял, чем вас не устраивает второй вариант.
AShushunov
29.09.2015 16:29Как я писал выше (http://habrahabr.ru/post/267927/#comment_8595311), не всегда дело ограничивается конфигами.
Есть еще случаи, когда нельзя просто так взять и изменить способ загрузки конфигов на живом проекте, которому > 10 лет.
dMetrius
29.09.2015 16:50>>Не сработает. Только untracked файлы можно исключать из-под версионного контроля.
Ваша неправда:
git rm --cached filename
и после этого добавляем его в .gitignoreAShushunov
29.09.2015 17:00Так git rm убирает файлы из-под версионного контроля.
И как после этого быть с требованием:
«В этом файле периодически меняются общие настройки, и разработчик хочет их получать (pull) и публиковать (commit)»
viatoriche
29.09.2015 18:48+1Мы храним все конфиги в системе управления конфигурацией (у нас ansible). Конфигурация (куча yaml файлов и jinja шаблонов) версионируется гитом, настроены разные хосты, роли, плейбуки, разная конфигурация для vagrant, production, test-server, local-development, remote-development и так далее. Нам нравится.
Starche
Я обычно решаю эту проблему несколькими конфиг файлами.
1) Глобальный общий конфиг, который трогают только тогда, когда надо внести изменения глобально. Например, там могут храниться глобальные константы, вычисляемые пути к файлам, и т.п. (global.conf)
2) По конфигу на каждый сервер/среду где разворачивается приложение (dev.conf, prod.conf...). Обычно как раз тут живут уровни логирования, уровни кэширования, наличие/отсутствие минификации файлов (если речь о веб-проекте), и прочие радости.
3) Конфиг локального компьютера. Добавлен в гитигнор. В Readme проекта записаны правила его создания. (local.conf). Можно также добавить файл-пример, который на самом деле конфигом не является (local-sample.conf). В локальном определяется подключаемый конфиг среды, а также вносятся локальные настройки (например доступ к базе данных, хранилищу кэша, и т.п.)
При этом конфиги «наследуются». Т.е. конфиг среды частично перезаписывает глобальный конфиг, а конфиг локального компьютера перезаписывает конфиг среды. (global->dev->local). Так обеспечивается естественное желение разработчика потестить под разными уровнями логирования/кэширования и т.п.
JIghtuse
Самый адекватный подход, я считаю. Гибкий и понятный.
Подобными слоями устроены настройки в дистрибутивах Linux; в том же git.
AShushunov
К сожалению, дело не всегда ограничивается конфигами. Я работал на проекте, в котором для сборки на локальной машине надо было менять pom-файл (описание сборки проекта для maven). Это и было одной из предпосылок для этого поста.