16

I have a local repository cloned from a bare remote repository. The following command lists al the remote repository's branches.

$ git ls-remote <remote>

74bd3eb190edb39db04f6c0c4dbbb9e1e96bc6db    refs/remotes/test
85de54d6ae813c624b9623983e6b0a4948dae0fe    refs/remotes/trunk

I want to checkout and track that remote's remote branch trunk. How do I do that?

Note that this is different from checking out a remote repository's local branch. This is how the remote repository looks like.

$ git branch -a

master
remotes/test
remotes/trunk

After running git fetch < remote > to fetch all of the remote repository's branches, I get this output in the local repository.

$ git branch -r

repo/HEAD -> repo/master
repo/master
Hans Sjunnesson
  • 21,745
  • 17
  • 54
  • 63
  • 1
    Jefromi's and Chris's answers should be enough. I just add for reference the interesting SO question http://stackoverflow.com/questions/1070496/having-a-hard-time-understanding-git-fetch. – VonC Jun 14 '10 at 12:14

4 Answers4

12

You can fetch any ref from any remote (as long as the server is willing to give it to you). The key to fetching refs outside refs/heads/ is to supply full ref paths that start with refs/. If desired, you can even pull from repositories that are not configured as remotes (git fetch can take a URL instead of a remote name).

By default, configured remotes will only fetch from the remote repository’s refs/heads/ namespace, so they will not pick up anything inside refs/remotes/. But, you could refer to a ref inside it by using a complete ref like refs/remotes/trunk (remotes/trunk might also work, but might also be ambiguous).

If the fetched refspec does not specify a destination ref, it will be stored in the special FETCH_HEAD ref.


Fetch a repository’s refs/remote/trunk into FETCH_HEAD and check it out as a detached HEAD:

git fetch remote-name-or-url refs/remotes/trunk &&
git checkout FETCH_HEAD

Same, but create a named, local branch instead of using a detached HEAD:

git fetch remote-name-or-url refs/remotes/trunk &&
git checkout -b trunk-from-remote FETCH_HEAD

Same, but directly into a local branch:

git fetch remote-name-or-url refs/remotes/trunk:trunk-from-remote &&
git checkout trunk-from-remote

If you are working with a configured remote, you can rewrite its remote.<remote-name>.fetch configuration and add an extra entry to automate fetching from both refs/heads/ and refs/remotes/.

# fetch branchs of remote into remote-name/heads/*
git config remote.remote-name.fetch '+refs/heads/*:refs/remotes/remote-name/heads/*' &&
# fetch remotes of remote into remote-name/remotes/*
git config --add remote.remote-name.fetch '+refs/remotes/*:refs/remotes/remote-name/remotes/*'

To avoid possible collisions, the above example configures fetch to store refs into disjoint namespaces (…/heads/ and …/remotes/). You can pick different names if you like. If you are sure there will be no conflicts, you can even stuff them both directly under refs/remotes/remote-name/.

Chris Johnsen
  • 214,407
  • 26
  • 209
  • 186
  • Can I set this up so it automatically pulls the remote's remote branch into a tracking local branch? Or am I better off making sure the remote have local tracking branches of its own, which I then track locally? – Hans Sjunnesson Jun 14 '10 at 12:20
  • @Hans: I have rewritten the answer. I de-emphasized the “unconfigured remote” aspect that was probably not so important to you and added a bit at the end about automating the fetch. – Chris Johnsen Jun 14 '10 at 12:39
  • How do I set up a local branch to track one of those remote remote branches? I do a proper 'git checkout -b trunk --track repo/remotes/trunk', but then a 'git pull repo' won't understand my branch.trunk.merge config. I have to do a 'git pull repo refs/remotes/trunk:refs/remotes/repo/remotes/trunk' for it to work. – Hans Sjunnesson Jun 15 '10 at 07:10
  • I got it working. I had set up fetching the heads of the remote wrong, which probably meant git couldn't figure out what refs/remotes/trunk referred to. – Hans Sjunnesson Jun 15 '10 at 10:29
6

Good question! I know that this works; can't think of anything else that does off the top of my head:

git fetch origin refs/remotes/trunk
git checkout FETCH_HEAD
# or make a branch to check out
git checkout -b remote-trunk FETCH_HEAD

It's odd, by the way, that those remote refs aren't of the form refs/remotes/<remote-name>/<branch-name>... maybe I misunderstood the names, but the method does work.

Cascabel
  • 479,068
  • 72
  • 370
  • 318
4

Actually, I've found a satisfying solution to this. Adding a remote sets up a refspec to fetch and pull its local heads. I set up another remote which I call /repo-remotes/ which fetch the remote's remote refs. The .git/config file ends up looking like this

[remote "repo"]
  url = ssh://git@<hostname>:<port>/repo
  fetch = +refs/heads/*:refs/remotes/repo/*

[remote "repo-remotes"]
  url = ssh://git@<hostname>:<port>/repo
  fetch = +refs/remotes/*:refs/remotes/repo-remotes/*

I can then do this.

$ git fetch repo-remotes
$ git checkout -b remote-trunk --track remotes/repo-remotes/trunk

Which sets up a local branch tracking the remote repository's remote branch /trunk/.

Hans Sjunnesson
  • 21,745
  • 17
  • 54
  • 63
-1

git.exe checkout --track -b trunk refs/remotes/trunk

too
  • 3,009
  • 4
  • 37
  • 51