changeRefs implementation causes an ambiguous default branch.
Closed this issue · 1 comments
The default branch of a git repository is its remote HEAD branch.
In modern versions of Go, go get
respects the default branch and uses it.
I have a tool that verifies that a Go package has the default branch checked out (and lets you know if it's not). It's currently failing to work correctly on some gopkg.in
repositories. This is because the implementation of changeRefs
does something that causes the remote HEAD to be ambiguous.
Consider gopkg.in/sourcemap.v1
import path.
If I go get
(or git clone
) it and cd into the directory:
$ git remote show origin
* remote origin
Fetch URL: https://gopkg.in/sourcemap.v1
Push URL: https://gopkg.in/sourcemap.v1
HEAD branch (remote HEAD is ambiguous, may be one of the following):
master
v1
Remote branches:
master tracked
v1 tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)
Note:
HEAD branch (remote HEAD is ambiguous, may be one of the following):
master
v1
On the other hand, a regular git repository such as github.com/gorilla/mux
typically prints:
$ git remote show origin
* remote origin
Fetch URL: https://github.com/gorilla/mux
Push URL: https://github.com/gorilla/mux
HEAD branch: master
Remote branches:
custom-context tracked
master tracked
matcher-refactor tracked
subexp-fix tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)
Note the single unambiguous value in HEAD branch: master
.
This issue was originally reported at shurcooL/Go-Package-Store#72 (/cc @mvdan), you can see it for more details.
You can reproduce it by running this code:
package main
import (
"fmt"
"log"
"github.com/shurcooL/vcsstate"
)
func main() {
rv, err := vcsstate.NewRemoteVCS(vcs.ByCmd("git"))
if err != nil {
log.Fatalln(err)
}
branch, revision, err := rv.RemoteBranchAndRevision("https://gopkg.in/sourcemap.v1")
fmt.Printf("branch = %q\nrevision = %q\nerr = %v\n", branch, revision, err)
// Output:
// branch = ""
// revision = "6e83acea0053641eff084973fee085f0c193c61a"
// err = HEAD branch not found in ls-remote output
}
On the other hand, a git repository from github results in:
branch, revision, err := rv.RemoteBranchAndRevision("https://github.com/gorilla/mux")
fmt.Printf("branch = %q\nrevision = %q\nerr = %v\n", branch, revision, err)
// Output:
// branch = "master"
// revision = "599cba5e7b6137d46ddf58fb1765f5d928e69604"
// err = <nil>
RemoteBranchAndRevision
internally uses git ls-remote --symref remoteURL HEAD refs/heads/*
, see its code.
You can also compare the output of:
curl -A 'git/2:2.1.1+github-607-gfba4028' 'https://github.com/gorilla/mux/info/refs?service=git-upload-pack'
curl -A 'git/2:2.1.1+github-607-gfba4028' 'https://gopkg.in/sourcemap.v1/info/refs?service=git-upload-pack'
git ls-remote --symref 'https://github.com/gorilla/mux' HEAD 'refs/heads/*'
git ls-remote --symref 'https://gopkg.in/sourcemap.v1' HEAD 'refs/heads/*'
I believe the root issue is in changeRefs
and that needs to be fixed.
I'm using git version 2.10.1 (Apple Git-78)
and go version go1.8 darwin/amd64
.
Please let me know if you need any more information to reproduce this @niemeyer. Thank you.
Sorry for the late reply here. The logic modifies references with the very specific goal of pleasing git while operating under the "go" tool. The fact this works so well is a feat on itself, so I'm not super keen on doing further work on gopkg.in to chase the general well being of other git tooling. I am sorry that this is the case, though, since your report was clearly well written and reserached, thanks for that.