Next & Previous

Managing a standard product and a personal version on GitHub

SG 2019-01-26: From 2015 until 2019, this blog ran on homebrew PHP software called Upblog, a kind of headless CMS. Now it is a static site built with Jekyll.

This blog platform, Upblog, is on GitHub; I want anyone to be able to download and install it. But I also have a version that I want to use for myself. I soon realised I didn’t want to be copying-and-pasting code changes across from the standard to my personal, so there had to be a proper way to do this with git.

How to do it


The Upblog software is hosted at My personal installation is


I have a folder for developing Upblog, which is isolated from my website folder. This has a git repo in it, which only has one remote:

$ cd ~/projects/upblog
$ git remote -v
origin (fetch)
origin (push)

Then there is my website folder, which has two remotes:

$ cd ~/stegriff/upblog
$ git remote -v
origin (fetch)
origin (push)
product (fetch)
product (push)

So the origin for my website is it’s own GitHub repo, but I’ve also added the product remote (in the usual way):

$ git remote add product

Developing the standard product

I write code to add features to the standard product. Be disciplined! Don’t add features to your live site! When a feature is tested and ready, I check everything is committed and then I push to the SP’s origin. Now my changes are in the GitHub version at

Check your site is clean

If I’ve added new posts, templates, or other sitely things, I make sure they’re all committed to the website’s origin (sg-upblog).

Ignore some files during pull and merge

We basically want to pull product remote changes into my personal now. This has a few caveats. I want to ignore certain files because I don’t want to overwrite instance-related config or templates specific to my website. This can be done!

I have added a .gitattributes file in the website directory as so:

/templates/*.* merge=ours
config.php merge=ours
.htaccess merge=ours merge=ours

I’m not totally sure that the templates line actually works yet, but it’s a WIP. The merge strategy above needs to be configured at the prompt, like this:

$ git config --global merge.ours.driver true

I got both of those steps from the progit book.

Pull and merge

In my website directory:

$ git pull --no-commit --edit product master

Using --no-commit and --edit gives you peace of mind that you can sort everything out before committing. Since I got my gitattributes file straight, I don’t actually use these flags any more, but they might be helpful to you on your first few merges.

If there are any problems, I resolve these using my default merging tool (TortoiseMerge) by running

$ git mergetool -y

If you don’t have a nice GUI merge tool, you should install one.

During this process, throw in lots of git status for good measure. You might be left with a .orig file for any files you used the tool on, so just delete those in your file browser or by using rm file.orig.

git add everything that you want to commit. I like to get my staged/unstaged into exactly the right state so that I can then git add -A

When you’re ready, commit the result and push back to origin

$ git commit -m 'Merged new product features'
$ git push origin master

Backing out

If you’re completely unhappy with how a merge is going and you want to put everything back the way it was:

$ git merge --abort
$ git status

If the merge has overwritten one or two key files, and you wanted to keep your site’s version, this can be fixed (using example of config.php):

$ git reset HEAD config.php
$ git checkout -- config.php
$ git status

git reset is the opposite of git add; it unstages a change. git checkout reverts changes on a file to the last commit.


Don’t maintain multiple codebases when you don’t have to! :)

Written 2015-09-29