Рабочий процесс git для проекта с открытой и проприетарной (частной) частью
Плагин Wordpress с бесплатной и PRO-версией. PRO версия содержит дополнительные файлы, разбросанные по базе кода.
Какова оптимальная стратегия для отслеживания обеих версий в git, удовлетворяющая следующим ограничениям:
- бесплатная версия с открытым исходным кодом на GitHub, принимающая участие;
- PRO версия синхронизирована с приватным репозиторием;
- локальная разработка происходит в версии PRO (например, для рефакторинга для работы);
- обе истории связаны (история PRO ⊇ бесплатно)
- низкие эксплуатационные расходы:
- мы мерзавцы,
- нет ручного учета того, что файл подходит, где.
Существует множество плагинов для Wordpress, которые следуют этой дихотомии "бесплатно против PRO". Как они версированы?
1 ответ
На ум приходит несколько простых подходов...
Отдельное пространство имен
Переместите все разбросанные файлы в отдельный каталог пространства имен, например./pro, в который вы клонируете отдельный PRO-репозиторий, содержащий только PRO-файлы. Недостаток: проверки в двух репозиториях должны быть синхронизированы (т. Е. Если вы переключаетесь на старый коммит в одном репо, вам всегда нужно также переключаться на совместимый коммит в другом репо).
Два хранилища
Это, я полагаю, так обычно и делается. Поддерживайте бесплатные и PRO версии в двух разных репозиториях. Пусть репозиторий PRO определит общедоступный удаленный источник для получения и объединения изменений.
cd ~/project-libre
git remote add origin GITHUB_PUBLIC_REPO
cd ~/project-pro
git remote add origin PRIVATE_REPO
git remote add libre GITHUB_PUBLIC_REPO # to fetch and merge changes from
Всякий раз, когда в общедоступный репозиторий вносятся изменения, вы можете объединить их с вашей PRO-версией с помощью:
cd ~/project-pro
git checkout master
git pull libre master --allow-unrelated-histories
git push origin master
Всякий раз, когда есть изменения в версии PRO, которые вы хотите синхронизировать с опубликованной бесплатной версией, вы можете использовать git-format-patch
экспортировать изменения в виде файлов исправлений, а затем на другом конце импортировать этот набор исправлений, исключая любые файлы, которые не публикуются в бесплатной версии. Вот так:
cd ~/project-pro
git checkout master
git format-patch HEAD~3..HEAD # Export e.g. last three commits as patches
Теперь переключитесь на бесплатную версию и примените патчи (с git-am
), исключая из каждого коммита все файлы PRO (пути), которые находятся в списке игнорирования для бесплатной версии. Я помещаю их в файл .gitignore здесь в свободном корне проекта, и командная строка предполагает, что оболочка POSIX доступна (повторяется --exclude
параметр для каждого файла / пути в.gitignore).
cd ~/project-libre
git checkout master
git am $(printf -- '--exclude=%s ' $(cat .gitignore)) ~/project-pro/*.patch
Две ветви
Есть две ветви, каждая из которых синхронизируется с другим пультом.
git remote add origin GITHUB_PUBLIC_REPO
git remote add private PRIVATE_REPO
Создайте два файла, один бесплатный и один PRO:
touch free1 pro1
В основной ветке создайте.gitignore, содержащий все файлы PRO
git checkout master
echo 'pro*' > .gitignore
git add .gitignore
git commit -m 'Add .gitignore ignoring PRO files'
Синхронизируйте публичную ветку с публичным репозиторием:
git push -u origin master
Теперь ветвь master в частную ветку PRO и очистите.gitignore, так как там не игнорируются файлы PRO.
git checkout --branch master-private
echo > .gitignore
git commit .gitignore -m 'Clear .gitignore -- track all files here'
Синхронизировать частную ветку с частным хранилищем:
git push -u private master-private
Теперь добавьте файлы free1 и pro1 в соответствующие ветки:
git checkout master
git add free1
git commit -m 'Add free1'
git checkout master-private
git add pro1
git commit -m 'Add pro1'
И объедините master с master-private, чтобы он содержал полный набор.
git checkout master-private
git merge master
Вам нужно разрешить один конфликт.gitignore (или вы можете указать -X ours
переключатель слияния).
Позже вы сделаете некоторую разработку для ветки master-private (§ 3), ретуши и создания различных файлов, которые поместятся в любую из двух веток:
git checkout master-private
touch free2 pro2
echo xxx > free1
echo xxx > pro1
Вы не хотите перечислять все не-PRO файлы для фиксации (§ 5.2); для этого у вас есть.gitignore. Вы используете его, переключаясь на мастер и фиксируя все, что подходит, затем переключаясь обратно на мастер-приват, фиксируя то, что остается. Сначала необходимо сохранить изменения, так как они будут перезаписаны путем переключения ветвей.
git stash
git checkout master
git stash apply
Вы получаете конфликт здесь о pro1, измененном в тайнике, но удаленном на master. Вы решаете это, говоря git просто продолжать игнорировать его, удаляя его.
git reset HEAD .
Теперь зафиксируйте все бесплатные файлы:
git add free2 # Manually add the new files (easy and not violating § 5.2)
git commit -a -m 'Update to free1 and free2'
Вернитесь обратно в приватную ветку, объедините обновленную главную ветку и зафиксируйте оставшиеся файлы снова из stash.
git checkout master-private
git merge master
git stash pop # The stash now applies cleanly and is removed
git add pro2 # Manual but necessary adding of new files (not violating § 5.2)
git commit -a -m 'Update pro1 and pro2'
И это все.
Когда вы получаете запрос на GitHub и объединяете его. После этого просто синхронизируйте с ним свой локальный мастер, а затем объедините его с частной веткой:
git checkout master
git pull
git checkout master-private
git merge master
git push
мерзавец легкий - peasy.