3

I'm setting up a test-architecture. In this system a VM has to test a specific revision of the code. The VM is completely clean, and does not have a local (updatable) version of the repo. The code is being hosted on an on-site git server, over ssh with a user named git. I have full control over both machines.

The easy solution is:

git clone --no-checkout git@gitserver:reponame.git
git checkout 8e8fdea8f8367f4a179d2faddbaadba495d6bc12

This works, but does too much: It transfers the full history over the network, something I want to avoid if at all possible.

It seems to me from the documentation that git clone can take a --branch option, but this doesn't allow me to specify a particular revision. If it would, this in combination with --depth 1 would work for me.

The alternative is to use git archive --remote. I understand the security implications of allowing this to get arbitrary revisions, and that is not a problem in this case, so I run

git config --global --bool --add uploadArchive.allowUnreachable 1

on the git server as the git user.

Now on the shell of the git user, I can do

git archive --format tar.gz --remote reponame.git 8e8fdea8f8367f4a179d2faddbaadba495d6bc12

Also, from my VM I can run

git archive --format tar.gz --remote git@gitserver:reponame.git master

However not working is:

git archive --format tar.gz --remote git@gitserver:reponame.git 8e8fdea8f8367f4a179d2faddbaadba495d6bc12

remote: fatal: no such ref: 8e8fdea8f8367f4a179d2faddbaadba495d6bc12
remote: git upload-archive: archiver died with error
fatal: sent error to the client: git upload-archive: archiver died with error

And yes, I'm pointing to the same repo, that revision definitely is in the repo, it will just not work with revision number. One thing that may be the case is that if the commands are executed over ssh, the default ~/.gitconfig file is not being read, although I could not find any information on this.

Currently I'm using bash as shell for the git user. It will work in the future with a restricted shell, but to show the basic problem, I wanted to use a normal shell.

I'm interested in both general remarks in how I should be getting a single revision to a clean machine, and a solution to the particular problem of not being able to use git archive with a revision.


EDIT: torek gave me some ideas about versions (I run on OSX, with git 1.8.5.2 stock, and 2.0.1 installed through brew), and I made a small wrapper script around git-upload-archive to figure out what was going on. The wrapper script:

/usr/local/bin/git --version > /tmp/version
tee /tmp/stdin | /usr/local/bin/git-upload-archive "$1" | tee /tmp/stdout

and calling the git-archive with the --exec option to run this script.

The version written is 2.0.1. The same problem persists however... From locally I can call git-archive with -remote and sha1 iff uploadarchive.allowunreachable is set, remotely I can't. Interestingly the request (in /tmp/stdin) is exactly the same in both cases, the reply is different. As far as I can see, this is because git-upload-archive is not picking up the correct config if started over ssh; this can be shown by using a local config in the repo, in which case it does work (my remark in the comments that this didn't work was because I was indeed picking up /usr/bin/git-upload-archive; the old version that doesn't allow this config flag).

The problem can actually be solved by calling /usr/local/bin/git upload-archive instead of /usr/local/bin/git-upload-archive. This can even be supplied as argument to git-archive: --exec='/usr/local/bin/git-upload-archive' doesn't work, --exec='/usr/local/bin/git upload-archive' does.

So problem works now. I would still be interested (from an academic point of view) in why git-upload-archive doesn't pick up the config. Possibly this is a bug that should be reported to the git project.

Claude
  • 8,806
  • 4
  • 41
  • 56
  • You could perhaps test the `~/.gitconfig` theory: set `uploadArchive.allowUnreachable` in the specific repo config, for instance. Or, on the server, make a tag pointing specifically to `8e8fdea8f8367f4a179d2faddbaadba495d6bc12` and fetch by tag. If either works it points to a failure of `allowUnreachable`. – torek Aug 24 '14 at 13:45
  • Interesting ideas. Setting the config option locally in the repo did not result in improvement. Assigning and pushing a tag to that revision does allow it to be archived. – Claude Aug 24 '14 at 13:54
  • Hm. The tag works but the local configuration entry doesn't: sounds like `git archive` is not actually looking at the configuration entry (globally *or* locally). See git's `archive.c`, around line 267: `remote_allow_unreachable` is not getting set. (What version of git is this anyway? The one on the server, specifically. It looks like this started getting restricted in 1.7.10 and allow-unreachable was added in 2.0.0.) – torek Aug 24 '14 at 14:27
  • It's git 2.0.1. As far as I understand, on the server git-upload-archive is being run. I can confirm that git-archive does respect the allowUnreachable flag when run locally. My second example `git archive --format tar.gz --remote reponame.git 8e8fdea8f8367f4a179d2faddbaadba495d6bc12` fails if that option is not set, and succeeds now. – Claude Aug 24 '14 at 14:51
  • Yes, when you run `git archive` locally with `--remote` pointing to the server, this invokes `git-upload-archive` on the server. That's when the restrictions kick in. But: "succeeds now", even with the raw SHA-1? What's changed that lets the raw SHA-1 work? – torek Aug 24 '14 at 15:31
  • Sorry, the "succeeds now" indeed suggests that something changed. I meant to say that running that command, locally, fails if the `uploadArchive.allowUnreachable` config option is not set, and succeeds if it is set and true. So the check works correctly in the local case (although I fail to see why it would be useful there), when running locally on the server (as git user), but fails when the git archive is run on another machine that connects to the server. – Claude Aug 24 '14 at 18:23
  • OK, that's particularly weird. The next thing I would do at this point is check whether *multiple versions of git are installed* (this happens remarkably often) and *the old one is being used in server mode* (this is about 50/50 when multiple versions are installed). – torek Aug 24 '14 at 18:27
  • You gave me a lot to think about. It sort-a works now, see my edit to the question. Thanks so far for all the help in tracking this down. – Claude Aug 25 '14 at 09:08

1 Answers1

1

Just in case someone else runs into this issue: 90% of the answer is defined in the question under the EDIT part. The last 10% is probably not worth really diving into. The important points I repeat here:

  • Take care that on OSX Mevericks the default GIT version is <2.0, and therefore doesn't support the uploadarchive.allowunreachable tag. When accessing git over SSH, it may select a different version depending on whether you start an interactive SSH session or not (your path may be different).
  • git-upload-archive doesn't check for the uploadarchive.allowunreachable flag in the global git config. This seems to be a bug in GIT. The solution is to not use git-upload-archive, but git upload-archive (i.e. use the git script, with upload-archive as first argument). One way to do this is to supply --exec='/usr/local/bin/git upload-archive' to the git archive call.
Claude
  • 8,806
  • 4
  • 41
  • 56