146

Best to be explained at an example: I am on branch 0.58 of repository and this his how I pull:

git pull origin 0.58

When I just call "git pull", I get:

ip238:openlierox az$ git pull
You asked me to pull without telling me which branch you
want to merge with, and 'branch.0.58.merge' in
your configuration file does not tell me either.  Please
name which branch you want to merge on the command line and
try again (e.g. 'git pull <repository> <refspec>').
See git-pull(1) for details on the refspec.

If you often merge with the same branch, you may want to
configure the following variables in your configuration
file:

    branch.0.58.remote = <nickname>
    branch.0.58.merge = <remote-ref>
    remote.<nickname>.url = <url>
    remote.<nickname>.fetch = <refspec>

See git-config(1) for details.

Seems I probably forgot some option (--track ?) when I checked that branch out. Anyway, I have set this now:

git config branch.0.58.merge 0.58
git config branch.0.58.remote origin

And this seems to work. Then, just because of interest, I took a look at some other branch about these setting:

ip238:openlierox az$ git config branch.0.57.merge
refs/heads/0.57
ip238:openlierox az$ git config branch.0.57.remote
origin

I was wondering now, is there a difference between "0.58" or should I specify "refs/heads/0.58"?

What is the difference exactly?

Arend v. Reinersdorff
  • 4,110
  • 2
  • 36
  • 40
Albert
  • 65,406
  • 61
  • 242
  • 386
  • 2
    Just to adress the typo in the title *(without messing with an old title by modifying it now)*, it should read **"refs/heads/branchname"**, `heads` with an "s". – Romain Valeri Dec 20 '19 at 14:44

5 Answers5

186

A ref is anything pointing to a commit, for example, branches (heads), tags, and remote branches. You should see heads, remotes, and tags in your .git/refs directory, assuming you have all three types of refs in your repository.

refs/heads/0.58 specifies a branch named 0.58. If you don't specify what namespace the ref is in, git will look in the default ones. This makes using only 0.58 conceivably ambiguous - you could have both a branch and a tag named 0.58.

Cascabel
  • 479,068
  • 72
  • 370
  • 318
  • 6
    Thanks a lot, this explains it very well. It just worked with the simple "0.58" as there is no such named tag. – Albert Oct 06 '09 at 16:41
  • 2
    Right, it will essentially always be completely fine, but it's good to be safe. – Cascabel Oct 06 '09 at 16:45
  • 18
    Here's all of them for clarity: `refs/heads/` and `refs/remotes/` and `refs/tags/` – Jim Aho Mar 14 '19 at 12:16
  • If anyone is confused what "branches (heads)" as I was - head vs HEAD explained here https://stackoverflow.com/a/4381549/8888320 – nCardot Sep 17 '21 at 14:35
56

Just for somebody who is curious - git show-ref, which is available since Git v1.8.2.2, will show you all references you have in your local repository.

Artem Dolobanko
  • 2,089
  • 2
  • 19
  • 21
39

See, branchName needs to be fully resolved before GIT can actually identify it. The fully resolved name will be refs/heads/branchName.

One of the famous commandsgit checkout branchName actually automatically resolves it fully to identify where you want to checkout. Note that it does it automatically hence we never write it fully on our own.

How does it do that ? Let us look here

refname :, e.g. master, heads/master, refs/heads/master

A symbolic ref name. E.g. master typically means the commit object referenced by refs/heads/master. If you happen to have both heads/master and tags/master, you can explicitly say heads/master to tell Git which one you mean. When ambiguous, a <refname> is disambiguated by taking the first match in the following rules:

1.If $GIT_DIR/<refname> exists, that is what you mean (this is usually useful only for HEAD, FETCH_HEAD, ORIG_HEAD, MERGE_HEAD and CHERRY_PICK_HEAD);

2.otherwise, refs/<refname> if it exists;

3.otherwise, refs/tags/<refname> if it exists;

4.otherwise, refs/heads/<refname> if it exists;

5.otherwise, refs/remotes/<refname> if it exists;

6.otherwise, refs/remotes/<refname>/HEAD if it exists.

So by above 6 steps , it tries to resolve what is this branchName. Hence we never need to give a fully resolved branchName to it.

Look here and here too.

Also, go in your .git directory and see inside the ref folder.

jaume
  • 381
  • 1
  • 5
  • 11
Number945
  • 4,631
  • 8
  • 45
  • 83
0

Consider "branchname" is Harry, Then

Harry is a pointer which is simply used to point the latest commit of that branch.

Whereas refs/heads/Harry is a kind of history tracker which tracks each and every activity done using the Harry pointer.It can be any activity like commit,switching to other branch,pushing the content of branch etc.

0

The other difference is:

  • branchname (like --no-all or --no-remote) can represent an "invalid type" ref: git branch --no-all or git branch --no-remotes look like a legitimate option, but they are not. And it is then interpreted by Git as a "branch name".
  • refs/heads/branchname is immediately seen as invalid with those non-existent options (refs/heads/--no-all or refs/heads/--no-remotes: makes no sense)

With Git 2.42 (Q3 2023), the command line parser rejects those as invalid options, not "invalid branch name".

See commit e12cb98 (18 Jul 2023) by Junio C Hamano (gitster).
(Merged by Junio C Hamano -- gitster -- in commit 9a5e3b5, 26 Jul 2023)

branch: reject "--no-all" and "--no-remotes" early

As the command line parser for "git branch --all"(man) forgets to use PARSE_OPT_NONEG, it accepted "git branch"(man) --no-all, and then passed a nonsense value to the underlying machinery, leading to a fatal error "filter_refs: invalid type".
The "--remotes" option had exactly the same issue.

Catch the unsupported options early in the option parser.

The error message will be:

unknown option --no-all
unknown option --no-remotes

(Instead of "filter_refs: invalid type")

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250