Keeping a project’s public Git or Mercurial remote safe from your private stuff

So you’re a committer on an open-source project, and you also use the same project to build non-public projects for your customers. You set-up your customer’s repository so that it has remotes that point to the public project’s repo on one side, and the customer’s private repo on the other. You pull from the public remote, and only ever push to the private one. Everything works fine, until one day, you make one small mistake and push all of your customer’s proprietary code to the public repo for all to see. Oops.

Before you ask, no, I did not just do that. I did it once a long time ago with some proprietary code of my own, not customer code, thankfully. It was embarrassing enough however, and I had to ask for some help zapping the code before it was on too many people’s clones. This post is not about fixing the mess, it’s about preventing it from happening.

What you’ll want to do to keep the public repo clean and protected, is to keep one clean local clone. This is where you’ll do your public contributions to the project. You can safely push and pull from that clone.

All your derived projects will be cloned from that local pure clone. If a project already exists, you can delete its “remote remote” and replace it with the pure “local remote”. You still never push to that pure remote, only to your customer’s private repo. You can pull all you want from both places.

Now if you ever make that mistake of pushing to the wrong remote, you are still safe: you can just zap your pure clone and start over. It would now take two mistakes to send your customer’s code to the public repo.

To recap:The clone configuration

  1. Clone “A” is a clone of the public repo “P”, will only ever have public code.
  2. A has one remote “RAP” pointing to P on Github or wherever.
  3. Clone “B” is a clone of A.
  4. B has A (not P, never P) as a remote “RBA”.
  5. B also has a private remote “RBX”.
  6. You can push and pull from A.
  7. Your public contributions are made on A.
  8. Customer-specific proprietary work is done on B.
  9. You can pull and push B from RBX.
  10. You can pull B from RBA.
  11. You can never push B to RBA. If you do, zap A and start over.

4 Comments

  • What's an example use-case for this kind of stuff though? Why not make a private repository that has a public one as a sub-repo?

  • I don't see how that would address the problem.

  • Well instead of having a repo that's a *variant* of another repo but with private stuff in it, you have a private repo that uses the other repo as a *dependency*. Hence, if you even commit changes to that dependency repo, it's only for stuff you actually want to push back upstream. I mean, if you don't want to push back something private by mistake, the easiest way to solve that is to not put that private stuff in the repo in the first place. Which leaves me baffled as to why you would do that? Obviously I'm missing some real-world use-case where this is the only viable solution, versus, like I said, just having one be a dependency/library in the other one.

  • Yes, that's what I thought: it doesn't address the problem. What you describe works for a library type of project, but is completely unadapted to a modular application framework such as Orchard.

Comments have been disabled for this content.