go: cmd/go: git export-subst causes hash mismatches
What version of Go are you using (go version
)?
1.11rc1
Does this issue reproduce with the latest release?
yeap
What operating system and processor architecture are you using (go env
)?
see below
What did you do?
These are the steps I did on three different machines. You can see the hash is different on the Macbook Pro vs the iMac and Linux machine. All of these operations were done in a new $GOPATH
and newly created module. I originally ran into this issue when doing go mod tidy
on the iMac machine after committing the go.sum
from the Macbook Pro.
Linux Workstation:
$ go1.11rc1 version
go version go1.11rc1 linux/amd64
$ uname -a
Linux theia 4.15.0-32-generic #35-Ubuntu SMP Fri Aug 10 17:58:07 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
$ go1.11rc1 env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/pivotal/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/pivotal/workspace/repro-mod-issue/go"
GOPROXY=""
GORACE=""
GOROOT="/home/pivotal/sdk/go1.11rc1"
GOTMPDIR=""
GOTOOLDIR="/home/pivotal/sdk/go1.11rc1/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/pivotal/workspace/repro-mod-issue/mod/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build539505302=/tmp/go-build -gno-record-gcc-switches"
$ go1.11rc1 get k8s.io/client-go@v0.0.0-20180709172653-0ec73abb067f
go: finding k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f
go: downloading k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f
go: finding k8s.io/client-go v8.0.0+incompatible
go: downloading k8s.io/client-go v8.0.0+incompatible
$ cat go.sum
k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f h1:0k3XNLIMLwDNdQdkviifMIGTGVAJSJYePselvFsqV8s=
k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
k8s.io/client-go v8.0.0+incompatible h1:2pUaSg2x6iEHr8cia6zmWhoCXG1EDG9TCx9s//Aq7HY=
iMac:
$ go version
go version go1.11rc1 darwin/amd64
$ uname -a
Darwin otis 17.7.0 Darwin Kernel Version 17.7.0: Thu Jun 21 22:53:14 PDT 2018; root:xnu-4570.71.2~1/RELEASE_X86_64 x86_64
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/pivotal/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/pivotal/workspace/repro-mod-issue/go"
GOPROXY=""
GORACE=""
GOROOT="/Users/pivotal/sdk/go1.11rc1"
GOTMPDIR=""
GOTOOLDIR="/Users/pivotal/sdk/go1.11rc1/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/pivotal/workspace/repro-mod-issue/mod/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/nl/f9hjjjhn0qq7lp917hnx05m00000gn/T/go-build367695573=/tmp/go-build -gno-record-gcc-switches -fno-common"
$ go get k8s.io/client-go@v0.0.0-20180709172653-0ec73abb067f
go: finding k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f
go: downloading k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f
go: finding k8s.io/client-go v8.0.0+incompatible
go: downloading k8s.io/client-go v8.0.0+incompatible
$ cat go.sum
k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f h1:0k3XNLIMLwDNdQdkviifMIGTGVAJSJYePselvFsqV8s=
k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
k8s.io/client-go v8.0.0+incompatible h1:2pUaSg2x6iEHr8cia6zmWhoCXG1EDG9TCx9s//Aq7HY=
Macbook Pro:
$ go version
go version go1.11rc1 darwin/amd64
$ uname -a
Darwin wat.local 17.6.0 Darwin Kernel Version 17.6.0: Tue May 8 15:22:16 PDT 2018; root:xnu-4570.61.1~1/RELEASE_X86_64 x86_64
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/jasonkeene/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/jasonkeene/projects/repro-mod-issue/go"
GOPROXY=""
GORACE=""
GOROOT="/Users/jasonkeene/sdk/go1.11rc1"
GOTMPDIR=""
GOTOOLDIR="/Users/jasonkeene/sdk/go1.11rc1/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/jasonkeene/projects/repro-mod-issue/mod/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/f2/8qjhqmss5ssb6ccx15bxvvl80000gn/T/go-build890262066=/tmp/go-build -gno-record-gcc-switches -fno-common"
$ go get k8s.io/client-go@v0.0.0-20180709172653-0ec73abb067f
go: finding k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f
go: downloading k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f
go: finding k8s.io/client-go v8.0.0+incompatible
go: downloading k8s.io/client-go v8.0.0+incompatible
$ cat go.sum
k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f h1:j4/k4PUx72J2958XS0i/rAn6JAaoi1v48mLEaY8QGzM=
k8s.io/client-go v0.0.0-20180709172653-0ec73abb067f/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
k8s.io/client-go v8.0.0+incompatible h1:7Zl+OVXn0bobcsi4NEZGdoQDTE9ij1zPMfM21+yqQsM=
What did you expect to see?
The hashes should match. This is the same git SHA for k8s.io/client-go
and same pseudo-version.
What did you see instead?
The hashes were different, resulting in a failed go mod tidy
and go mod verify
.
One difference between the Macbook Pro and iMac/Linux is that I installed go1.11rc1 the day before on the Macbook Pro. The other two machines I installed go1.11rc1 today. I installed using go get golang.org/dl/go1.11rc1
on all three machines.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 1
- Comments: 19 (17 by maintainers)
Commits related to this issue
- [release-branch.go1.11] cmd/go: ensure git attributes are set This change disables the export-subst and export-ignore attributes when creating zip files for modules. This is done to prevent the zipha... — committed to golang/go by jasonkeene 6 years ago
- build: update go.sum using go 1.11.2 to to fix wrong checksum go 1.11 had a bug (https://github.com/golang/go/issues/27153) generating non unique checksums. Update go.sum using go 1.11.2 to fix this... — committed to sgotti/stolon by sgotti 6 years ago
- build: update go.sum using go 1.11.2 to to fix wrong checksum go 1.11 had a bug (https://github.com/golang/go/issues/27153) generating non unique checksums. Update go.sum using go 1.11.2 to fix this... — committed to sgotti/stolon by sgotti 6 years ago
- build: update go.sum using go 1.11.2 to to fix wrong checksum go 1.11 had a bug (https://github.com/golang/go/issues/27153) generating non unique checksums. Update go.sum using go 1.11.2 to fix this... — committed to sgotti/stolon by sgotti 6 years ago
- go1.11.2 updates tracking (#2) * [release-branch.go1.11] doc/go1.11, cmd/go: elaborate on new GOFLAGS environment variable In Go 1.11, cmd/go gained support for the GOFLAGS environment variable. ... — committed to changkun/go by changkun 6 years ago
I’m not sure
export-subst
is something that go modules should enable. Here is my reasoning:export-subst
is a git attribute that allows for replacing certain format strings whengit archive
is invoked. The result is source code that is different than what would be in the working directory of the repo. Something like this:is turned into this:
This seems like behaviour that is undesierable. If I run:
I would expect to get the exact same source code for that SHA1. Instead I get a mutated version of the source code. We have seen issues with the format strings not being consistent between git versions. Even something like the amount of objects located in the repo can change the results of
export-subst
.The situation that I ran into was
k8s.io/client-go
populating version information into the source code. This string can be populated by the builder via ldflags. Alternatively, version information can be read from the binary with something likersc.io/goversion
.export-subst
is not needed to get version information into the binary.Possbile solutions:
Disable
export-subst
attributeThis can be achieved by adding the following to
.git/info/attributes
before doing thegit archive
:This disables the option for the whole repo. Adding the attribute in this way has the highest precedence and can not be overrode by attributes in
.gitattributes
files or global configuration. I have been working on a CL that does this.Disable all export attributes
This would include the
export-ignore
attribute. This attribute ignores certain paths when creating the.zip
. This can be done by adding the following to.git/info/attributes
.To be clear,
export-ignore
would likely not cause the ziphash to be different but it would cause the contents of the zip file to be different from the source code that is in the repo.Require a minimum version of git that is after the change to
%h
This option is not valid as the format strings for
export-subst
change with variables outside of the git version.Do nothing
This would require all git repos that currently have these features enabled (likely for valid reasons) to stop using these features if they want to get consistent ziphashes. Naturally, folks will not know to do this until they run into this issue, causing them to at best do the research to find why this is occuring or more likely just ignore validation warnings. Training users to ignore these warnings seems like a bad idea.
I think a decision needs to be made if modules should use the contents of the repo as they are or if modules should apply extra processing to the source code via
git archive
and whatever other features are in other version control systems.I agree that for the sake of reproducibility and consistency we should use the source as it is checked out, not depend on a post-processing step that is both uncommon and undeterministic, so I’d favor
* -export-subst -export-ignore
. (And I believe this is a git misfeature we should opt out of.)It’s a bit unfortunate that the GitHub-generated zip files will differ, but it’s my understanding that we don’t use those anymore?
I’m not sure that this is actually a problem for
cmd/go
to solve.export-subst
should be fine as long as the substitutions are deterministic, well-defined, and stable across platforms andgit
versions. If a particular repository has anexport-subst
configuration that is inherently not deterministic or not stable, that seems like an issue to file against the owner of that repository.If the main source of instability is git’s abbreviation algorithm, is there some way to specify abbreviation parameters explicitly, or to disable abbreviation altogether?