Tracking an upstream-project using git

Software developments should never reinvent the wheel. This is already implied by the DRY-principle. I apply the principle also to external software projects, i.e. I don’t want to repeat myself and I don’t want to repeat the work of others. This is why almost every software project depends and builds on other software projects. But sometimes a dependent software project must be adapted, modified or patched before it can be used.

Patching external software projects

Let’s take an open source project for an example, that must be modified before it can be used. (Note: Prior to changing the code of other projects, make sure to check the license first!). We take a release of the project, perform your modifications and use the modified dependency. The issue at hand: How do we apply our changes to updated versions of the external project?

The solution can be found in the version control system git. The idea is really simple, but simplifies the workflow. First of all you import an initial version of the external project (“Release 1.0” in the example below). Now you go ahead and branch into 2 directions:

  1. one branch contains the official release (upstream)
  2. another branch also containing the local changes (master)

Now we go ahead and perform our changes in the “master” branch. When a new software version is released, we import it into the “upstream” branch. Now once we merge the branch “upstream” into “master”, you get an automatically patched version. In most cases a real time saver.

Note: You don’t have to perform the import manually if the external software project uses git. Other than that workflow is identical.

Unclean start

But how do we get to a clean start if we didn’t know that git could make our life that easy? Let’s take an example that we just took the upstream project and applied our patches onto them, maybe even without a history:

From here we create a branch “upstream” from the branch “master”. Now you switch to the newly created branch, wipe out the content and import the official release (the exact same version matching the current “master” branch passt, i.e. if master was a patched version of 1.0, we would import version 1.0). Now a merge from upstream into master would result in massive merge conflicts. Now we need to aid git a bit. We inform git, that everything in the “upstream” branch is already in the master branch:

git checkout master
git merge -s ours upstream

This way the setup will allow a workflow identical to the one described above, allowing you to import new releases into “upstream” and merge them into master.

This little trick reduced the duration of hours of manual comparisons to an automated process done within minutes. Note: After creating a new patched release you of course need to test it!

Give changes back to the upstream project

This workflow is pretty easy, but a bit expensive (according to how often upstream releases need to be incorporated). My personal idea is, to hand over the changes to the upstream project, even if not explicitly required by the license. First of all it reduces my personal workload, but also provides a (commonly useful) adaption to all users and motivates the projects maintainers.

Copyright © christophbrill.de, 2002-2018.