Subject: Re: Cloning a remote tag without using git-fetch-pack directly?

From: Josh Triplett <[email-masked]>
Date: Wed, 20 Apr 2011 00:27:20 -0700

On Wed, Apr 20, 2011 at 02:26:54AM -0400, Jeff King wrote:
> On Tue, Apr 19, 2011 at 03:20:53PM -0700, Josh Triplett wrote:
> 
> > Using fetch-pack, I can clone a single tag from a repository:
> > 
> > /tmp/testrepo$ git init
> > Initialized empty Git repository in /tmp/testrepo/.git/
> > /tmp/testrepo$ git fetch-pack /home/josh/src/linux-2.6/.git refs/tags/v2.6.12
> 
> I don't think there is any reason to use fetch-pack here instead of
> fetch. The latter will handle other non-git protocols like dumb http and
> git-over-http.
> 
> > However, I can't seem to find any way to convince git clone to do the
> > same thing for me.  git clone will clone a branch, but not a tag.
> > 
> > /tmp/testrepo$ git clone /home/josh/src/linux-2.6/.git -b refs/tags/v2.6.12
> > Cloning into linux-2.6...
> > done.
> > warning: Remote branch refs/tags/v2.6.12 not found in upstream origin, using HEAD instead
> 
> Right. There is no way to do what you want with clone. The "-b" option
> is not "just clone this one thing", it is "clone everything, but the
> branch I am interested in is ...". The fetch refspec remains
> "+refs/heads/*:refs/remotes/origin/*".

Oh, good to know; I hadn't yet figured out that -b didn't change the
refspec.

> To clone a subset of a repository, you have to do the init+fetch trick,
> as you did above.  If you want the configuration set up by clone, you
> can do that, too, with "git config". So the equivalent commands to the
> clone you want are:
> 
>   git init linux-2.6
>   cd linux-2.6
>   git config remote.origin.url /home/josh/src/linux-2.6
>   git config remote.origin.fetch refs/tags/v2.6.12
>   git fetch origin
> 
> We could make clone more flexible with respect to such things, but I
> don't know how useful that would be. A very small minority of power
> users want to use weird fetch refspecs, and it is simple enough to
> configure them manually, as above.

I'd certainly appreciate having a "git clone --refspec=..." or similar,
but thanks for suggesting fetch rather than fetch-pack!  I actually
don't always want the remote set up for this particular purpose, so
using fetch works out well.

> > On a different note, git fetch-pack seems to silently fail if asked to
> > fetch a remote tag which points at a tree object rather than a commit
> > object:
> > 
> > /tmp/testrepo$ git init
> > Initialized empty Git repository in /tmp/testrepo/.git/
> > /tmp/testrepo$ git fetch-pack /home/josh/src/linux-2.6/.git refs/tags/v2.6.12-tree
> > (1) /tmp/testrepo$ echo $?
> > 1
> 
> Did you mean v2.6.11-tree? There is no v2.6.12-tree in standard
> linux-2.6 repositories. So fetch-pack is failing because there are no
> matching refs to fetch. This works for me:
> 
>   $ git init
>   $ git fetch-pack /home/peff/compile/linux-2.6 refs/tags/v2.6.11-tree
>   remote: Counting objects...
>   ...
> 
> If you want better error messages, use the fetch porcelain:
> 
>   $ git init
>   $ git fetch /home/peff/compile/linux-2.6 refs/tags/v2.6.12-tree
>   fatal: Couldn't find remote ref refs/tags/v2.6.12-tree
>   fatal: The remote end hung up unexpectedly

Well, *that's* embarassing.  I thought I'd tested that with a couple of
other repositories and tree-tag objects, but apparently not.

Sadly, though, I still can't check out the result:

/tmp/linux-2.6$ git checkout FETCH_HEAD
fatal: Cannot switch branch to a non-commit.
(128) /tmp/linux-2.6$ git checkout -b master FETCH_HEAD
fatal: Cannot switch branch to a non-commit.

I guess I'd hoped for something similar to "detached HEAD" mode.

Based on this, I need still to switch to using faked commits rather than
trees.

- Josh Triplett