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

Iva*_*van 4888 git gitignore git-rm

有一个文件被跟踪git,但现在该文件在.gitignore列表中.

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

CB *_*ley 5151

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

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

git rm --cached <file>
Run Code Online (Sandbox Code Playgroud)

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

警告:虽然这不会从本地删除物理文件,但它将在下次从其他开发人员计算机中删除文件git pull.

  • 非常重要的补充.如果被忽略的文件将被修改(但是尽管不应该提交),在修改并执行`git add .`后,它将被添加到索引中.下一次提交会将其提交到存储库.为了避免这种情况,在所有mataal再说一个命令之后执行:`git update-index --assume-unchanged <path&filename> (103认同)
  • 这将删除`git pull`上的文件. (81认同)
  • 为我工作的过程是1.首先提交挂起的更改2. git rm --cached <file>并再次提交3.将文件添加到.gitignore,检查git status并再次提交 (53认同)
  • @AkiraYamamoto的方法也适合我.在我的情况下,我压缩了输出,因为我的存储库有成千上万的文件:`git rm -r -q --cached .` (32认同)
  • git rm --cached <file>只是从存储库中删除文件,git update-index --assume-unchanged <file>未显示未更改的文件中的文件,并且不会进行新的更改.但是我想要GIT J NOT IGNORE文件内容 (19认同)
  • @PetrPeller,那是对的......那么什么是正确的解决方案? (6认同)
  • mataal的评论非常重要.首先提交挂起的更改,然后git rm --cached并再次提交.如果rm是另一个提交的一部分,则它不能按预期工作. (4认同)
  • 您应该参考下面的Seth的答案作为这种方法的危险.Seth提到的确切事情发生在我身上,但由于上选票的数量,我已经按照你的回答了. (4认同)
  • @CharlesBailey:根据你自己的评论,你已经证明有一种情况可以删除你可能不想要的文件.仅仅因为你可以检索它并不意味着你想要它发生.我通过这种方法停止跟踪'文件,当我拉到qa服务器时,它删除了重要的(但特定于环境的)shell脚本,而不是仅仅跟踪它.这会降低部署过程的速度,并且在我检索文件时实时推出了停机时间.我不是说这是错误的方法,我说你也应该参考Seth的答案. (4认同)
  • @CharlesBailey:首先,让我们不要小气,我没有设置这个部署策略,这是我继承的项目.其次,提问者说"该文件在编辑后一直显示在git st中",所以很明显他们想保留文件,只是没有跟踪,因此有必要警告有关删除风险的警告. (3认同)
  • [@openCivilization](/sf/users/118509961/) 如果你想让 git “完全忘记”(追溯应用 gitignore 就好像它一开始就存在一样),**和/或**想要**避免**在下一个“git pull”上从其他开发人员计算机中删除文件,请参阅[此](/sf/answers/4024126361/)答案或[此](https:// stackoverflow.com/q/57418769/423125)问题/答案 (3认同)
  • @CharlesBailey:当然,你可以看出Seth有16个赞成回答的原因.可能有15个人犯了同样的错误. (2认同)
  • @Mark:您可能不希望使用源代码管理工具作为部署策略中的唯一元素,但如果您这样做,那么您肯定与想要强制git"完全忘记的问题提供者的情况不同关于"文件.我在答案中明确说:"从头版本中删除文件将在下次提交时发生." (2认同)
  • 这支持通配符,例如:`git rm --cached*.pyc`将递归删除所有带有`.pyc`扩展名的文件. (2认同)
  • 完整的答案是`git rm --cached -r。git add。; git状态` (2认同)
  • 我仍在使用这个答案,因为事实证明它比其他答案更安全、更保守,但我却经历了不良影响。完整的流程是 `git rm --cached &lt;文件或文件夹&gt;`、`git add .`、`git commit`、`git push`。 (2认同)
  • 如果答案还指定了当其他人执行 git pull 时如何避免删除现在未跟踪并添加到 gitignore 的文件,将会有所帮助。此外,当切换分支时,文件将被删除。如果您有表示被吹走的状态(例如在 terraform 中)的 tmp 文件,那么这是一个很大的问题。 (2认同)
  • **双重警告** 它会在本地删除该文件,如果您碰巧有一个包含之前创建的文件的存储,请应用它并通过选择“删除”中止合并。您可能认为它只删除索引,但它删除文件。 (2认同)

Mat*_*ear 2476

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

第一:

git rm -r --cached . 
git add .
Run Code Online (Sandbox Code Playgroud)

然后:

git commit -am "Remove ignored files"
Run Code Online (Sandbox Code Playgroud)

  • 要突出显示此答案与已接受答案之间的区别:使用此命令您无需实际知道受影响的文件.(想象一个临时目录,其中包含许多随机文件,应该从索引中清除). (181认同)
  • 将它作为标准的git命令会很高兴.像'git rmignored`这样的东西. (68认同)
  • 与接受的答案相同.文件将在`git pull`上删除. (44认同)
  • 有了这个,您最终可能会添加*其他*无用的文件,这些文件当前不在`.gitignore`中.如果取决于此命令后你的`git status`的噪音程度,可能很难找到.*仅删除*新忽略的文件的命令会更好.这就是为什么我更喜欢[thSoft的回答](http://stackoverflow.com/a/23839198/236871) (13认同)
  • @gudthing -r代表"递归" (12认同)
  • 所以,你们知道git rm -r --cached。从字面上将删除跟踪中的每个单个文件。每一个 不论其是否在gitignore中。我显然是个白痴,实际上执行了该命令并大声笑。我有成千上万的文件。我必须先打开reflog,git clean -d,在此命令之前签出分支,创建临时分支,将master设置为跟踪新分支,签出master并强制推送对其进行修复。哎哟。 (4认同)
  • 这是一个“危险”命令,因为它还会清除应用于早期文件的**-f **开关。例如,我们要显式保存单个DLL文件,那么通常要做的是使用** -f **开关在.git跟踪中显式添加该文件。但是**运行`git rm -r --cached``命令也会删除早期的强制文件。**。因此最好使用`git rm -r --cached &lt;filename&gt;`而不是加点。 (4认同)
  • 此解决方案会导致所有当前文件显示为“新”。提交后它们会显示为新的吗?[如何撤消 git rm -r 。如果你不提交](http://stackoverflow.com/questions/2125710/how-to-revert-a-git-rm-r) (2认同)
  • 不!这会造成混乱。使用下面康斯坦丁的答案。 (2认同)
  • @Berik:`git clean -X`只删除Git忽略的文件 (2认同)

Kon*_*tin 1015

git update-index为我做的工作:

git update-index --assume-unchanged <file>
Run Code Online (Sandbox Code Playgroud)

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

编辑:由于此答案已过帐,因此创建了一个新选项,应该首选.您应该使用--skip-worktree哪个用于用户不想再提交的已修改跟踪文件,并保持--assume-unchanged性能以防止git检查大跟踪文件的状态.有关详细信息,请参阅/sf/answers/954206781/

git update-index --skip-worktree <file>
Run Code Online (Sandbox Code Playgroud)

  • 这****是真正的答案.真棒,非常简单,不污染`git status`,实际上非常直观.谢谢. (157认同)
  • 使用以下命令撤消:git update-index --no-assume-unchanged <file> (60认同)
  • `git update-index --assume-unchanged <path> ...`将导致git忽略指定路径中的更改,而不管`.gitignore`.如果您从远程执行并且该远程对此路径进行了更改,则git将使冲突失败并且您需要手动合并.`git rm --cached <path> ...`将导致git停止跟踪该路径.如果你没有添加`.gitignore`的路径,你将看到未来`git status`的路径.第一个选项在git提交历史记录中具有较少的噪声,并允许在将来分发对"已忽略"文件的更改. (23认同)
  • 我很困惑这不是公认的答案.这里接受的答案显然不是回答被问到的实际问题.此答案忽略对存储库中文件的更改,同时不将其从存储库中删除. (21认同)
  • 如果它准确地解释了给定命令的作用,例如它与其他建议的解决方案有何不同,那么这个答案会更有用. (11认同)
  • 所以这只能在本地完成,而 `git rm --cached` 会在为其他人拉取时删除它。如果您只想忽略对文件的未来更改,无论是在您的机器上还是在其他机器上(已经拥有该文件),并且不想像当前在任何机器上一样自动删除它,该怎么办? (5认同)
  • 我找到了足够好的`rm [...].解决方案,因为至少我可以理解它是如何工作的.我没有找到关于`update-index`和`--assume-unchanged`做什么的好文档.任何人都可以添加这个与另一个相比的方式,因为我想删除所有被忽略的文件吗?(或清楚解释的链接?) (4认同)
  • 该命令仅对您的机器有效吗?如果我想停止在所有计算机上跟踪文件怎么办?还可以在将来克隆代表的机器上? (3认同)
  • 忽略整个目录,请参阅http://stackoverflow.com/a/12288918/848072 (2认同)
  • 这非常有用(我希望我能不止一次),但从技术上讲,这不是问题的答案.因为它会独立于.gitignore中的文件,所以我的意思是它不是100%回答OP问题(它解决了我的问题). (2认同)
  • 例如,如果我使用此选项,从远程拉取的其他存储库是否会知道停止跟踪文件?(也许只有当我将文件添加到 .gitignore 时?) (2认同)
  • 如果它是一个目录,请确保在目录名称的末尾添加一个尾部斜杠.例如`git update-index --assume-unchanged .history /` (2认同)
  • 这个解决方案是我一直在寻找的。`git rm --cached` 将在拉取时删除已删除的文件(这意味着,您不想忽略该文件,而是想删除它)。`git rm --cached ` 和 `.gitignore` 是一个误导性的组合。不会删除您在更改后运行 `git pull` 的同事的文件的实际解决方案是这个答案。谢谢 !运行`git ls-files -v | grep '^[[:lower:]]'` 以这种方式查找忽略的文件。 (2认同)
  • 我尝试过,但似乎当我尝试拉取它时它不起作用并给出错误,例如“您对以下文件的本地更改将被合并覆盖” (2认同)
  • 在某些情况下,您希望将干净的文件推送到存储库,然后禁用更改跟踪,以便用户可以在自己的计算机上编辑它们。ASP.NET 应用程序的 appsettings 文件就是一个示例。 (2认同)
  • 为一个文件设置“--skip-worktree”后,我无法签出另一个分支:“git checkout”说“请在切换分支之前提交您的更改或存储它们。”尽管“git status”声称“您的分支已达到”日期`,`没有什么可提交的,工作树干净`。因此,如果没有额外的研究/解释,这个答案可能会破坏东西。 (2认同)

thS*_*oft 265

git ls-files --ignored --exclude-standard -z | xargs -0 git rm --cached
git commit -am "Remove ignored files"
Run Code Online (Sandbox Code Playgroud)

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

  • 最好使用\ 0作为分隔符:`git ls-files --ignored --exclude-standard -z | xargs -0 git rm --cached` (9认同)
  • 如果你还需要从工作目录中删除它们,那么只需运行`git ls-files --ignored --exclude-standard | xargs git rm` 我相信这个答案是最好的!因为它非常清楚,以Unix方式,并且以直接的方式完成所需的事情,而不构成其他更复杂的命令的副作用. (7认同)
  • git ls-files --ignored --exclude-standard | sed's /.*/"&"/'| xargs git rm --cached (7认同)
  • 很好的答案; 但是,如果中间有空格的路径,命令将失败,例如:"My dir/my_ignored_file.txt" (5认同)
  • 如果`ls-files`与任何东西都不匹配,`git rm`会抱怨.如果没有文件匹配,请使用`xargs -r git rm ...`告诉`xargs`不要运行`git rm`. (2认同)
  • 你能解释一下将选项 `-a` 添加到 `git commit` 的动机吗?对我来说没必要... (2认同)
  • 从 Git 2.32 开始第一行被破坏,使用 `git ls-files -c --ignored --exclude-standard -z | xargs -0 git rm --cached` (2认同)

Dav*_*dez 76

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

git ls-files --ignored --exclude-standard | sed 's/.*/"&"/' | xargs git rm -r --cached
Run Code Online (Sandbox Code Playgroud)

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

  • 我也发现这个"最干净".这可能是显而易见的,但只是运行第一部分,`git ls-files --ignored --exclude-standard`,它可以让你首先理解/验证你的新`.gitignore`将要排除/删除的文件,在你继续执行最终的`git rm`之前. (5认同)
  • 好方案!工作得很完美,感觉更正确,删除所有文件,然后重新添加. (3认同)
  • Git 2.32 破坏了 ls 文件的行为 - 您现在需要添加“-c”。 (3认同)
  • 另一个警告:拉时,这将导致文件在其他人的工作目录中删除,对吗? (2认同)

Joe*_*oks 61

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

  • 请注意,与大多数(所有?)其他答案一样,这会在“git pull”时删除其他人的文件。 (4认同)
  • 如果您想忽略以前没有被忽略的一堆文件,这很有效。虽然就像你说的,可能有更好的方法。 (2认同)
  • 似乎是我能看到的唯一方法。这是 git 中的一个巨大错误(不是“功能”),只要您将文件/文件夹添加到 .gitignore,它就不会从那时起忽略该文件 - 永远 - 无处不在。 (2认同)

Set*_*son 61

如果您不能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 magic为你应用和删除更改,例如将配置文件涂抹为备用分支的签出,并将配置文件清理为HEAD的签出.这是棘手的东西,我不建议新手用户使用它.
  • 将配置文件保留在专用于它的部署分支上,该分支永远不会合并到主服务器.当您要部署/编译/测试时,您将合并到该分支并获取该文件.除了使用人工合并策略和extra-git模块之外,这基本上是涂抹/清洁方法.
  • 反推荐:不要使用假设不变,它只会以泪水结束(因为让git欺骗自己会导致坏事发生,就像你的变化永远丢失一样).

  • 如果文件在删除时是脏的,git不会删除该文件.如果它不脏,检索文件就像`git checkout <oldref> - <filename>`一样简单 - 但是它会被检出并被忽略. (7认同)

Dhe*_*kar 55

在以下时间使用此

你想要解开很多文件,或者

2.您更新了gitignore文件

来源链接: 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 .
Run Code Online (Sandbox Code Playgroud)
  • rm是remove命令
  • -r将允许递归删除
  • -cached只会从索引中删除文件.你的文件仍然存在.

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

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

git add .
Run Code Online (Sandbox Code Playgroud)

第4步:提交

git commit -m ".gitignore fix"
Run Code Online (Sandbox Code Playgroud)

你的存储库很干净:)

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

  • 它不会从远程存储库中删除文件吗?如果我想将文件同时保存在本地存储库和远程存储库中,但让 git “忘记”它们呢? (2认同)

drr*_*lvn 47

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

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

git filter-branch --index-filter 'git rm --cached --ignore-unmatch filename' HEAD
Run Code Online (Sandbox Code Playgroud)

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

  • 警告:这将从您的整个历史记录中删除该文件.这是我正在寻找的,删除了很久以前在版本历史中提交的完全不必要的和超大的文件(应该永远不会提交的输出). (18认同)
  • 这将更改所有提交ID,从而破坏存储库副本之外的分支的合并. (8认同)

Jon*_*ave 46

什么对我不起作用

(在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
Run Code Online (Sandbox Code Playgroud)

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

所以我提供

git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached
Run Code Online (Sandbox Code Playgroud)

它使用-z参数LS-文件-0参数xargs的安全迎合/正确的文件名中的"肮脏"的字符.

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

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

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

编辑:我被要求添加 - 就像任何git rm命令 - 这必须后面提交,以使删除永久,例如git commit -am "Remove ignored files".

  • 对我来说,这是最好的解决方案。它的性能比 `git add .` 好得多。它还包含上述一些评论中的最佳改进。 (2认同)

小智 22

  1. 更新.gitignore文件 - 例如,添加您不想跟踪的文件夹.gitignore.

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

  3. git add .- 除了那些文件外,所有文件都将被重新添加.gitignore.


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


Boo*_*ype 16

我想,也许git不能完全忘记文件,因为它的概念("快照,不是差异"部分).

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

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

这两篇文章对我有帮助:

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

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

git update-index --skip-worktree <file>
Run Code Online (Sandbox Code Playgroud)

从此刻起,此文件中的所有本地更改都将被忽略,并且不会转到远程.如果远程更改了文件,则会发生冲突git pull.藏匿不起作用.要解决此问题,请将文件内容复制到安全位置并按照以下步骤操作:

git update-index --no-skip-worktree <file>
git stash
git pull 
Run Code Online (Sandbox Code Playgroud)

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

git update-index --skip-worktree <file>
Run Code Online (Sandbox Code Playgroud)

如果每个与项目合作的人都会表现出来git update-index --skip-worktree <file>,那么问题pull应该是缺席的.当每个开发人员都有自己的项目配置时,此解决方案适用于配置文件.

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


Ars*_*mad 15

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

删除文件:

  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
Run Code Online (Sandbox Code Playgroud)

删除文件夹:

  1. 需要将该文件夹添加到文件.gitignore
  2. 需要使用命令(git rm -r --cached folder name)删除该文件
  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
Run Code Online (Sandbox Code Playgroud)

  • 先生,您才是真正的MVP! (3认同)

Sha*_*jib 14

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

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

2.立即将文件/目录添加到gitignore文件中并保存.

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

git rm -r --cached path-to-those-files
Run Code Online (Sandbox Code Playgroud)

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

git add .
git commit -m "removed unnecessary files from git"
git push origin
Run Code Online (Sandbox Code Playgroud)


you*_*ans 13

复制/粘贴答案是 git rm --cached -r .; git add .; git status

此命令将忽略已提交到Git存储库的文件,但现在我们已将其添加到.gitignore.

  • 可以将其读取为好像命令行将更改文件 *.gitignore* 的内容。你能[做到](https://stackoverflow.com/posts/53373557/edit)清楚事实并非如此(***没有***“编辑:”,“更新:”或类似的答案 - 答案应该看起来就像今天写的一样)。也就是说,不是直接澄清,而是通过改变书写方式。 (2认同)

Ame*_*een 9

Matt Fear的答案是最有效的恕我直言.以下只是一个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 .
Run Code Online (Sandbox Code Playgroud)


goo*_*ogy 9

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

这个方法让Git彻底忘记了被忽略的文件(过去/现在/未来),但它不会工作目录中删除任何内容(即使从远程重新拉取)。

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

所有强制 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
Run Code Online (Sandbox Code Playgroud)

最后,请遵循本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
Run Code Online (Sandbox Code Playgroud)

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

#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
Run Code Online (Sandbox Code Playgroud)

脚注

1因为/.git/info/exclude可以使用上面的说明应用于所有历史提交,所以也许有关将.gitignore文件放入需要它的历史提交的详细信息超出了本答案的范围。我希望.gitignore根提交中有一个正确的文件,就好像这是我做的第一件事一样。其他人可能不在乎,因为无论文件存在于提交历史记录中/.git/info/exclude的何处,都可以完成相同的事情,并且显然重写历史记录是非常困难的.gitignore敏感的主题,即使意识到后果也是如此。

FWIW,潜在的方法可能包括git rebasegit filter-branch复制外部 .gitignore到每个提交中,就像这个问题的答案一样。

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

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

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


rld*_*rld 9

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

然后我用了:

git update-index --skip-worktree .envrc
git rm --cached .envrc
Run Code Online (Sandbox Code Playgroud)

并且该文件已被删除。

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

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

然后我使用了这个命令:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch .envrc' HEAD
Run Code Online (Sandbox Code Playgroud)

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


Apr*_*che 8

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

  • `git rm --cached`将从索引中删除文件而不将其从磁盘中删除,因此无需移动/复制它 (32认同)

小智 5

BFG是专为去除像混帐回购大文件或密码不需要的数据而设计的,所以它有一个简单的标志,将消除任何大型历史(未在你的当前提交)文件:“--strip-blobs-大于

$ java -jar bfg.jar --strip-blobs-bigger-than 100M
Run Code Online (Sandbox Code Playgroud)

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

$ java -jar bfg.jar --delete-files *.mp4
Run Code Online (Sandbox Code Playgroud)

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

资料来源:https : //confluence.atlassian.com/bitbucket/reduce-repository-size-321848262.html


Ped*_* T. 5

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


Llo*_*oyd 5

在最新的 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
Run Code Online (Sandbox Code Playgroud)


Jay*_*ine 5

我喜欢JonBrave的回答,但是我的工作目录杂乱无章,可以提交-吓到我了,所以这是我做的事情:

git config --global alias.exclude-ignored'!git ls-files -z --ignored --exclude-standard | xargs -0 git rm -r --cached && git ls文件-z --ignored --exclude-standard | xargs -0 git stage && git stage .gitignore && git commit -m“新的gitignore并从索引中删除被忽略的文件”'

分解:

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"
Run Code Online (Sandbox Code Playgroud)
  • 从索引中删除忽略的文件
  • .gitignore和您刚刚删除的文件
  • 承诺


Ske*_*ets 5

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

您如何强迫git完全忘记[文件]?

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

正确的方法,以力混帐忘掉一个文件被GitHub的记录在这里

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

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
Run Code Online (Sandbox Code Playgroud)

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

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


Khu*_*alm 5

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

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

在此,我们基本上也尝试在之前的提交中重写该特定文件的历史记录。

有关更多信息,您可以参考这里的filter-branch的手册页

来源:从存储库中删除敏感数据 - 使用过滤器分支

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


归档时间:

查看次数:

1109960 次

最近记录:

6 年 前