163

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?

1
  • 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". Commented Dec 20, 2019 at 14:44

5 Answers 5

208

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks a lot, this explains it very well. It just worked with the simple "0.58" as there is no such named tag.
Right, it will essentially always be completely fine, but it's good to be safe.
Here's all of them for clarity: refs/heads/ and refs/remotes/ and refs/tags/
If anyone is confused what "branches (heads)" as I was - head vs HEAD explained here stackoverflow.com/a/4381549/8888320
66

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.

1 Comment

Also git log --decorate=full will show the full names of references in the history
47

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.

Comments

2

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")

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.