The following git command (which deletes all files that end in a ~) uses escape characters
git rm \*~
The rationale is that git uses it's own filename expansion in addition to the expansion used by the shell.
Does this mean the escape characters are a way to suppress the filename expansion done by the shell ?
Somehow I am not able to get a proper handle on this.
Yes, the escape character suppresses the file name expansion normally performed by the Unix shell. To answer the subquestions:
git rm
implements its own expansion likely because the files might not be present in the checked-out directory. (Think of the situation where you first rm *~
, and then remember that you also want to remove them from git
.)
Using the backslash escape character (or wrapping the argument in quotes) does exactly that — suppresses file name expansion at the shell level. This cannot be done by git
automatically because git
doesn't control your shell, by the time it is executed, the expansion is already over. The expansion must be prevented by the shell itself or, more realistically, by the end user invoking git
through the shell.
Why does git use its own filename expansion?
@user4815162342's answer is missing a key reason to escape a glob metacharacter (e.g., *
) from the shell:
git's filename expansion is recursive. Your shell's filename expansion is not. To confirm:
mkdir testA testA/testB
cd testA
touch test1.txt testB/test2.txt
git init
Now you have a directory structure and git repo to use to test recursive filename expansion. While in testA:
echo *.txt
# test1.txt
git add \*.txt
git status
# On branch master
#
# No commits yest
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: test1.txt
# new file: testB/test2.txt
You can see that filename expansion by the shell is not recursive, as echo *.txt
only expanded to text file in the testA
directory. If you had run git add *.txt
, you would have only added test1.txt
. On the other hand, filename expansion in git is recursive. When you run git add \*.txt
, suppressing the glob metacharacter from the shell and allowing git to expand it, it expands to all .txt
files in your repo, which includes subdirectories.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With