The Short Answer (TL;DR)
"Tree-ish" is a term that refers to any identifier (as specified in the Git
revisions documentation) that ultimately leads to a (sub)directory
tree (Git refers to directories as "trees" and "tree objects").
In the original poster's case, foo
is a directory that he wants to
specify. The correct way to specify a (sub)directory in Git is to use this
"tree-ish" syntax (item #15 from the Git revisions documentation):
<rev>:<path>
, e.g. HEAD:README
, :README
, master:./README
A suffix :
followed by a path names the blob or tree at the given path in
the tree-ish object named by the part before the colon.
So, in other words, master:foo
is the correct syntax, not master/foo
.
Other "Tree-ish" (Plus Commit-ish)
Here's a complete list of commit-ish and tree-ish identifiers (from the Git
revisions documentation, thanks to LopSae for pointing it
out):
----------------------------------------------------------------------
| 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, :README, master:./README
----------------------------------------------------------------------
| 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
At its lowest levels, Git keeps track of source code using four fundamental
objects:
- Annotated tags, which point to commits.
- Commits, which point to the root directory tree of your project.
- Trees, which are directories and subdirectories.
- 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:
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.
As explained in the documentation (thanks to Trebor for helping
me find it):
<tree>
Indicates a tree object name.
<commit>
Indicates a commit object name.
<tree-ish>
Indicates a tree, commit or tag object name. A command that takes a <tree-ish>
argument ultimately wants to operate on a <tree>
object but automatically
dereferences <commit>
and <tag>
objects that point at a <tree>
.
<commit-ish>
Indicates a commit or tag object name. A command that takes a <commit-ish>
argument ultimately wants to operate on a <commit>
object but automatically
dereferences <tag>
objects that point at a <commit>
.
The set of tree-ish identifiers that cannot be used as commit-ish are
<rev>:<path>
, which leads directly to directory trees, not commit
objects. For example, HEAD:subdirectory
.
Sha1 identifiers of directory tree objects.
master:foo
is tree-ish, but you better usemaster foo
as i<tree-ish> <path>
. – Splintgit archive
command no longer refer to tree-ish, but when I asked this question they did. And regarding the accepted answer; at the time no one else bothered to answer the question. It was over two years later that another answer had was even posted. – Nudicaulgit archive
and they still refer to<tree-ish>
as of Git version 1.9.3. seegit help archive
. – Nudicaul$ man gitglossary
has a short explanation. Do not confuse the git tree with the filesystem tree[path...]
. – Icefall