如何让Git“忘记”一个被跟踪但现在位于.gitignore的文件?

问题描述 投票:4479回答:23

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

但是,该文件在编辑后会一直显示在git status中。你怎么强迫git完全忘记它?

git gitignore git-rm
23个回答
4772
投票

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

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

git rm --cached <file>

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

git rm -r --cached <folder>

从头修订中删除文件将在下次提交时发生。

警告:虽然这不会从本地删除物理文件,但它将在下一个git pull上从其他开发人员机器中删除文件。


41
投票

What didn't work for me

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

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

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

So I offer

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

这使用qsxswpoi参数到ls-files,而-z参数用于xargs安全/正确地处理文件名中的“讨厌”字符。

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

如果未使用-z选项,则路径名中的TAB,LF和反斜杠字符分别表示为\ t,\ n和\\。

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

编辑:我被要求添加 - 就像任何-0命令 - 这必须后面提交使删除永久,例如git rm


21
投票
  1. 更新您的git commit -am "Remove ignored files"文件 - 例如,添加您不想跟踪的文件夹到.gitignore
  2. .gitignore - 删除所有跟踪的文件,包括通缉和不需要的文件。只要您在本地保存,您的代码就是安全的。
  3. git rm -r --cached . - 所有文件都将被重新添加,但git add .除外。

帽子提示@AkiraYamamoto指出我们正确的方向。


15
投票

我想,也许git不能完全忘记文件,因为它的概念(.gitignore)。

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

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

这两篇文章对我有帮助:

section "Snapshots, Not Differences"git assume-unchanged vs skip-worktree

基于它我会执行以下操作,如果已经跟踪了文件:

How to ignore changes in tracked files with 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>的问题应该不存在。当每个开发人员都有自己的项目配置时,此解决方案适用于配置文件。

在远程更改文件时,每次执行此操作都不是很方便,但可以保护它不被远程内容覆盖。


12
投票

按顺序执行以下步骤,你会没事的。

1.从目录/存储中删除错误添加的文件。您可以使用“rm -r”(用于linux)命令或通过浏览目录删除它们。或者将它们移动到PC上的其他位置。[如果运行移动/移除,您可能需要关闭IDE]

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

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

gitignore

4.现在进行提交和推送,使用这些命令。这将从git remote中删除这些文件并使git停止跟踪这些文件。

git rm -r --cached path-to-those-files

9
投票

复制/粘贴答案是git add . git commit -m "removed unnecessary files from git" git push origin

此命令将忽略已提交给Git存储库的文件,但现在我们已将它们添加到git rm --cached -r .; git add .; git status


8
投票

Matt Fear的答案是最有效的恕我直言。以下只是一个PowerShell脚本,用于Windows中的那些只能从他们的git仓库中删除与其排除列表匹配的文件。

.gitignore

6
投票

将文件移动或复制到安全位置,这样就不会丢失它。然后git rm文件并提交。如果您还原到其中一个早期提交,或者另一个尚未删除的分支,该文件仍将显示。但是,在以后的所有提交中,您都不会再次看到该文件。如果文件在git中忽略,那么你可以将它移回文件夹,git将不会看到它。


4
投票

# 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 . 专门用于从Git repos中删除不需要的数据,如大文件或密码,因此它有一个简单的标志,可以删除任何大型历史(不在当前提交)文件:'--strip-blobs-降幅高于”

BFG

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

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

BFG比git filter-branch快10-1000倍,并且通常更容易使用 - 请查看$ java -jar bfg.jar --delete-files *.mp4 full usage instructions以获取更多详细信息。

资料来源:examples


4
投票

如果您不想使用CLI并且正在使用Windows,一个非常简单的解决方案是使用https://confluence.atlassian.com/bitbucket/reduce-repository-size-321848262.html,它在菜单中有“删除(保持本地)”操作,该工作正常。


4
投票

我喜欢JonBrave的答案,但是我有足够的工作目录,这让我感到害怕 - 所以这就是我所做的:

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并从索引中删除被忽略的文件”

打破它:

TortoiseGit
  • 从索引中删除被忽略的文件
  • stage .gitignore和你刚刚删除的文件
  • 承诺

2380
投票

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

第一:

git rm -r --cached . 
git add .

然后:

git commit -am "Remove ignored files"

2
投票

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

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" 最终忽略了被跟踪但已删除的文件。您可以通过运行以下脚本来自行测试。最后的.gitignore声明应报告“无需承诺”。

git status

1
投票

如果已经承诺# Create empty repo 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

DS_Store

忽略它们:

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

最后,提交一下!


1
投票

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

比如说slnx.sqlite,我刚刚完全摆脱它如下:

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

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


1
投票

使用git rm {PATH_OF_THE_FILE}/slnx.sqlite -f git commit -m "remove slnx.sqlite" 命令无法回答原始问题:

你怎么强迫git rm --cached完全忘记[文件]?

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

GitHub git pull记录了强制git忘记文件的正确方法。

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

here

只需将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历史。


942
投票

git update-index为我做的工作:

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

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

编辑:由于此答案已过帐,因此创建了一个新选项,应该首选。您应该使用--skip-worktree,这是用于不再需要提交的已修改跟踪文件,并保持--assume-unchanged的性能,以防止git检查大型跟踪文件的状态。有关更多详细信息,请参阅https://stackoverflow.com/a/13631525/717372

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

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

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


71
投票

我总是使用此命令删除那些未跟踪的文件。单行,Unix风格,干净的输出:

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

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


59
投票

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

总结一下:

  • 让您的应用程序查找被忽略的文件config-override.init并将其用于提交的文件config.ini(或者,查找〜/ .config / myapp.ini或$ CONFIG FILE)
  • 提交文件config-sample.ini并忽略文件config.ini,必要时根据需要使用脚本或类似的文件复制文件。
  • 尝试使用gitattributes clean / smudge magic为你应用和删除更改,例如将配置文件涂抹为备用分支的签出,并将配置文件清理为HEAD的签出。这是棘手的东西,我不建议新手用户使用它。
  • 将配置文件保留在专用于它的部署分支上,该分支永远不会合并到主服务器。当您要部署/编译/测试时,您将合并到该分支并获取该文件。除了使用人工合并策略和extra-git模块之外,这基本上是涂抹/清洁方法。
  • 反推荐:不要使用假设不变,它只会以泪水结束(因为让git欺骗自己会导致坏事发生,就像你的变化永远丢失一样)。

56
投票

将它移出,提交,然后将其移回。这在过去对我有用。实现这一目标可能有一种“轻微”的方式。


51
投票

Use this when:

1. You want to untrack a lot of files, or

2. You updated your gitignore file

来源链接:http://www.codeblocq.com/2016/01/Untrack-files-already-added-to-git-repository-based-on-gitignore/

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

第1步:提交所有更改

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

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

要清除您的仓库,请使用:

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

rm命令可能是无情的。如果您希望事先尝试它的功能,请添加-n--dry-run标志来测试。

第3步:重新添加所有内容

git add .

第4步:提交

git commit -m ".gitignore fix"

你的存储库很干净:)

将更改推送到遥控器以查看更改在那里有效。


42
投票

我用git filter-branch完成了这个。我使用的确切命令来自手册页:

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.