已删除文件的暂存处理

626

假设我在git仓库中有一个名为foo的文件。

如果使用rm(而不是git rm)删除了该文件,则git状态将显示:

Changes not staged for commit:

    deleted: foo

如何分阶段删除单个文件?

如果我尝试:

git add foo

It says:

'foo' did not match any files.

更新(9年后,哈哈):

看起来这个问题已经在git 2.x中得到解决:

$ git --version
git version 2.25.1

$ mkdir repo

$ cd repo

$ git init .
Initialized empty Git repository in repo/.git/

$ touch foo bar baz

$ git add foo bar baz

$ git commit -m "initial commit"
[master (root-commit) 79c736b] initial commit
3 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bar
create mode 100644 baz
create mode 100644 foo

$ rm foo

$ git status
On branch master
Changes not staged for commit:
    deleted: foo

$ git add foo

$ git status
On branch master
Changes to be committed:
    deleted:    foo

4
旧版本的Git中是否存在此问题?现在似乎没有这个问题了,它的工作方式类似于修改后的文件。 - cst1992
@cst1992:是的,现在看起来已经修复了。git add foo现在可以工作了。请参见更新。 - Andrew Tomazos
10个回答

598

使用git rm foo来将文件标记为待删除状态。(如果这个文件之前没有被删除,它也将从文件系统中删除。当然,由于之前已经提交到了Git,因此可以从Git中还原它。)

如果想要将文件标记为待删除状态但不从文件系统中删除它,可以使用git rm --cached foo


9
你可以添加 --cache 标记,仅从代码库中删除文件,并在文件系统中不做任何更改。 - Hauleth
116
实际上,OP 问如何分阶段处理已删除的文件。您可以通过以下命令完成此操作:git status | grep 'deleted:' | cut -d':' -f2 | xargs -t -I {} git add -u "{}"。其他答案似乎展示了如何正确删除文件(但未说明如何分阶段处理已删除的文件)。请注意,基于 xargs 的命令在 Ubuntu 12.04 上对我有效,但是当我手动执行 git add -u deleted_file.txt 时无效。我的 Git 版本是 1.7.9.5。 - Dimitry K
12
即使文件已从文件系统中删除,git rm 命令也会高兴地将其标记为待删除文件并添加到暂存区。正如提问者在另一个答案的评论中指出的那样,他们想要将一个已经被删除的特定文件标记为待提交状态。 - Wooble
8
git rm 命令不会将已经被删除的文件添加到暂存区。当你执行 git rm "~$Box.SLDASM" 命令时,会出现以下错误信息:fatal: pathspec '~.SLDASM' did not match any files。下面是证明的截图链接:https://i.imgur.com/cKNKGGe.png https://i.imgur.com/1p9JdWF.png。第一张截图清楚地显示了有两个文件被删除但未被暂存,第二张截图则展示了在输入 git rm "~$Box.SLDASM" 命令时出现的错误信息。 - KulaGGin
2
@KulaGGin:读取错误信息。它并不是试图删除一个名字中带有“$Box”的文件,因为你的shell已经为你处理了这个问题。如果你要使用可怕的文件名,请添加更多引号。 - Wooble
显示剩余8条评论

480

虽然使用 git rm [FILE] 是正确的,但你也可以使用 git add -u

根据 git-add 文档:

-u --update

仅更新索引已经存在匹配项的[FILE]。这将删除并修改索引条目以匹配工作树,但不添加新文件。

如果在使用 -u 选项时未给出 [FILE],则将更新整个工作树中所有跟踪的文件(旧版本的 Git 会将更新限制在当前目录及其子目录中)。

这样,索引就会被刷新,文件也会被适当地暂存。


71
是的,git add -A .会添加所有更改,但我特别想将一个已删除的文件暂存。 - Andrew Tomazos
30
这将添加所有修改过的文件,而不仅仅是已删除的文件。 - Foreever
3
没问题。更具体地说,它将分阶段处理所有已跟踪文件中的更改,无论是已删除还是仅修改。当您删除多个文件并且不想逐个进行分阶段处理时,这很有帮助。 - Sailesh
10
有没有只提交已删除的文件而不是修改过的文件的方法?只是好奇。 - aug
22
我执行了 git add -u FolderWithDeletedFiles/,它完成了我想要的操作,谢谢。 - parliament
显示剩余2条评论

206

要显示所有手动删除的文件,您可以使用:

git rm $(git ls-files --deleted)

要将别名添加到此命令作为git rm-deleted,请运行:

git config --global alias.rm-deleted '!git rm $(git ls-files --deleted)'

7
$()符号在Windows Bash控制台中似乎不存在,导致出现“未知选项`deleted)`”的错误提示。 - Félix Adriyel Gagnon-Grenier
3
如果你的路径中有空格,我认为这种方法行不通。至少在我的系统(使用zsh)上不行。 - Wil Shipley
1
在Windows中执行以下命令:for /F %I in ('git ls-files --deleted') do git add -u %I - eis
5
如果文件名中含有空格,这种方法不起作用,如果需要可以使用 'git add -u' 命令。 - J-Dizzle
3
很小的一点建议,我只是想用“git add”替换“git rm”,因为文件已经被删除了,我只是要更新索引。 - cambunctious
显示剩余2条评论

51

自Git 2.0.0版本以来,git add命令还会将文件的删除操作添加到暂存区。

Git 2.0.0文档 - git-add

< pathspec >…

要添加内容的文件。可以使用文件通配符(例如*.c)添加所有匹配的文件。也可以给出一个前导目录名(例如dir),以更新索引以匹配整个目录的当前状态(例如指定dir将记录不仅工作树中修改了的文件dir/file1、增加的文件dir/file2,还有从工作树中删除的文件dir/file3)。请注意,旧版本的Git命令会忽略已删除的文件;如果您想添加修改或新增的文件但忽略已删除的文件,请使用--no-all选项。


1
被接受的答案并没有解决问题 - 而其他方法在Git 2.0.0之后更加繁琐 - 这是最好的方式!你有我的赞同。 - João Antunes
2
这里有一个重要的警告:类似于 git add foo/*/deleted.file 这样的命令是行不通的,因为 * 只会扩展到仍然存在的文件。但你可以使用其他不依赖于文件存在的模式,例如 git add foo/{bar,baz,quux}/deleted.file - IMSoP
3
如果文件系统中的文件已被删除,位置在 foo/*/deleted.file,您也可以通过在路径周围加上单引号来将它们暂存以供删除。这包括通配符,防止操作系统尝试扩展通配符,而是由git扩展并将已删除的文件暂存在其中:git add 'foo/*/deleted.file' - Matthias Fripp

43

你可以使用这个命令

git add `git ls-files --deleted`

解释:

git ls-files --deleted - 此命令将返回所有已删除文件的文件名。


1
如果文件名中有空格,则无法正常工作。 - Tadej Magajna

39

添加已经删除的所有文件

git status -s | grep -E '^ D' | cut -d ' ' -f3 | xargs git add --all

请检查以确保感谢已发送。

git status

你应该准备好了


7
确认这个有效。我认为这里的教训是不要使用rm <文件>,而是使用git rm <文件> - DanGordon
2
FYI:如果任何路径中有空格,剪切空格会导致问题。 - davis
2
这个命令不支持带空格的文件名,如果需要可以使用 'git add -u' 命令。 - J-Dizzle
在我的电脑上,git version 2.15.2 (Apple Git-101.1) 运行得非常完美。 - Kalob Taulien

11
您可以使用 git rm -r --cached -- "path/to/directory" 命令来暂存删除的目录。

6

Ian Mackinnon找到了答案,但使用xargs更好:

git ls-files --deleted -z | xargs -r0 git rm

作为 git 别名:
git config --global alias.rm-deleted '!git ls-files --deleted -z | xargs -r0 git rm'

这个命令使用了 xargs 和 NUL 终止符(字节保证不出现在路径中),并提供了一个选项,以避免在文件列表为空的情况下运行 git rm 命令。

这种语法也与 fish 兼容。


6
如果您想将所有已删除的文件添加到暂存区,则可以使用git add .
这是目前在git v2.27.0中最简单的方法。请注意,使用*.是不同的方法。使用git add *仅添加当前存在的文件,而git add .还会将使用rm命令删除的文件添加到暂存区。
显而易见但值得一提的是,当您使用git add .时,其他已修改的文件也将被添加到暂存区。

5

对于那些在PowerShell中使用Git 2.x+的人:

foreach ($filePath in (git ls-files --deleted)) { git add "$filePath" }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接