At Made we’ve used GitHub for years for all of our public and open source projects. That has always been free, and the experience has always been great. We have been hosting our private repositories with another service for a really long time. However, the user experience, speed and feature set of GitHub that we get with our public repositories has finally led us to make the jump, and to migrate all of our repositories across to GitHub with a paid plan.
Our git repositories are used hundreds, if not thousands of times a day by our team, working on various projects. Minimising the access downtime during migration was essential as we were doing this during office hours, so we had a few hurdles to tackle during the migration.
- Importing to GitHub
- Build pipelines
- Local development
Importing to GitHub
This turned out to be the simplest of all the steps we had to take. We split our repositories up between the three of us that were working on the migration, and for each repository we would make a bare clone to our local machine. This means pulling down solely the data from a git repository (normally what is contained within the .git directory), and not having a working copy of the latest changes in a repo. We then push the bare repo into GitHub. This was essential as we wanted to maintain our existing branches and tags.
git clone --bare git@path/to/repo/on/old/service/project.git
git push --mirror firstname.lastname@example.org/madetech/project.git
As simple as that! The git push –mirror ensures that all branches and tags get pushed into GitHub.
To simplify our Jenkins configuration, we decided on creating a dedicated GitHub user for our Jenkins, with an OAuth token allocated to it. This OAuth token had the repos permission assigned which is all our build pipelines require.
Using the Jenkins credentials plugin, adding a new global credential was as easy as setting the username to user the OAuth token, and the password field to use x-oauth-basic.
For each of our Jenkins jobs, we set the Git repository URL to use the https version, and then allocated the OAuth credentials.
Finally, we created a ‘Deploys’ Team underneath our Organisation on GitHub, and assigned our dedicated Jenkins user to it. Then for each of the repositories that we wanted Jenkins to access, we assigned the team as a collaborator per repository.
Our projects either use Capistrano or cf-deploy for deployments. cf-deploy always transfers files to the app instance from the directory it’s being run from, whereas Capistrano will ssh into the instance, and then clone down the code. With our Capistrano deploys, we simply had to change the repo_url value in our config files:
set :repo_url, 'email@example.com:madetech/project.git'
We then just added our SSH keys to the dedicated Jenkins user so that Capistrano would be able to pull the changes in on the remote app instance.
Finally, as our developers needed to push up new code, they needed to update the remote git references to our old service provider and replace them with a new GitHub URL. The default remote name used in git is origin, so it was a case of overriding the existing value with a new GitHub repo URL.
git remote set-url origin firstname.lastname@example.org:madetech/project.git
From then on, any remote action would use the GitHub repo.
The migration went a lot easier than we first expected. We’ll miss our previous service provider, but we look forward to using GitHub from here on out, and are excited by new features yet to come.