What are commit-ish and tree-ish in Git?

Note for non-native English [sic!] speakers: "-ish" is a suffix that can be applied to an adjective in order to indicate "having qualities like" or "slightly" - see http://chambers.co.uk/search/?query=ish&title=21st

Hence "tree-ish" - like a "tree" .... "commit-ish" - like a "commit"

eg "Mars appears like a reddish star" ("d" is doubled !); "the food on the plate was not hot, but warmish"

I believe that this helps explain "what are ..." better, in that it explains the language usage.


The Short Answer (TL;DR)

Here's a complete list of commit-ish and tree-ish identifiers (from the Git revisions documentation):

----------------------------------------------------------------------
|    Commit-ish/Tree-ish    |                Examples
----------------------------------------------------------------------
|  1. <sha1>                | dae86e1950b1277e545cee180551750029cfe735
|  2. <describeOutput>      | v1.7.4.2-679-g3bee7fb
|  3. <refname>             | master, heads/master, refs/heads/master
|  4. <refname>@{<date>}    | master@{yesterday}, HEAD@{5 minutes ago}
|  5. <refname>@{<n>}       | master@{1}
|  6. @{<n>}                | @{1}
|  7. @{-<n>}               | @{-1}
|  8. <refname>@{upstream}  | master@{upstream}, @{u}
|  9. <rev>^                | HEAD^, v1.5.1^0
| 10. <rev>~<n>             | master~3
| 11. <rev>^{<type>}        | v0.99.8^{commit}
| 12. <rev>^{}              | v0.99.8^{}
| 13. <rev>^{/<text>}       | HEAD^{/fix nasty bug}
| 14. :/<text>              | :/fix nasty bug
----------------------------------------------------------------------
|       Tree-ish only       |                Examples
----------------------------------------------------------------------
| 15. <rev>:<path>          | HEAD:README.txt, master:sub-directory/
----------------------------------------------------------------------
|         Tree-ish?         |                Examples
----------------------------------------------------------------------
| 16. :<n>:<path>           | :0:README, :README
----------------------------------------------------------------------

Identifiers #1-14 are all "commit-ish", because they all lead to commits, but because commits also point to directory trees, they all ultimately lead to (sub)directory tree objects, and can therefore also be used as "tree-ish".

#15 can also be used as tree-ish when it refers to a (sub)directory, but it can also be used to identify specific files. When it refers to files, I'm not sure if it's still considered "tree-ish", or if acts more like "blob-ish" (Git refers to files as "blobs").

The Long Answer

Commits and Directory Trees in Git

At its lowest levels, Git keeps track of source code using four fundamental objects:

  1. Annotated tags, which point to commits.
  2. Commits, which point to the root directory tree of your project.
  3. Trees, which are directories and subdirectories.
  4. Blobs, which are files.

Each of these objects has its own sha1 hash ID, since Linus Torvalds designed Git like an content- addressable filesystem, i.e. files can be retrieved based on their content (sha1 IDs are generated from file content). The Pro Git book gives this example diagram:

Figure 9-3 from Pro Git book

Commit-ish vs Tree-ish

Many Git commands can accept special identifiers for commits and (sub)directory trees:

  • "Commit-ish" are identifiers that ultimately lead to a commit object. For example,

    tag -> commit

  • "Tree-ish" are identifiers that ultimately lead to tree (i.e. directory) objects.

    tag -> commit -> project-root-directory

Because commit objects always point to a directory tree object (the root directory of your project), any identifier that is "commit-ish" is, by definition, also "tree-ish". In other words, any identifier that leads to a commit object can also be used to lead to a (sub)directory tree object.

But since directory tree objects never point to commits in Git's versioning system, not every identifier that points to a (sub)directory tree can also be used to point to a commit. In other words, the set of "commit-ish" identifiers is a strict subset of the set of "tree-ish" identifiers.

The set of tree-ish identifiers that cannot be used as commit-ish are

  1. <rev>:<path>, which leads directly to directory trees, not commit objects. For example, HEAD:subdirectory.

  2. Sha1 identifiers of directory tree objects.

Tags:

Git