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/
.