6988

Git 正在跟踪一个文件,但现在该文件在.gitignore列表中。

但是,该文件在编辑后会继续显示git status。你如何强迫 Git 完全忘记它?

4

31 回答 31

7394

.gitignore将阻止将未跟踪的文件添加(不带add -f)到 Git 跟踪的文件集中,但是 Git 将继续跟踪任何已经被跟踪的文件。

要停止跟踪文件,您需要将其从索引中删除。这可以通过这个命令来实现。

git rm --cached <file>

如果要删除整个文件夹,则需要递归删除其中的所有文件。

git rm -r --cached <folder>

从头版本中删除文件将在下一次提交时发生。

警告:虽然这不会从本地删除物理文件,但会从 next 上的其他开发人员机器中删除文件git pull

于 2009-08-13T20:40:59.257 回答
3103

下面的一系列命令将从 Git 索引中删除所有项目(而不是从工作目录或本地存储库中),然后将更新 Git 索引,同时尊重 Git 忽略。PS。索引 = 缓存

第一的:

git rm -r --cached .
git add .

然后:

git commit -am "Remove ignored files"

或作为单行:

git rm -r --cached . && git add . && git commit -am "Remove ignored files"
于 2013-09-30T13:51:26.907 回答
1476

git update-index为我做这项工作:

git update-index --assume-unchanged <file>

注意:此解决方案实际上是独立的,.gitignore因为 gitignore 仅适用于未跟踪的文件。


更新,更好的选择

自从发布此答案以来,已经创建了一个新选项,应该是首选。您应该将--skip-worktreewhich 用于用户不想再提交的已修改跟踪文件并保留--assume-unchanged性能以防止 git 检查大跟踪文件的状态。有关更多详细信息,请参阅https: //stackoverflow.com/a/13631525/717372...

git update-index --skip-worktree <file>

取消

git update-index --no-skip-worktree <file>
于 2013-11-27T11:24:15.623 回答
330
git ls-files -c --ignored --exclude-standard -z | xargs -0 git rm --cached
git commit -am "Remove ignored files"

这将获取被忽略文件的列表,将它们从索引中删除,并提交更改。

于 2014-05-23T22:29:37.067 回答
100

我总是使用这个命令来删除那些未跟踪的文件。一行 Unix 风格的干净输出:

git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

它列出了所有被忽略的文件,用引用的行替换每个输出行,而不是处理内部带有空格的路径,并将所有内容传递给以git rm -r --cached从索引中删除路径/文件/目录。

于 2015-06-19T15:42:11.817 回答
92

将其移出,提交,然后将其移回。

这在过去对我有用,但可能有一种“gittier”方式来实现这一点。

于 2009-08-13T19:27:31.227 回答
84

复制/粘贴答案是:

git rm --cached -r .; git add .; git status; git commit -m "Ignore unwanted files"

此命令不会更改.gitignore文件的内容。它只会忽略已经提交到 Git 存储库但现在我们已将它们添加到.gitignore.

该命令git status;仅用于查看更改并且可以删除。

最后,它将立即提交更改并显示“忽略不需要的文件”消息。

如果您不想提交更改,请删除命令的最后一部分 ( git commit -m "Ignore unwanted files")

于 2018-11-19T11:21:40.063 回答
79

在以下情况下使用它:

  1. 您想取消跟踪很多文件,或者
  2. 您更新了.gitignore文件

来源:基于 .gitignore 取消跟踪已添加到 Git 存储库的文件

假设您已经将一些文件添加/提交到您的 Git 存储库,然后将它们添加到您的.gitignore文件中;这些文件仍将存在于您的存储库索引中。这篇文章我们将看到如何摆脱它们。

第 1 步:提交所有更改

在继续之前,请确保您的所有更改都已提交,包括您的.gitignore文件。

第 2 步:从存储库中删除所有内容

要清除您的存储库,请使用:

git rm -r --cached .
  • rm是删除命令
  • -r将允许递归删除
  • --cached只会从索引中删除文件。您的文件仍然存在。

rm命令可能是无情的。如果您想预先尝试它的功能,请添加-nor--dry-run标志以进行测试。

第 3 步:阅读所有内容

git add .

第 4 步:提交

git commit -m ".gitignore fix"

您的存储库很干净:)

将更改推送到您的遥控器以查看更改也在那里生效。

于 2018-04-22T18:11:09.810 回答
70

如果您因为其他人可能需要而无法git rm跟踪文件(警告,即使 git rm --cached,当其他人获得此更改时,他们的文件将在他们的文件系统中被删除)。这些通常是由于配置文件覆盖、身份验证凭据等而完成的。请查看https://gist.github.com/1423106了解人们解决此问题的方法。

总结一下:

  • 让您的应用程序查找被忽略的文件 config-overide.ini 并在提交的文件 config.ini 上使用它(或者,查找 ~/.config/myapp.ini 或 $MYCONFIGFILE)
  • 提交文件 config-sample.ini 并忽略文件 config.ini,如有必要,有一个脚本或类似的复制文件。
  • 尝试使用 gitattributes clean/smudge 魔法为您应用和删除更改,例如将配置文件涂抹为来自备用分支的结帐,并将配置文件清理为来自 HEAD 的结帐。这是棘手的东西,我不建议新手用户使用。
  • 将配置文件保存在专用于它的部署分支上,该分支永远不会合并到主控。当您想要部署/编译/测试时,您合并到该分支并获取该文件。除了使用人工合并策略和额外的 git 模块外,这本质上是涂抹/清洁方法。
  • 反建议:不要使用假设不变,它只会以泪水告终(因为 git 对自己撒谎会导致坏事发生,比如你的更改会永远丢失)。
于 2012-07-19T00:08:57.427 回答
57

我通过使用git filter-branch实现了这一点。我使用的确切命令取自手册页:

警告:这将从您的整个历史记录中删除该文件

git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD

该命令将重新创建整个提交历史,git rm在每次提交之前执行,因此将摆脱指定的文件。不要忘记在运行命令之前备份它,因为它丢失。

于 2009-08-13T19:35:53.920 回答
52

什么对我不起作用

(在 Linux 下),我想使用这里的帖子来建议这种ls-files --ignored --exclude-standard | xargs git rm -r --cached方法。但是,(某些)要删除的文件\n的名称中有一个嵌入的换行符/LF/。两种解决方案都不是:

git ls-files --ignored --exclude-standard | xargs -d"\n" git rm --cached
git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached

应对这种情况(获取有关未找到文件的错误)。

所以我提供

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached
git commit -am "Remove ignored files"

这使用ls-files的参数和xargs的参数来-z安全/正确地满足文件名中的“讨厌”字符。-0

在手册页git-ls-files(1)中,它指出:

当不使用 -z 选项时,路径名中的 TAB、LF 和反斜杠字符分别表示为 \t、\n 和 \\。

所以我认为如果文件名中包含任何这些字符,则需要我的解决方案。

于 2015-12-29T12:50:08.847 回答
32

对文件/文件夹执行以下步骤:

删除文件:

  1. 需要将该文件添加到.gitignore。
  2. 需要使用命令(git rm --cached file name)删除该文件。
  3. 需要运行(git add .)。
  4. 需要(commit -m)“文件删除”。
  5. 最后,(git push)。

例如:

我想删除test.txt文件。我不小心推送到 GitHub 并想将其删除。命令如下:

首先,在.gitignore文件中添加“test.txt”

git rm --cached test.txt
git add .
git commit -m "test.txt removed"
git push

删除文件夹:

  1. 需要将该文件夹添加到文件.gitignore
  2. 需要使用命令(git rm -r --cached 文件夹名称)删除该文件夹。
  3. 需要运行(git add .)。
  4. 需要(commit -m)“删除文件夹”。
  5. 最后,(git push)。

例如:

我想删除.idea文件夹/目录。我不小心推送到 GitHub 并想将其删除。命令如下:

首先,在文件.gitignore中添加.idea

git rm -r --cached .idea
git add .
git commit -m ".idea removed"
git push
于 2020-09-09T02:09:34.083 回答
27
  1. 更新您的.gitignore文件 - 例如,将您不想跟踪的文件夹添加到.gitignore.

  2. git rm -r --cached .- 删除所有跟踪的文件,包括想要的和不需要的。只要您保存在本地,您的代码就会很安全。

  3. git add .– 所有文件都将被重新添加,除了.gitignore.


向@AkiraYamamoto 致敬,为我们指明了正确的方向。

于 2016-04-04T04:09:39.290 回答
23

依次执行以下步骤,您会没事的。

  1. 从 directory/storage中删除错误添加的文件。您可以使用“rm -r”(适用于 Linux)命令或通过浏览目录来删除它们。或者将它们移动到 PC 上的另一个位置。(如果为移动/移除而运行,您可能需要关闭 IDE 。)

  2. 现在将文件/目录添加到.gitignore文件并保存。

  3. 现在使用这些命令它们从Git 缓存中删除(如果有多个目录,请通过重复发出此命令将它们一一删除)

     git rm -r --cached path-to-those-files
    
  4. 现在使用以下命令进行提交和推送。这将从 Git 远程删除这些文件,并使 Git停止跟踪这些文件。

     git add .
     git commit -m "removed unnecessary files from Git"
     git push origin
    
于 2018-09-20T10:52:31.380 回答
18

我认为,也许 Git 不能完全忘记文件,因为它的概念(“快照,而不是差异”部分)。

例如,在使用CVS时,不存在此问题。CVS 将信息存储为基于文件的更改列表。CVS 的信息是一组文件以及随时间对每个文件所做的更改。

但是在 Git 中,每次提交或保存项目状态时,它基本上都会拍摄当时所有文件的样子,并存储对该快照的引用。因此,如果您添加了一次文件,它将始终存在于该快照中。

这两篇文章对我很有帮助:

git assume-unchanged vs skip-worktree以及如何使用 Git 忽略跟踪文件中的更改

在此基础上,如果文件已被跟踪,我会执行以下操作:

git update-index --skip-worktree <file>

从这一刻起,该文件中的所有本地更改都将被忽略,并且不会转到远程。如果远程更改文件,则会发生冲突,当git pull. 藏匿行不通。要解决它,请将文件内容复制到安全的地方并按照以下步骤操作:

git update-index --no-skip-worktree <file>
git stash
git pull

文件内容将被远程内容替换。将您的更改从安全位置粘贴到文件并再次执行:

git update-index --skip-worktree <file>

如果与该项目一起工作的每个人都将执行git update-index --skip-worktree <file>pull那么应该不存在问题。当每个开发人员都有自己的项目配置时,此解决方案适用于配置文件。

每次在远程更改文件时都这样做不是很方便,但它可以保护它不被远程内容覆盖。

于 2017-05-21T15:12:39.520 回答
11

使用该git rm --cached命令并不能回答原始问题:

你如何强迫git完全忘记[一个文件]?

实际上,此解决方案将导致在执行时删除存储库的每个其他实例中的文件git pull

GitHub在这里记录了强制 Git 忘记文件的正确方法。

我建议阅读文档,但基本上:

git fetch --all
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch full/path/to/file' --prune-empty --tag-name-filter cat -- --all
git push origin --force --all
git push origin --force --tags
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

只需替换full/path/to/file为文件的完整路径即可。确保您已将文件添加到.gitignore文件中。

您还需要(暂时)允许非快进推送到您的存储库,因为您正在更改您的 Git 历史记录。

于 2019-05-09T02:27:29.707 回答
10

Matt Frear的回答是最有效的恕我直言。以下只是一个 PowerShell 脚本,供 Windows 用户仅从其 Git 存储库中删除与其排除列表匹配的文件。

# Get files matching exclusionsfrom .gitignore
# Excluding comments and empty lines
$ignoreFiles =  gc .gitignore | ?{$_ -notmatch  "#"} |  ?{$_ -match  "\S"} | % {
                    $ignore = "*" + $_ + "*"
                    (gci -r -i $ignore).FullName
                }
$ignoreFiles = $ignoreFiles| ?{$_ -match  "\S"}

# Remove each of these file from Git
$ignoreFiles | % { git rm $_}

git add .
于 2013-12-25T00:51:04.883 回答
8

将文件移动或复制到安全位置,以免丢失。然后“git rm”文件并提交。

如果您恢复到其中一个较早的提交或另一个尚未删除它的分支,该文件仍将显示。但是,在以后的所有提交中,您将不会再次看到该文件。如果文件在 Git 忽略中,那么您可以将其移回文件夹中,Git 不会看到它。

于 2009-08-13T19:27:44.267 回答
6

我喜欢JonBrave 的回答,但我的工作目录很乱,commit -a让我有点害怕,所以这就是我所做的:

git config --global alias.exclude-ignored '!git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached &&  git ls-files -z --ignored --exclude-standard | xargs -0 git stage &&  git stage .gitignore && git commit -m "new gitignore and remove ignored files from index"'

分解它:

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached
git ls-files -z --ignored --exclude-standard | xargs -0 git stage
git stage .gitignore
git commit -m "new gitignore and remove ignored files from index"
  • 从索引中删除被忽略的文件
  • stage .gitignore 和你刚刚删除的文件
  • 犯罪
于 2018-08-08T20:49:29.503 回答
6

就我而言,我需要将“ .envrc”放在.gitignore文件中。

然后我用:

git update-index --skip-worktree .envrc
git rm --cached .envrc

并且该文件已被删除。

然后我再次提交,告诉文件已被删除。

但是当我使用 command 时git log -p,文件的内容(这是Amazon S3的秘密凭证)正在显示已删除的内容,我不想在 Git 存储库的历史记录中显示此内容。

然后我使用了这个命令:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch .envrc' HEAD

而且我再也看不到内容了。

于 2021-04-16T20:37:21.240 回答
5

BFG专为从 Git 存储库中删除不需要的数据(如大文件或密码)而设计,因此它有一个简单的标志,可以删除任何大型历史(不在您的当前提交中)文件:'--strip-blobs-大于'

java -jar bfg.jar --strip-blobs-bigger-than 100M

如果您想按名称指定文件,您也可以这样做:

java -jar bfg.jar --delete-files *.mp4

BFG 比 BFG 快 10-1000 倍,git filter-branch并且通常更易于使用 - 请查看完整的使用说明示例以获取更多详细信息。

来源:减少存储库大小

于 2017-09-03T12:37:28.307 回答
5

如果您不想使用 CLI 并且在 Windows 上工作,一个非常简单的解决方案是使用TortoiseGit。它在菜单中有“删除(保留本地)”操作,效果很好。

于 2018-03-15T11:04:04.670 回答
5

接受的答案不会“让Git “忘记”文件......”(历史上)。它只会让 Git忽略当前/未来的文件。

这种方法使 Git完全忘记被忽略的文件(过去/present/future),但它不会工作目录中删除任何内容(即使从远程重新拉出)。

此方法需要使用文件/.git/info/exclude(首选)所有具有要忽略/忘记的文件的提交中预先存在的文件。 1.gitignore

所有强制执行 Git 的方法都会忽略事后行为,从而有效地重写历史记录,因此对在此过程之后可能被拉出的任何公共/共享/协作存储库产生重大影响。2

一般建议:从一个干净的存储库开始——所有内容都已提交,工作目录或索引中没有任何待处理的内容,并进行备份

此外,此答案的评论/修订历史以及此问题的修订历史)可能有用/有启发性。

#Commit up-to-date .gitignore (if not already existing)
#This command must be run on each branch

git add .gitignore
git commit -m "Create .gitignore"

#Apply standard Git ignore behavior only to the current index, not the working directory (--cached)
#If this command returns nothing, ensure /.git/info/exclude AND/OR .gitignore exist
#This command must be run on each branch

git ls-files -z --ignored --exclude-standard | xargs -0 git rm --cached

#Commit to prevent working directory data loss!
#This commit will be automatically deleted by the --prune-empty flag in the following command
#This command must be run on each branch

git commit -m "ignored index"

#Apply standard git ignore behavior RETROACTIVELY to all commits from all branches (--all)
#This step WILL delete ignored files from working directory UNLESS they have been dereferenced from the index by the commit above
#This step will also delete any "empty" commits.  If deliberate "empty" commits should be kept, remove --prune-empty and instead run git reset HEAD^ immediately after this command

git filter-branch --tree-filter 'git ls-files -z --ignored --exclude-standard | xargs -0 git rm -f --ignore-unmatch' --prune-empty --tag-name-filter cat -- --all

#List all still-existing files that are now ignored properly
#If this command returns nothing, it's time to restore from backup and start over
#This command must be run on each branch

git ls-files --other --ignored --exclude-standard

最后,遵循本GitHub 指南的其余部分(从第 6 步开始),其中包括有关以下命令的重要警告/信息

git push origin --force --all
git push origin --force --tags
git for-each-ref --format="delete %(refname)" refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --prune=now

从现在修改的远程存储库中提取的其他开发人员应该进行备份,然后:

#fetch modified remote

git fetch --all

#"Pull" changes WITHOUT deleting newly-ignored files from working directory
#This will overwrite local tracked files with remote - ensure any local modifications are backed-up/stashed

git reset FETCH_HEAD

脚注

1因为/.git/info/exclude可以使用上述说明应用于所有历史提交,所以可能有关将.gitignore文件放入需要它的历史提交的详细信息超出了此答案的范围。我想要一个合适的.gitignore文件在根提交中,就好像这是我做的第一件事一样。其他人可能不在乎,因为/.git/info/exclude无论.gitignore文件在提交历史中的哪个位置都可以完成同样的事情,而且很明显重写历史是一个非常敏感的主题,即使知道后果也是如此。

FWIW,潜在的方法可能包括git rebase或将外部git filter-branch复制到每个提交中,例如这个问题的答案。 .gitignore

2通过提交独立命令的结果来强制执行 Git 事后忽略行为可能会导致在未来从强制推送远程拉取时删除git rm --cached新忽略的文件。以下命令中的标志通过自动删除先前的“删除所有忽略的文件”仅索引提交来避免此问题。重写 Git 历史也会更改提交哈希,这将对公共/共享/协作存储库的未来拉取造成严重破坏。在对此类存储库执行此操作之前,请充分了解其后果。此 GitHub 指南指定以下内容:--prune-emptygit filter-branch

告诉你的合作者对他们从旧的(受污染的)存储库历史创建的任何分支进行rebase而不是合并。一次合并提交可能会重新引入部分或全部受污染的历史记录,而这些历史记录是您刚刚费力清除的。

影响远程存储库的替代解决方案是git update-index --assume-unchanged </path/file>or git update-index --skip-worktree <file>,可以在此处找到示例。

于 2019-08-14T02:38:06.130 回答
4

git rm --cached -r <YOUR_files_or_folders>

--缓存 | 仅从索引中删除文件

于 2022-01-21T07:48:05.427 回答
4

这就是我解决问题的方法:

git filter-branch --tree-filter 'rm -rf path/to/your/file' HEAD
git push

在这方面,我们基本上也试图在以前的提交中重写该特定文件的历史记录。

有关更多信息,您可以在此处参考filter-branch的手册页

来源:从存储库中删除敏感数据 - 使用 filter-branch

资料来源:Git:如何删除错误提交的大文件

于 2021-04-12T12:59:25.187 回答
4

这在最新的 Git (撰写本文时为 v2.17.1)中不再是问题。

.gitignore文件最终会忽略已跟踪但已删除的文件。您可以通过运行以下脚本自行测试。最终git status声明应报告“没有任何承诺”。

# Create an empty repository
mkdir gitignore-test
cd gitignore-test
git init

# Create a file and commit it
echo "hello" > file
git add file
git commit -m initial

# Add the file to gitignore and commit
echo "file" > .gitignore
git add .gitignore
git commit -m gitignore

# Remove the file and commit
git rm file
git commit -m "removed file"

# Reintroduce the file and check status.
# .gitignore is now respected - status reports "nothing to commit".
echo "hello" > file
git status
于 2018-06-13T16:21:32.087 回答
2

特别是对于基于 IDE 的文件,我使用这个:

例如,对于 slnx.sqlite 文件,我完全摆脱了它,如下所示:

git rm {PATH_OF_THE_FILE}/slnx.sqlite -f
git commit -m "remove slnx.sqlite"

请记住,其中一些文件存储了一些本地用户设置和项目首选项(例如您打开了哪些文件)。因此,每次您在 IDE 中导航或进行一些更改时,该文件都会更改,因此它会检查它并显示为未提交的更改。

于 2019-04-05T18:48:14.317 回答
2

如果有人在 Windows 上遇到困难而您想忽略整个文件夹,请转到文件资源管理器上所需的“文件夹”,右键单击并执行“Git Bash Here”(应该已经安装了 Windows 版 Git)。

运行此命令:

git ls-files -z | xargs -0 git update-index --assume-unchanged
于 2019-12-14T04:36:10.183 回答
2

如果已经提交DS_Store

find . -name .DS_Store -print0 | xargs -0 git rm --ignore-unmatch

通过以下方式忽略它们:

echo ".DS_Store" >> ~/.gitignore_global
echo "._.DS_Store" >> ~/.gitignore_global
echo "**/.DS_Store" >> ~/.gitignore_global
echo "**/._.DS_Store" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_global

最后,做出承诺!

于 2018-04-22T21:14:49.947 回答
0

如果您使用类似的命令创建了 gitignore 文件echo node_modules >> .gitignore,它将无法正常工作。

windows终端保存文件UCS-2 LE BOM,git似乎不接受。

您可以通过打开Notepad并使用UTF-8编码重新保存来解决此问题

记事本保存 utf-8 编码

它现在有效。

我认为他们需要解决这个问题,因为这样做echo "filetoignore" >> .gitignore实际上看起来很方便

于 2021-07-28T13:49:59.877 回答
0

在我的例子中,我在几个需要删除的目录中有几个 .lock 文件。我运行了以下命令,它无需进入每个目录即可删除它们:

git rm -r --cached **/*.lock

这样做会进入我所在的“根”下的每个文件夹,并排除所有与模式匹配的文件。

于 2019-12-27T22:05:05.300 回答