Photo Credit: t1ggr
Dependencies. They’re knotty, and there really is no straight-forward, one-size-fits all solution.
Dependency hell is a colloquial term for the frustration of some software users who have installed software packages which have dependencies on specific versions of other software packages. —Wikipedia
I recently saw a comment on GitHub:
When I run [the tests] they always pass, but that is because they import the package from [the package path] and not my local fork.
What’s going on here?
In order to illustrate the problem, imagine the following hypothetical scenario.
Hellø, Wørld
You’re using my sophisticated library, which translates English into Norwegish.
package main
import (
"fmt"
"github.com/kytrinyx/norwegish"
)
func main() {
fmt.Println(norwegish.Translate("Hello, World!"))
}
You realize that the output is, incorrectly, Hellø, Wørld, so you fork my project in order to fix it so that it uses the correct translation, Hellø Vørld.
You go get
your fork, and run the tests. As expected, they’re passing.
Then you add a test for the Vørld case, and (as expected) it fails.
Finally, you change the code to fix the bug and run the tests, but—no dice—they’re still failing.
Import Paths and $GOPATH
If you look closely at my test suite, it tests the package from the outside, black-box style, importing the norwegish
package using the github.com/kytrinyx/norwegish
import path, just like you would in any other application.
In other words, the tests are using the code which you already have on your system at $GOPATH/src/github.com/kytrinyx/norwegish
.
The tests in your fork are still importing the original package, which doesn’t have the fix. You could manually change the import path, but that would be tedious and error prone.
The key is to use multiple remotes.
Mine, Yours, Origin, Upstream
Everything works out if you have both the original and your fork living on your system in the directory corresponding to the original’s import path.
When you first go get
or clone a repository, you will have a single remote, with the default name origin.
$ cd $GOPATH/src/github/kytrinyx/norwegish
$ git remote -v
origin https://github.com/kytrinyx/norwegish (fetch)
origin https://github.com/kytrinyx/norwegish (push)
You can add new remotes at will. This is good when you want to try out some random person’s patch on a project:
$ git remote add rando1 git@github.com:random-person1/norwegish.git
$ git remote add rando2 git@github.com:random-person2/norwegish.git
Then you can git fetch rando1
and check out branches based on their code.
Handy.
In this case, what we want is your fork as the secondary:
$ git remote add fork git@github.com:you/norwegish.git
Now you’ll have two remotes, origin
and fork
:
$ git remote -v
fork git@github.com:you/norwegish.git (fetch)
fork git@github.com:you/norwegish.git (push)
origin https://github.com/kytrinyx/norwegish (fetch)
origin https://github.com/kytrinyx/norwegish (push)
With this setup, the tests will pass, because your fix lives at the correct import path.
Side Note
I like to use the remote name origin
for my version of a project, and upstream
for the upstream that I forked it from, but I’m somewhat obsessed with naming and consistency. If you have unhealthy obsessions too, you can remove and re-add remotes:
$ git remote rename origin upstream
$ git remote rename fork origin
Branching and Pull Requests
Assuming that the kytrinyx/norwegish repo is at origin
, and your fork is at fork
, you can use all the usual branching shenanigans for creating a pull request:
git checkout -b fix-capital-w-bug
git commit add -m "Translate capital W to capital V"
git push fork fix-capital-w-bug
… and then easily reset master so you don’t get out of sync:
git fetch origin
git reset --hard origin/master
It turns out this is not too complicated after all.
About Katrina Owen:
Katrina is obsessed with refactoring, idiomatic code, and naming things. She is the creator of Exercism.io, an open source application that combines practice problems with crowd-sourced mentorship, which is written mostly in Ruby and Go.
July 24, 2014