为什么Git不会忽略我指定的文件?

324

我在.gitignore中添加了以下行:

sites/default/settings.php

但是当我输入git status命令时,它显示该文件为未暂存文件。

问题出在哪里?所有其他模式都能正常工作。


我曾经遇到过同样的问题,后来发现我的.gitignore文件保存在另一个驱动器上了 :face-palm: - Henry
把东西放在代码库里却忽略对它的更改是一个非常糟糕的想法。 - Yevgeniy Afanasyev
确保已初始化存储库。 - Dan
15个回答

649

确保你的.gitignore文件在工作目录的根目录下,并在该目录中运行git status命令,然后从状态输出中复制文件路径并将其粘贴到.gitignore文件中。

如果这样做不起作用,那么你的文件很可能已经被Git跟踪了。你可以通过git status输出来确认这一点。如果该文件未列在“未跟踪的文件”部分中,则它已由Git跟踪,并且会忽略.gitignore文件中的规则。

在Git中忽略文件的原因是为了防止它们被添加到代码库中。如果您之前添加了一个要被忽略的文件,则它将被Git跟踪,而匹配它的忽略规则将被跳过。Git这样做是因为该文件已经是代码库的一部分了。

为了真正忽略文件,您必须取消跟踪并将其从存储库中删除。您可以使用 git rm --cached sites/default/settings.php 来执行此操作。这会从存储库中删除文件,而不会物理删除文件(这就是 --cached 的作用)。提交更改后,该文件将从存储库中删除,并且应该可以正确地忽略它。

正如 @display-name below 所指出的那样,有时需要在 git rm --cached 后执行 git add . 以正确重建索引。


“工作目录的根”是什么意思?是指“.git”存储库所在的目录吗? - Jonathan Leffler
工作目录是包含.git目录的目录,它本身是存储库的根目录。例如,当您将存储库克隆到/xy/时,/xy/就是您的工作目录,其中包含/xy/.git/ - poke
9
有时候在执行完git rm --cached后,你还需要执行git add .来正确重建索引。 - Display name
检查Git状态的想法真是太棒了。我一直在Eclipse的Git暂存区中检查它,但路径不正确。谢谢! - walla
1
我需要添加-r(递归)标志,因为我也选中了嵌套文件夹。在我的情况下,我移动到git文件夹的根目录,然后运行命令git rm --cached -r .vs/,其中vs是我想要从跟踪中删除的顶级文件夹。 - RobbiewOnline

167

我遇到了这个问题,这是一个老问题,但是我想要追踪那个文件,但不想在某些工作副本上追踪它,为此您可以运行:

git update-index --assume-unchanged sites/default/settings.php

9
这实际上是我想要的答案。其他回答都假定文件已通过git add添加,但并非总是如此。在Acquia Cloud中,.gitignore文件应该忽略settings.php(例如),但该文件在第一次提交时会被包含。取消跟踪该文件将简单地从代码库中删除它,因此也会从线上网站中删除它... - PatrickS
帮了我很多 - 谢谢!点赞。我怀疑它只适用于本地git仓库,一旦推送到远程并被其他开发人员克隆,它就不会持久存在了? - Ivan
1
是的,它只是本地的。 - Mescalito
4
这个回答让我找到了我需要的Git功能,即避免跟踪我本地对存储在远程代码库中的设置文件所做的更改。我最终使用的命令是git update-index --skip-worktree 文件名 - coppereyecat
很想看看如何还原这个。 git update-index --no-assume-unchanged sites/default/settings.php - wieczorek1990

108

请使用此命令

git rm -rf --cached .
git add .
有时候,即使.gitignore文件正确,它们也可能无法正常工作。Git忽略文件的原因是它们没有被添加到仓库中。如果你之前添加了一个需要忽略的文件,那么它将被Git跟踪,并且任何匹配规则都将被跳过。Git这样做是因为该文件已经是仓库的一部分。

有时候,即使.gitignore文件正确,它们也可能无法正常工作。Git忽略文件的原因是它们没有被添加到仓库中。如果你之前添加了一个需要忽略的文件,那么它将被Git跟踪,并且任何匹配规则都将被跳过。Git这样做是因为该文件已经是仓库的一部分。


16
在执行这个命令之前,我建议您先将所有更改进行存储。之前我没有这样做导致了一些 Git 上的混乱。 - Clifford Fajardo
请在提交之前提交您想要提交的内容。这基本上会将您工作目录中的所有更改添加到Git中。 - bunyaCloven
这对我有用。由于文件之前没有被添加,.gitignore 没有将它们排除在外。谢谢。 - Joselo
哇,你是不是把被采纳的答案ctrl+cctrl+v了?这个回答的唯一段落几乎与被采纳的答案完全相同。 - starriet

56

.gitignore只会忽略您尚未添加到代码库中的文件。

如果您执行了 git add . ,并且该文件已被添加到索引中,.gitignore将无法帮助您。您需要执行 git rm sites/default/settings.php 将其删除,然后它才会被忽略。


谢谢。但是我该如何仅从索引中而非工作目录中删除文件? - Nick.h
1
git rm 可以做到这一点,但它可能会要求您使用 -f 选项将其从工作目录中删除。我还没有想到其他方法,只能先复制文件,然后执行 git rm -f 命令,最后再恢复复制的文件。 - jonescb
一样的,伙计。在某个地方做一个拷贝,然后将其移除,提交已移除的状态,再将文件添加回去,看它们现在如何被忽略。 - Yevgeniy Afanasyev

28

我遇到了同样的问题。
在运行git status时,.gitingore中定义的文件被列为未跟踪的文件。

这是因为.gitignore文件保存为UTF-16LE编码,而不是UTF8编码。

.gitignore文件的编码更改为UTF8后它就工作了。


有没有想过为什么文件编码很重要?也许是路径读取不正确吗? - Chargnn
非常感谢。我读了很多答案,说问题是在某个时候提交了文件,但我知道我没有提交这些文件。我的问题是一个带有UTF-16LE编码的.gitignore文件。它变成这样是因为我在powershell中使用echo "" > .gitignore创建了该文件。 - M Katz

7

有些情况下,例如应用程序配置文件,我希望它们在git中被跟踪(因此.gitignore将无法起作用),但我需要为本地设置更改这些文件。我不想让git管理这些文件或显示它们已经被修改。为了实现这一点,我使用skip-worktree:

git update-index --skip-worktree path/to/file

您可以通过列出文件并检查以"S"开头的行来确认文件是否被跳过。
git ls-files -v | grep ^S

如果未来您想让git再次在本地管理该文件,请运行以下命令:
 git update-index --no-skip-worktree path/to/file

Mescalito之前给出了一个很好的答案,引导我进入了正确的轨道,但是:
git update-index --assume-unchanged file/to/ignore.php 与git有一个合约,在此合约中:用户承诺不更改文件,并允许Git假定工作树文件与索引中记录的内容匹配。
然而,在我的情况下,我更改了文件的内容,因此--skip-worktree是更好的选择。
Toshiharu Nishina的网站提供了关于skip-worktree和assume-unchanged的详细解释:Ignore files already managed with Git locally

7

我成功地忽略了 settings.php 文件的方法如下:

  1. git rm --cached sites/default/settings.php
  2. commit(到这里还没有生效)
  3. 手动删除 sites/default/settings.php(这个方法奏效了)
  4. git add .
  5. commit(已经成功忽略)

我认为,如果在 Git 上有提交的文件,则忽略不会按预期工作。只需删除该文件并进行提交。之后它将被忽略。


5
另一个可能的原因是同时运行几个git客户端。例如“git shell”+“GitHub Desktop”等。


我遇到了这种情况,我使用“GitHub Desktop”作为主要客户端,但它忽略了一些新的.gitignore设置:每次提交后:

  1. 你提交了某些东西。
  2. 接下来,再次提交:它忽略了.gitignore设置。提交包括在.gitignore中提到的许多临时文件。
  3. 清除git缓存;检查.gitignore是否为UTF8;删除文件->提交->将文件移回去;跳过1次提交-没有帮助。

原因:Visual Studio Code编辑器在后台运行并打开了相同的仓库。VS Code具有内置的git控制功能,这会导致一些冲突。

解决方法:仔细检查多个隐藏的git客户端,并一次只使用一个git客户端,特别是在清除git缓存时。


3

这里的优秀回答似乎忽略了另一种.gitignore或多个.gitignore文件的存在。

有一次,我克隆了一个仓库,但在运行git add时,发现一个“被忽略”的文件再次被添加,而我却无法解决。后来发现,在子文件夹中还有一个.gitignore文件,并且它覆盖了根目录中的.gitignore文件。

/.gitignore
/some-folder/.gitignore
/some-folder/this-file-keeps-getting-staged

根目录的 /.gitignore 文件忽略了 this-file-keeps-getting-staged 文件。

/some-folder/.gitignore

没有指定忽略 "this-file-keeps-getting-staged" 文件。

因此出现了问题。

其中一个解决方法是在层级结构中简单搜索 多个 .gitignore 文件,并找出适用的规则。


1
是的,内部的.gitignore文件比存储库根目录下的.gitignore文件具有更高的优先级。谢谢! - GaidinD
1
谢谢你指出这个问题并指出它是一个特例。可能不是原始帖子的答案,但仍然是很好的内容和故障排除。已点赞。 - JoelAZ
1
谢谢你指出这个问题并指出这是一个特例。可能不是楼主的答案,但仍然是很好的内容和故障排除。已点赞。 - undefined

2

我在VS Code终端上尝试了大部分以上命令,但是出现了以下错误:

fatal: pathspec '[dir]/[file]' did not match any files

后来我在GitHub桌面版中打开了这个项目,并从那里忽略了它,结果就成功了。


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