What is the meaning of :/ (colon, forward slash) in the 2.0 version of git add --update syntax?
Edit, Nov 2019: I've replaced this answer as the original was more wrong than right, really.
The :/
syntax for git add
uses what Git calls a pathspec. Pathspecs are defined in the gitglossary. It's worth mentioning that :
and :/
have an entirely different meaning in gitrevisions syntax, which is used by many other commands, but not by git add
. For these other uses, see VonC's answer.
In pathspecs, the colon character :
is supposed to be followed by either the long form or the short form of various modifiers. After the modifiers, whatever is left over is either a pattern, or a simple string that gets treated as a file name.
:/
uses the short form. In the short form, each recognized character after the colon has some special meaning. The /
character means at the top of the work-tree.1
Any unrecognized characters after the colon are part of the left-over stuff. In this case, the entire sequence is colon-and-slash, so nothing is left over. However, if you wrote :/README
, that would mean the file README in the top of the work-tree.
That is, suppose you're in the sub-directory (sub-folder) named sub/
, and it has a README
file as well. Then:
git add README
adds sub/README
(because you're in sub
), but:
git add :/README
or:
git add ../README
adds the top-level file.
For each short-form expression, there's a long-form variant. There are long-form variants that do not have short-forms, though. To use the long-form variant, write a colon, then an open parenthesis (
, then as many long-form names as you like, separated by commas. End the sequence with a clone parenthesis )
.2 For instance, you can write :(top,icase)readme
to mean a file named readme
, or ReadMe
, or README
, or any other crazy mixed case, at the top of the work-tree. Some command-line interpreters may require quotes around parenthesized expressions: git add ":(top,icase)readme"
.
The empty string, in this particular case, has the same meaning as .
to Git. So :/:
or :(top)
means the same as :/:.
or :(top).
. This names every file in the work-tree.3 Leaving off the terminating :
in the pathspec syntax is OK, so :/
also means every file in the work-tree.
1There are—at least currently—only two other special characters, !
and ^
, which both mean "exclude". So with the colon form, you can write :/
or :^
or :!
, or combine them with :/!
.
You can terminate the short form with a second colon, i.e., you can write :/:!
if you want to add the file named !
that is at the top of the work-tree. The pathspec :/!:!
means do not add the file !
that is at the top of the tree; this would only be meaningful if you said to add multiple top-of-tree files, e.g., git add :/!:! :/:.
would add all files except the top-level file !
.
2Do not add another colon at the end of the long form. That is, :/:
is correct, and :(top)
is correct, but :(top):
is wrong! This trips me up now and then.
3The usual .gitignore
rules apply, of course. Remember that any tracked file—any file that is in the index right now—is never ignored!
Sidebar: removed files
As I recall, Git 1.x and 2.0 differ in treatment of files that were in the previous commit, are currently tracked (i.e., are present in the index, visible with git ls-files --stage
for instance), but—for whatever reason—are not in the work-tree right now.
The behavior in Git 2.0 is that files removed from the work-tree tend to get removed from the index. For instance, suppose we run:
$ git checkout master
and get a file named file
in the work-tree as a result of the tip commit of master
containing the file named file
. Then we do:
$ rm file
so that file
is still in the index but is no longer in the work-tree. A git status
at this point will say:
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: file
no changes added to commit (use "git add" and/or "git commit -a")
Various forms of git add
will now remove the file file
from the index. That includes git add :/
as well as git add file
:
$ git add :/
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: file
If you don't want this removal "added" to the index, you have a number of options, including the --ignore-removal
option:
$ git reset --hard
HEAD is now at 29c2e68 initial
$ git add --ignore-removal :/
$ git status
On branch master
nothing to commit, working tree clean
So if you are using :/
but want to skip updating (i.e., removing) removed files, use --ignore-removal
. The default in Git 2.x is to "add the removal" as well.
The :/
is not the only new syntax, you also have
:!
:(exclude)
Making 'git log' ignore changes for certain paths
So the :
signifies that a pathspec is immediately following. Then you have /
, also known as the
root directory, or perhaps in this case representing the root of the repository.
The first answer is not completely correct. In the context of git-add
, the :/
cannot be a revision. It is a pathspec. See my answer to the related question "What does "git add -A :/" do?".
pathspec is defined in gitglossary(7).