Git – 忽略文件的 4 种方法
使用 .gitignore 并不是适用于所有用例的良好解决方案。还有其他替代方法。
1. 问题
在使用 Git 等版本管理工具时,通常有两种情况,您希望版本管理工具 Git 忽略对工作目录或文件本身的更改。
- 垃圾文件
- 本地版本文件
在第一种情况中,通常您会有构建过程的输出、中间文件或构建的最终结果。这些文件是您希望“不跟踪”的,也就是说,Git 完全不跟踪这些文件。所以,您希望它们“不跟踪”。
在第二种情况中,通常您会有本地版本与跟踪版本不同的文件,但您不希望将您的本地更改提交到 Git。一个例子是,如果您使用诸如 web.config 之类的配置文件,其中包含您的数据库连接字符串。您希望跟踪该文件,因为它应用程序的重要部分,但您希望忽略对本地系统的更改,因为您的本地版本将包含每个开发人员在该项目上不同的本地设置。所以,您希望它们“跟踪,忽略本地更改”。
2. Git 中有四种忽略文件的方法
以下是 Git 中忽略文件的四种方法:
- 使用 .gitignore(全局不跟踪)
- 使用 .git/info/exclude(本地不跟踪)
- 使用
assume-unchanged
(跟踪,忽略本地更改) - 使用
skip-worktree
(跟踪,忽略本地更改)
3. 示例项目
我们设置了一个小型项目来演示这篇文章。
我们使用了 GUI 工具 SourceTree
来添加和提交文件。
4. 方法 A - 使用 .gitignore
4.1. 概述
.gitignore 文件的使用非常普遍,并且在其他地方已有详细的描述,因此我将不再赘述。仅需提及,此方法旨在应用于您希望“全局不跟踪”的文件。.gitignore 中的文件会被所有使用该存储库的系统完全忽略。
您需要添加 .gitignore 文件,并在该文件中添加您要忽略的文件。您需要将 .gitignore 添加并提交到 Git。
此方法可应用于不跟踪且您希望忽略的文件。尝试将此方法用于已由 Git 跟踪的文件是不合适的。向 .gitignore 添加已跟踪的文件将不会产生任何结果。有人可能会想,如果我将已跟踪的文件添加到 .gitignore,那么它将从那时起不会被跟踪,但事实并非如此。
4.2. 示例
假设我们有一个 spam1.txt 文件,我们不希望跟踪它。SourceTree
会显示它存在。
您需要添加 .gitignore 文件,并在该文件中添加您要忽略的文件。您需要将 .gitignore 添加并提交到 Git。现在的情况是这样的:
因此,SourceTree
不再显示 spam1.txt。它确实显示了一个额外的文件 .gitignore。所以文件 spam1.txt 是“全局不跟踪”的。
5. 方法 B - 使用 .git/info/exclude
5.1. 概述
您需要添加 .git/info/exclude 文件,并在该文件中添加您要忽略的文件。格式与 .gitignore 文件的格式相同。
此方法与 .gitignore 方法非常相似,只是 .git/info/exclude 文件本身不属于存储库,因此其影响是局部的。此方法旨在应用于您希望“本地不跟踪”的文件。
5.2 示例
假设我们有一个 spam2.txt 文件,我们不希望跟踪它。SourceTree
会显示它存在。
您需要添加 .git/info/exclude 文件,并在该文件中添加您要忽略的文件。格式与 .gitignore 文件的格式相同。现在的情况是这样的:
SourceTree
不再显示 spam2.txt 文件。因此,文件 spam2.txt 是“本地不跟踪”的。
6. 方法 C - 使用 assume-unchanged
6.1. 概述
assume-unchanged
选项最初是为了提高性能而设计的,但经常在忽略文件的解决方法中被提及。您明确告诉 Git 不检查文件是否已被更改。此方法旨在应用于您希望“跟踪,忽略本地更改”的文件。
以下是您需要的命令
To ignore local changes to tracked files:
git update-index --assume-unchanged [<file>...]
To track local changes again:
git update-index --no-assume-unchanged [<file>...]
To list all files assumed unchanged:
git ls-files -v | grep '^[[:lower:]]'
仅需提及,互联网上的一些文章 [3] 强烈不鼓励使用此方法。
6.2 示例
让我们添加 config1.txt 文件并将其提交到存储库。
然后对 config1.txt 文件进行一些更改,SourceTree
将报告文件已被编辑。
在命令提示符下,您需要添加一个命令来假定文件未更改。Source tree 将不再报告文件已被编辑。
SourceTree
不再将 config1.txt 文件视为已修改,尽管该文件实际上已被本地修改。所以,文件 config1.txt 是“跟踪,忽略本地更改”。
7. 方法 D - 使用 skip-worktree
7.1. 概述
skip-worktree
选项被许多人推荐为忽略文件的正确方法。您明确告诉 Git 不检查文件是否已被更改。此方法旨在应用于您希望“跟踪,忽略本地更改”的文件。
以下是您需要的命令
To ignore local changes to tracked files:
git update-index --skip-worktree [<file>...]
To track local changes again:
git update-index --no-skip-worktree [<file>...]
To list all files marked with skip-worktree:
git ls-files -v | grep ^S
7.2. 示例
让我们添加 config2.txt 文件并将其提交到存储库。
然后对 config3.txt 文件进行一些更改,SourceTree
将报告文件已被编辑。
在命令提示符下,您需要添加 skip-worktree
命令。Source tree 将不再报告文件已被编辑。
SourceTree
不再将 config2.txt 文件视为已修改,尽管该文件实际上已被本地修改。所以,文件 config2.txt 是“跟踪,忽略本地更改”。
8. 结论
具有“跟踪,忽略本地更改”文件用例非常强大。仅需提及 web.config 文件,每个 ASP.NET 开发人员都会在本地对其进行修改,至少会修改数据库连接字符串。在这种情况下,使用 .gitignore 将无法解决问题。适当的方法是使用 Git 中的 skip-worktree
选项。
Git 有很多选项,但命令行界面并不用户友好。令人失望的是,即使是 GUI SourceTree
也不能提供例如上下文菜单选项来设置文件的“本地更改不跟踪”标志。
9. 参考文献
- [1] https://stackoverflow.com/questions/1753070/how-do-i-configure-git-to-ignore-some-files-locally
- [2] https://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html
- [3] https://stackoverflow.com/questions/23097368/git-ignore-vs-exclude-vs-assume-unchanged
- [4] https://avdi.codes/keep-local-modifications-in-git-tracked-files/
10. 历史
- 2023 年 6 月 30 日:初版