Working with forks in Go

How to work on a forked repository of an open-source Go package

Have you ever wanted to create a fork of a Go package you’re using? Maybe you need to add a feature, specific to your use case, and there is no other way than to change it inside the code. Or maybe you want to fix a bug and submit a PR to an open-source project.

Whatever the case, Go, with its location-based import system, makes it hard to swap implementations of a package. If you try to just swap it into place, you’ll most likely get an error along the lines of: cannot use s (type "fork".SomeStruct) as type "original".SomeStruct in argument to SomeFunc as soon as you pass your data types to a function defined in another file.

You can fix this with heavy refactoring — changing imports in your own code, and typecasting everything coming in from or going out to another package — but it’s near impossible on a large project with many files.

Type aliases can help, but with a little bit of Git magic, you can seamlessly swap a package for your fork and keep hacking away.

Fork and fix

I won’t go into detail on how to create a fork and submit a PR, GitHub has extensive documentation on the subject. I’ll just assume you’ve clicked the “Fork” button on GitHub, and now have your own repository containing a duplicate of the original source.

But as we’ve said, you can’t just go get the forked repository, since all the import paths will be wrong. What we want is to have your local branch, inside your GOPATH , track your forked remote repository, instead of the original.

Let’s start by adding a remote. From the package source path, type the following:

$ git remote add forked <remote repository url>

Then, let’s make sure the local branch tracks the forked remote, and not the origin anymore.

$ git branch -u forked/master

Branch master set up to track remote branch master from forked.

After this line, you can start committing and pushing to your own fork, and all Go packages relying the package will transparently use your own fork of the code.

This is useful, for example, if you’re sure of a bugfix, as you can start working with the fixed version of the code without waiting for the changes to be merged upstream.

When you want to revert to tracking the origin, perhaps because your PR has been merged and you have deleted your fork, or because you need to use the original code for some other project, just type: