Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the meaning of :/ (colon, forward slash) in the 2.0 version of git add --update syntax?

Tags:

git

I upgraded Git a couple months ago and since then I've been receiving the following deprecation notice upon attempting git add --update:

Warning: The behavior of 'git add --update (or -u)' with no path argument from a subdirectory of the tree will change in Git 2.0 and should not be used anymore. To add content for the whole tree, run:

git add --update :/ (or git add -u :/)

To restrict the command to the current directory, run:

git add --update . (or git add -u .)

With the current Git version, the command is restricted to the current directory.

The warning itself makes perfectly good sense, and it's saved me some resetting. I've gotten used to typing the . or :/, but still find the latter quite strange because it's unlike any other command line syntax I've encountered. The . is pretty token: it just means "current directory", like in find ., but :/... never seen that except in this context. What does it mean?

I keep thinking of it as an emoticon, and certainly that's not the case?

like image 845
Dmitry Minkovsky Avatar asked Feb 22 '14 03:02

Dmitry Minkovsky


3 Answers

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

like image 131
torek Avatar answered Nov 15 '22 22:11

torek


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.

like image 26
Zombo Avatar answered Nov 15 '22 23:11

Zombo


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

like image 28
lrineau Avatar answered Nov 15 '22 22:11

lrineau