将所有文件都添加到提交中,除了一个单独的文件?

845

我有一堆文件在一个变更集中,但我想特别忽略一个修改过的文件。在 git status 之后看起来像这样:

# modified:   main/dontcheckmein.txt
# deleted:    main/plzcheckmein.c
# deleted:    main/plzcheckmein2.c
...

我能否在执行git add命令时忽略一个我不想处理的文本文件?类似这样:

git add -u -except main/dontcheckmein.txt

2
“-u”标志的目的是什么?它可以在没有“-u”的情况下工作吗? - Saad Abbasi
3
从 man git add: -u, --update “仅在索引中已有匹配项的位置更新。这将删除以及修改索引条目以匹配工作树,但不添加新文件。...”</pathspec> - Simeon
5
也许这个来自https://github.com/git-guides/git-add的表格更好地解释了-u命令: git add -u:只缓存新建和修改的文件,不包括已删除的文件。 - Simeon
3
如果您有未被追踪的文件,则使用“-u”选项确保这些文件不会被添加。而“git add --all”则会添加所有未被追踪的文件。 - Simeon
20个回答

1120
git add -u
git reset -- main/dontcheckmein.txt

注意:Git后来添加了特殊的语法,其他答案中有解释。


46
如何排除整个文件夹?--是 main 还是 main/ 还是 main/* ? - Alan Coromano
16
@MariusKavansky,您可以使用这些表单。如果您使用 main/*,则需要在其前面添加 --,以让Git知道它是一个路径。另外两种变体可以在不包括这两个破折号的情况下工作。(在Windows 7上的命令提示符上使用msysGit进行测试) - Dennis van der Schagt
2
如果您有一些包含大量文件或其他文件夹的要排除的文件夹:暂时将它们添加到您的gitignore中。之后对这些文件夹执行git reset仍然有效,但是Git需要很长时间才能添加大型文件夹。 - Michahell
2
那么,没有一行代码的解决方案吗? - BroVic
13
@Ben Jackson,逐行评论一下会更好,你觉得呢? - ed1nh0
显示剩余6条评论

329

现在 git 支持通过路径规范魔法 :(exclude) 和其简写形式 :! 来排除特定的路径和文件。因此,您可以轻松地使用以下命令实现。

git add --all -- :!main/dontcheckmein.txt
git add -- . :!main/dontcheckmein.txt

实际上,您可以指定更多:

git add --all -- :!path/to/file1 :!path/to/file2 :!path/to/folder1/*
git add -- . :!path/to/file1 :!path/to/file2 :!path/to/folder1/*

对于 Mac 和 Linux,将每个文件/文件夹路径用引号括起来。

git add --all -- ':!path/to/file1' ':!path/to/file2' ':!path/to/folder1/*'

57
太棒了!请注意,在Linux上,您需要引用 :!... 条款以防止shell抱怨。因此,例如:git add --all -- ':!path/to/file1' ':!path/to/file2' ':!path/to/folder1/*' - Martin_W
5
这与zsh中的某些内容冲突,在我的macOS和最新的git上无法工作。 - Merlin
2
没有在 :!... 周围加引号,我在 Windows 10 Git Bash 中也遇到了 event not found 错误。请参考 @Martin_W 的评论。 - Nuhman
6
这是最好的答案。如果需要排除一个包含大量文件的大文件夹,则添加和重置需要很长时间。git add -- . ':!<path>' 更快。 - jolammi
2
git add . --:!path/to/file 也能行吗?git add .git add -- . 有区别吗?第一个 --. 前面是必须的吗? - Matt
显示剩余6条评论

194

1) 忽略已经版本控制的单个文件的更改

git update-index --assume-unchanged "main/dontcheckmein.txt"

并撤销 git update-index --no-assume-unchanged "main/dontcheckmein.txt"

GitHub 文档:忽略文件

2) 忽略一个特定的文件,防止它被创建到仓库中

首先,查看这篇 stackoverflow 帖子:Git global ignore not working

.gitignore 中,添加到该文件的相对路径,不包括前导 ./

因此,如果您的文件位于 MyProject/MyFolder/myfile.txt(其中 .git 也在 MyProject 文件夹中),则将 MyFolder/myfile.txt 添加到您的 .gitignore 文件中。

可以使用 git check-ignore "MyFolder/myfile.txt" 确认与忽略相关的规则

关于全局忽略

该链接讨论了 ~/.gitignore_global,但该文件与您的项目有关。因此,如果您在 ~/.gitignore_global 中放置排除模式 MyFolder/myfile.txt,它将起作用,但不会有太多意义...

另一方面,如果您使用 git config core.excludesfile .gitignoreMyProject 中设置您的项目,那么本地文件将覆盖 ~/.gitignore_global,后者可以拥有极其有用的规则...

因此,现在,最好编写一些脚本,将您的 .gitignore~/.gitignore_global 混合到 .gitignore 中。

最后警告
如果您想要忽略的文件已经在仓库中,则除非您执行以下操作:git rm "MyFolder/myfile.txt",否则此方法将无法工作。请先备份它,因为它也将在本地删除!稍后可以将其复制回来...


6
你可以使用git rm --cached MyFolder/myyfile.txt将文件从版本库中删除,但在本地保留它。有关说明,请参见help.github.com - Dennis van der Schagt
我该如何再次添加这些文件? - SagarM
我想知道这个命令 git update-index --assume-unchanged "main/dontcheckmein.txt" 存储在 git 文件夹结构中的哪里。 - MaXi32

113

对于一个文件

git add -u
git reset -- main/dontcheckmein.txt

对于一个文件夹

git add -u
git reset -- main/*

19
为什么需要加上“-u”参数?为什么不直接使用“git add . && git reset -- main/*”命令? - user5047085
3
-u选项仅更新索引中与<pathspec>匹配的条目。这将删除并修改索引条目以匹配工作树,但不添加新文件。如果在使用-u选项时未给出<pathspec>,则会更新整个工作树中所有已跟踪的文件(旧版本的Git只更新当前目录及其子目录)。 - Farhad Mammadli
18
为了让非 Git 专业人士理解,有人能否解释一下为什么在语言中需要使用 -u?(请注意:这是正在翻译的内容,不包括解释或其他内容。) - Patrick
8
-u用于引用您正在推送到的当前分支。在下一次推送时,您将不再需要键入git push origin master,只需键入git push,Git 将知道它在主分支中。希望能对你有所帮助。 - Pepeng Hapon

30

Git提供:(exclude)路径规范前缀以排除特定路径。

其短魔术签名是:^
文档:https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-exclude

git add . :^main/dontcheckmein.txt

这个帖子中的一些答案提到了:!,这也可以工作,但是只有在引号内。通常来说,!被认为是shell扩展中糟糕的字符。


如果你和我一样——总是使用-p标志审查要提交的更改,并在git add命令中使用:^魔术签名,也同样如此:

git add -p . :^main/dontcheckmein.txt

同意... ^ 看起来不像 ! 那么可怕。 - hustnzj
git add -- . '!:foldername' 对我有效。谢谢。 - Victor Eke

22
虽然Ben Jackson是正确的,但我想补充一下我如何使用该解决方案。以下是我使用的非常简单的脚本(称为gitadd),用于添加除了我在名为.gittrackignore的文件中列出的几个选择之外的所有更改(非常类似于.gitignore的工作方式)。
#!/bin/bash
set -e

git add -A
git reset `cat .gittrackignore`

这是我的当前.gittrackignore文件的样子。

project.properties

我正在处理一个Android项目,当部署时需要从命令行编译。这个项目依赖于SherlockActionBar,因此需要在project.properties中引用,但这会干扰编译,所以现在我只需键入gitadd并添加所有更改到git中,而无需每次取消添加project.properties。


直到看到你的评论,我才知道--是什么。根据man手册,它是可选的,并且不会改变命令的结果(至少在这种情况下)。这个问题似乎支持这一点,https://dev59.com/02Mm5IYBdhLWcg3wMssp.如果我错了,请纠正我,但它似乎意味着“将--之后的任何内容视为参数,而不是选项/开关”。 - Anthony Naddeo
在那个问题中,git checkout 中的 -- 使用得很好。直到我们的交流,我才知道双破折线是什么意思。我想知道 git checkout 在分支和文件之间的歧义是否也会以这种或其他形式影响 git reset - Giulio Piancastelli

18
为保留文件更改但不提交,我执行以下操作:

git add .

git reset -- main/dontcheckmein.txt

git commit -m "commit message"

验证文件是否被排除,请执行以下命令:

git status


通过执行命令 git add . 将所有文件添加到暂存区后,输入 git status 命令会建议您执行 git restore --staged main/dontcheckmein.txt。为什么 @gsumk 建议使用 reset 呢? - Simeon

14
git add .
git reset main/dontcheckmein.txt

8
我们可以添加所有文件,然后通过git reset排除需要删除的文件。
git add .
git reset -- <file_name_to_exclude>

7
使用git add -A一次性添加所有修改和新增的文件。
示例:
git add -A
git reset -- main/dontcheckmein.txt

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