Why Git use 2 different commands to show HEAD?

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:

  • Why am I getting “: No such file or directory” when trying to execute a bash script?
  • git ignores $GIT_AUTHOR_DATE — is this a bug?
  • GIT: clone works, remote push doesn't. Remote repository over copssh
  • What does it mean when it says a git step is “1 ahead”
  • How to make git mark a deleted and a new file as a file move?
  • Complex setup for GIT: fork from Github to Bitbucket, PUSH to Bitbucket only
  • 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?

  • How do you allow multiple people to push to github?
  • Using git and svn with multiple developers
  • Installing Git on OS X
  • Git create branch from range of previous commits?
  • Configure Git With Existing Keys
  • Github: how to fork after cloning?
  • 2 Solutions collect form web for “Why Git use 2 different commands to show HEAD?”

    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.

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

    Git Baby is a git and github fan, let's start git clone.