Рабочий процесс git для проекта с открытой и проприетарной (частной) частью

Плагин Wordpress с бесплатной и PRO-версией. PRO версия содержит дополнительные файлы, разбросанные по базе кода.

Какова оптимальная стратегия для отслеживания обеих версий в git, удовлетворяющая следующим ограничениям:

  1. бесплатная версия с открытым исходным кодом на GitHub, принимающая участие;
  2. PRO версия синхронизирована с приватным репозиторием;
  3. локальная разработка происходит в версии PRO (например, для рефакторинга для работы);
  4. обе истории связаны (история PRO ⊇ бесплатно)
  5. низкие эксплуатационные расходы:
    1. мы мерзавцы,
    2. нет ручного учета того, что файл подходит, где.

Существует множество плагинов для 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.

Другие вопросы по тегам