git rm 命令可以删除文件,那么它删除的是 index 还是 工作区呢,和手动删除文件有什么区别呢?相信你也有这些疑惑,请接着往下看。
Remove files from the working tree and from the index
说明 git rm 既能删除 Index 也能删除工作区的文件。
$ git rm -h
usage: git rm [<options>] [--] <file>...
-n, --dry-run dry run
-q, --quiet do not list removed files
--cached only remove from the index
-f, --force override the up-to-date check
-r allow recursive removal
--ignore-unmatch exit with a zero status even if nothing matched
操作试验
$ git status
On branch master
nothing to commit, working tree clean
查看 index 中的文件
$ git ls-files
a/b/c/t3.txt
q/w/t4.txt
t1.txt
t2.txt
t5.txt
修改 t5.txt
$ git rm t5.txt
error: the following file has local modifications:
t5.txt
(use --cached to keep the file, or -f to force removal)
发现删不掉,加上 -f 强制删除
$ git rm -f t5.txt
rm 't5.txt'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: t5.txt
$ git ls-files
a/b/c/t3.txt
q/w/t4.txt
t1.txt
t2.txt
可见 index 和 工作区 都被删掉了,git rm 只会产生变动,但是并没有提交。
$ git commit -m 'rm'
$ git status
On branch master
nothing to commit, working tree clean
现在删除 a/b/c/t3.txt 文件
$ git rm a/b/c/t3.txt
rm 'a/b/c/t3.txt'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: a/b/c/t3.txt
$ git commit -m 'rm'
[master c82f70a] rm
1 file changed, 1 deletion(-)
delete mode 100644 a/b/c/t3.txt
修改 t2.txt,并 add
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: t2.txt
$ git ls-files
q/w/t4.txt
t1.txt
t2.txt
$ git rm t2.txt
error: the following file has changes staged in the index:
t2.txt
(use --cached to keep the file, or -f to force removal)
可见只要某个文件在 index 或者 工作区 有变动都是不能删除的,必须加上 -f 参数。
另外,--cached 参数会将文件从 index 删除,变成 Untracked 状态,依然是没有提交,接着上面的场景。
$ git ls-files
q/w/t4.txt
t1.txt
t2.txt
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: t2.txt
$ git rm --cached t2.txt
rm 't2.txt'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: t2.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
t2.txt
于是 t2.txt 从 index 删除了,待提交,同时,文件还在工作区中,处于 Untracked 状态。
所以 git rm 会先删除工作区的文件,然后调用 add 将变动添加到 index;跟你手动删除是不一样的。
如果文件从工作区删了,此时 index 处于变动状态,还没有提交,如果想恢复呢?
$ git rm t2.txt
rm 't2.txt'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: t2.txt
$ git ls-files
q/w/t4.txt
t1.txt
显然 t2.txt 已经不在 index 中,我们尝试使用 git checkout 来恢复
$ git checkout -- t2.txt
error: pathspec 't2.txt' did not match any file(s) known to git
那是因为使用 git checkout 来放弃变动实际上是以当前 index 来恢复工作区而已,而 t2.txt 并不在当前 index 中。此时只能从版本
库恢复index再恢复工作区。
$ git reset -- t2.txt
$ git status
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: t2.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git ls-files
q/w/t4.txt
t1.txt
t2.txt
$ git checkout -- t2.txt
当然 git rm 也可以删除目录,如果想递归删除的话加上参数 -r