5

I noticed there are 2 HEADs:

  • .git\HEAD
  • .git\refs\remotes\origin\HEAD

When I use git show-ref HEAD, it only gives me this:

ce0762c073b407d794f54f0b5d2a50375fdcb609 refs/remotes/origin/HEAD

Whle when I use git rev-parse HEAD, it gives me the value of .git\HEAD:

a758e523fe40e799194878bac567b7f4b8eec2b9

Why Git use 2 different commands to show HEAD? Any strong reason?

Adnan Y
  • 2,982
  • 1
  • 26
  • 29
smwikipedia
  • 61,609
  • 92
  • 309
  • 482

2 Answers2

8

git-show-ref shows a list of references in your repository and their commit IDs. It should probably be called git-show-refs. It's preferred over directly referencing files in the .git directory.

When you say git show-ref HEAD you're not asking for HEAD. What you're asking for is any references in the list which match the pattern HEAD. HEAD itself is normally filtered out, so you get refs/remotes/origin/HEAD. You can include HEAD with --head.

$ git show-ref --head HEAD
f37beeea95f3b0e6b064f6d4b5f835a058e0568c HEAD
aa1124b89f38eed793e2b9f2d2b2ba5d80a27a20 refs/remotes/origin/HEAD

So you shouldn't be using git show-ref <ref> to look up references.


git-rev-parse takes a revision parameter and gives back a commit ID. Its meant to deal with the myriad different ways you can refer to a commit. For example...

$ git rev-parse --verify master
aa1124b89f38eed793e2b9f2d2b2ba5d80a27a20
$ git rev-parse --verify heads/master
aa1124b89f38eed793e2b9f2d2b2ba5d80a27a20
$ git rev-parse --verify refs/heads/master
aa1124b89f38eed793e2b9f2d2b2ba5d80a27a20

git rev-parse --verify <ref> is what you should be using to look up the commit ID of a reference.

Schwern
  • 153,029
  • 25
  • 195
  • 336
3

.git/HEAD is used by Git to hold the current ref. So when you're on master, it will be ref: refs/heads/master. When you are on detached HEAD, it will be a commit's hash.

.git/refs/remotes/origin/HEAD is actually a remote ref that points to the default branch on remote. When master is the default remote branch, it will be ref: refs/remotes/origin/master (if your remote is origin). It's possible to have a default remote branch other than master but I have noticed that it will not correctly reflect that.

But

$ git remote show github

will always tell you the correct default remote branch.

See this answer of How does origin/HEAD get set? for more details.

git show-ref shows you refs, which are local branches, remote branches, tags, stash refs.

With

git show-ref HEAD

Git is using the "HEAD" as pattern

git show-ref [-q|--quiet] [--verify] [--head] [-d|--dereference]
         [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags]
         [--heads] [--] [<pattern>…​]

and only showing refs that match.

See git-show-ref doc.

I mostly use git branch with -a or -r options to see branches, git tag to see tags, and rarely use git show-ref.

hIpPy
  • 4,649
  • 6
  • 51
  • 65