Saturday, 25 January 2014

Updating GitHub Forks with latest commits from GitHub's 'parent' repo

One of the areas that tend to case some problems with GitHub 'Forking model' workflow, is the need to have the Forks updated with the commits that have been added to the Parent repo (i.e. the repo that was used to create the Fork from).

To see real-word examples (and pains) of this issue, take a look at these posts:
For the example show below, I'm going to update the DinisCruz-Dev/TeamMentor_Eclipse_Plugin repo which is a Fork of TeamMentor/TeamMentor_Eclipse_Plugin (here also referenced as the Parent repo).

At the moment these repos are the stage shown in Updating the GitHub repos for the 1.6.0 release of the Eclipse Fortify Plugin :
Here is what this looks like form the Parent's repo TeamMentor/TeamMentor_Eclipse_Plugin point of view:
And here is what this looks like form the Forked repo DinisCruz-Dev/TeamMentor_Eclipse_Plugin point of view:

Looking at the common commits, might help to visualise what is going on.

The last commit at the Fork is the  b4dad953767fcc674d9ca948fc0cfb762415f01c, which can be seen below as represented by the large LAST BLUE dot in the DinisCruz-Dev/TeamMentor_Eclipse_Plugin repo Network graph


But the same commit can be seen below as the large GREEN dot in the TeamMentor/TeamMentor_Eclipse_Plugin Parent repo (note that it is not the last one in this repo):


At the moment the Parent repo is currently at the 2ac007c7385fd992fb5f6c6e4774cfdaaa88ba43 commit (which doesn't exit in the Forked repo)

The practical consequences of this situation, is that the Fork is currently in an 'incompatible' state with its Parent , and it will not be possible to send Pull Requests/code-fixes upstream (note that this is 'by design' since Git does not allow merges when there are no common parents).

The solution is to do a Pull Request from 'Parent to Fork' (ie. from TeamMentor/TeamMentor_Eclipse_Plugin to DinisCruz-Dev/TeamMentor_Eclipse_Plugin), as seen below:


In this case, there is only one update (made directly on the Parent repo) that needs to be merged into the Forked repo, and more importantly we get the desired 2ac007c7385fd992fb5f6c6e4774cfdaaa88ba43 commit:


Here is how I created the Pull Request:


Which I then opened up in a browser logged in as DinisCruz-Dev (the DinisCruz account doesn't have GitHub privs to make this merge)



And since the commits are all compatible, I can just click on the 'Merge pull request' button:


... to successfully apply the merge:


And now the Forked repo contains all commits that exist in the 'parent' repo (note the the 2ac007c7385fd992fb5f6c6e4774cfdaaa88ba43 commit below)


A final good house cleaning step is to also update the Master branch of the Fork:


... which makes the final version of the graph look like this:


Note that all these steps could had been done using the git.exe command line, and in some cases, that is better, since we have more control over the creation of new commits on merge (for example note how every-time I merged a Pull Request in GitHub, a new commit was created! ... which is something that is not needed all the time)

For example I prefer when we can align the branches that are synced with the same commit, like what was done on Syncing all releases to the same commit and Tag (for TeamMentor v3.4)  and shown below: