Search code examples
git

What does the "at" @ sign/symbol/character mean in Git?


The at-sign @ is often used in git to specify revisions in different ways. For example,

  1. <ref>@{<date>} specifies the reference at its state on <date>.

    Example: git diff master@{yesterday} master.

  2. <ref>@{<n>} specific the reference at its nth prior state.

    Example: git diff master@{1} master.

  3. @{-<n>} specifies the nth previously checked-out branch before the current one.

    Example: git checkout @{-5}.

  4. <ref>@{upstream} specifies the upstream branch for the reference.

    Example: git diff master@{upstream} master.

However, the @ is being used in other ways in git commands too, like

git rebase -i @~4
git log @^^..@

What does the at-sign @ mean in those examples?


Solution

  • As of Git version 1.8.5, the at-sign @, without a leading branch/reference name and ordinal {n} suffix like HEAD@{1} and master@{1}, is just a synonym/alias/shortcut for the special Git reference HEAD:

    Instead of typing four capital letters "HEAD", you can say "@" now, e.g. "git log @".

    So for these commands

    git rebase -i @~4
    git log @^^..@
    

    you can simply substitute the first occurrence of @ with HEAD (or head if using Windows or OS X)

    git rebase -i HEAD~4
    git log HEAD^^..HEAD
    

    So what does HEAD mean? As explained by the official Linux Kernel Git documentation for specifying Git revisions, HEAD is a special shortcut reference for the commit that you currently have checked-out as your working copy (or in Git terms, your "working tree"):

    HEAD names the commit on which you based the changes in the working tree.

    You can also read these other Stack Overflow questions on what the special reference HEAD means:

    1. HEAD and ORIG_HEAD in Git.
    2. What is git HEAD, exactly?.

    VonC also found interesting information about why @ was chosen as a shortcut for head in this Stack Overflow answer (the last section at the bottom).

    Note that like it often happens with Git, while @ is a convenient shortcut, it isn't always a valid replacement for HEAD. Example:

    $ git bundle create temp.bundle @
    Enumerating objects: 25, done.
    Counting objects: 100% (25/25), done.
    Compressing objects: 100% (20/20), done.
    Total 25 (delta 3), reused 0 (delta 0), pack-reused 0
    
    $ git bundle list-heads temp.bundle
    c006e049da432677d1a27f0eba661671e0524710 refs/heads/master
    
    $ git bundle create temp.bundle HEAD
    Enumerating objects: 25, done.
    Counting objects: 100% (25/25), done.
    Compressing objects: 100% (20/20), done.
    Total 25 (delta 3), reused 0 (delta 0), pack-reused 0
    
    $ git bundle list-heads temp.bundle
    c006e049da432677d1a27f0eba661671e0524710 HEAD
    

    In this case, using @ is more like a replacement for master (the branch that HEAD happened to be pointing to) rather than for HEAD. If you try to fetch from the resulting bundle later, you'll have to specify the ref you want to fetch (master) if you used @, and you won't have to to it if you specified HEAD explicitly.