具有开源和专有(私有)部分的项目的 git 工作流程

K3-*_*rnc 1 git wordpress plugins git-workflow

免费和专业版的 Wordpress 插件。PRO 版本包含分散在代码库中的其他文件。

在 git 中跟踪两个版本的最佳策略是什么,满足以下约束:

  1. 免费版本在 GitHub 上开源,接受贡献;
  2. PRO 版本与私人存储库同步;
  3. 本地开发发生在 PRO 版本上(例如为了重构工作);
  4. 两个历史都是相关的(PRO的历史?免费)
  5. 低维护:
    1. 我们是 git noobs,
    2. 没有手动记账什么文件适合哪里。

有许多 Wordpress 插件遵循这种完全免费的与专业版的二分法。它们是如何版本化的?

K3-*_*rnc 6

想到了一些简单的方法......

独立的命名空间

将所有分散的文件移动到单独的命名空间目录中,例如 ./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
Run Code Online (Sandbox Code Playgroud)

每当有更改提交到公共存储库时,您可以将它们合并到您的 PRO 版本中:

cd ~/project-pro
git checkout master
git pull libre master --allow-unrelated-histories
git push origin master
Run Code Online (Sandbox Code Playgroud)

每当您想要同步到已发布的免费版本的 PRO 版本中更改时,您可以使用git-format-patch将更改导出为补丁文件,然后在另一端导入该补丁集,排除任何不会在免费版本中发布的文件. 像这样:

cd ~/project-pro
git checkout master
git format-patch HEAD~3..HEAD  # Export e.g. last three commits as patches
Run Code Online (Sandbox Code Playgroud)

现在切换到免费版本并应用补丁(带有git-am),从每次提交中排除免费版本忽略列表中的所有 PRO 文件(路径)。我将它们放在免费项目根目录中的.gitignore文件中,命令行假定 POSIX shell 可用(--exclude为 .gitignore 中的每个文件/路径重复参数)。

cd ~/project-libre
git checkout master
git am $(printf -- '--exclude=%s ' $(cat .gitignore)) ~/project-pro/*.patch    
Run Code Online (Sandbox Code Playgroud)

两个分支

有两个分支,每个分支都与不同的遥控器同步。

git remote add origin  GITHUB_PUBLIC_REPO
git remote add private PRIVATE_REPO
Run Code Online (Sandbox Code Playgroud)

创建两个文件,一个免费,一个 PRO:

touch free1 pro1
Run Code Online (Sandbox Code Playgroud)

在 master 分支上,创建一个包含所有 PRO 文件的 .gitignore

git checkout master
echo 'pro*' > .gitignore

git add .gitignore
git commit -m 'Add .gitignore ignoring PRO files'
Run Code Online (Sandbox Code Playgroud)

将公共分支与公​​共存储库同步:

git push -u origin master
Run Code Online (Sandbox Code Playgroud)

现在将 master 分支到一个私有 PRO 分支并清除 .gitignore 因为 PRO 文件在那里不会被忽略。

git checkout --branch master-private
echo > .gitignore

git commit .gitignore -m 'Clear .gitignore -- track all files here'
Run Code Online (Sandbox Code Playgroud)

将私有分支与私有存储库同步:

git push -u private master-private
Run Code Online (Sandbox Code Playgroud)

现在将 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'
Run Code Online (Sandbox Code Playgroud)

并将 master 合并到 master-private 中,使其包含完整的集合。

git checkout master-private
git merge master
Run Code Online (Sandbox Code Playgroud)

您需要解决一个 .gitignore 冲突(或者您可以指定-X ours合并开关)。


稍后,您在主私有分支(第 3 节)上进行一些开发,修饰并创建适合两个分支之一的各种文件:

git checkout master-private
touch free2 pro2
echo xxx > free1
echo xxx > pro1
Run Code Online (Sandbox Code Playgroud)

您不想枚举所有要提交的非 PRO 文件(第 5.2 节);这就是你拥有 .gitignore 的目的。您可以通过切换到 master 并在那里提交适合的所有内容来使用它,然后切换回 master-private,提交剩余的内容。您需要先存储更改,因为它们会被切换分支覆盖。

git stash
git checkout master
git stash apply
Run Code Online (Sandbox Code Playgroud)

您在此处遇到了关于 pro1 在 stash 中更改但在 master 上删除的冲突。您可以通过告诉 git 通过取消暂存来继续忽略它来解决它。

git reset HEAD .
Run Code Online (Sandbox Code Playgroud)

现在提交所有免费文件:

git add free2  # Manually add the new files (easy and not violating § 5.2)
git commit -a -m 'Update to free1 and free2'
Run Code Online (Sandbox Code Playgroud)

切换回私有分支,合并更新的主分支,并再次从 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'
Run Code Online (Sandbox Code Playgroud)

就是这样。


当您在 GitHub 上收到拉取请求并合并它时。之后只需将您的本地 master 与其同步,然后将其合并到私有分支中:

git checkout master
git pull
git checkout master-private
git merge master
git push
Run Code Online (Sandbox Code Playgroud)

git 很简单——很简单。