Forking Golang repositories on GitHub and managing the import path

November 23, 2015

Problem: there's an awesome Golang project on GitHub which you want to fork. You want to develop & collaborate on that fork, but the golang import path, in your source code, still references the original path, breaking everything.

A couple solutions offered below. First, though, let's get some names.

A sample case, the problem at hand

There's an awesome tool on You successfully fork it onto

You want to collaborate on; you wish to pull, commit & push. Maybe you want to send pull requests to the origin.

The following is commonly found throughout .go files in the repository:

import (

If you:

go get

golang creates your $GOPATH/src/, which is awesome. However, as you resolve dependencies via

cd $GOPATH/src/ ; go get ./...

golang digs into the source code, finds references to etc, and fetches those from and onto $GOPATH/src/, which is not awesome. You actually have two copies of the code, one from your fork, one from the origin, and your own fork will be largely ignored as it mostly points back to the origin.

A bad solution

The dirty, bad solution would be for you to go over the source code and replace "" entries with "". It is bad for two reasons:

  • You will not be able to further pull changes from upstream
  • You will not be able to pull-request and push your own changes upstream

When I say "You will not be able" I mean "in a reasonable, developer-friendly manner". The code will be incompatible with upstream and you have effectively detached your code. You will need to keep editing and re-editing those entries anytime you wish to pull/push upstream.

Solution #1: add remote

Described in GitHub and Go: forking, pull requests, and go-getting, follow these procedures:

go get
git remote add awesome-you-fork

You're adding your repository as remote. You will from now on need to explicitly:

git pull --rebase awesome-you-fork
git push awesome-you-fork

If you forget to add the "awesome-you-fork" argument, you are pulling and pushing from upstream.

Solution #2: cheat "go get", DIY

The problem began with the go get command, which copied the URI path onto $GOPATH/src. However go get implicitly issues a git clone, and we can do the same ourselves. We will dirty our hands just once, and then benefit from an ambiguous-less environment.

We will now create our git repository in the name of awesome-org but with the contents of awesome-you:

mkdir -p {src,bin,pkg}
mkdir -p src/
cd src/
git clone # OR: git clone
cd tool/
go get ./...

The mkdir -p {src,bin,pkg} is there just in case you do not have anything setup in your $GOPATH. We then create the repository path under the name of awesome-org, but once inside clone from awesome-you.

The source code's import path fits your directory layout now, but as you push/pull you are only speaking to your own awesome-you repository.

  • Joakim Söderberg

    Thanks for the useful blog entry. I am learning Go and found an improvement in a depedency, when I ran into this exact issue.

    I had initially thought the fact that you can simply do an import on a github project like this is a really cool feature in golang...

    However, after running into this issue, and then realising there is no "official" or "good" solution for this, I kind of think it's a bad design decision. My 1 line "fix" I wanted to test now becomes a lot bigger hassle. Especially when I am building and running my go-app within a docker. Simply going in and changing the git clone and similar solutions will be very "unclean" and cumbersome.

  • darrenrush

    Any reason you didn't submit this as an Issue to the main go repository? I would go so far as to say this is bug with security and social implications. The additional friction this adds to the fork/PR/merge workflow means that the amount of collaboration from open source and other contributors is greatly limited for Go relative to just about every other language.

  • Alexandre Richonnier

    Hi, Thanks for the useful blog entry.
    To automate this process, I wrote a small script. You can find more details on my blog ...

  • Dan Tenenbaum

    You say "The source code's import path fits your directory layout now, but as you push/pull you are only speaking to your own awesome-you repository."

    But what about when you "go get ./..."? Or when the compiler tries to resolve dependencies? Are you then speaking to the original repository? Seems like then it might pull from the original when that is not what you want.

Powered by Wordpress and MySQL. Theme by