Git:如何从索引中删除文件而不删除任何存储库中的文件

时间:2010-04-09 01:52:07

标签: git version-control gitignore git-rm

使用时

git rm --cached myfile

它不会从本地文件系统中删除,这是目标。但是,如果您已经对文件进行了版本化和提交,将其推送到中央存储库,并在使用该命令之前将其拉入另一个存储库,它将从该系统中删除该文件。

有没有办法从版本控制中删除文件而不从任何文件系统中删除它?

编辑:澄清,我希望。

7 个答案:

答案 0 :(得分:109)

我不认为Git提交可以记录“停止跟踪此文件但不删除它”的意图。

实现这样的意图需要在Git之外的任何存储库中进行干预,这些存储库合并(或重新绑定)删除文件的提交。


保存副本,应用删除,恢复

可能最简单的方法是告诉下游用户保存文件副本,删除删除,然后恢复文件。 如果他们通过rebase进行拉动并对文件进行“修改”,则会发生冲突。要解决此类冲突,请使用git rm foo.conf && git rebase --continue(如果冲突提交除已删除文件之外的更改)或git rebase --skip(如果冲突提交仅更改为已删除文件)。

在删除删除它的提交后将文件恢复为未跟踪

如果他们已经撤消了删除提交,他们仍然可以使用git show恢复以前版本的文件:

git show @{1}:foo.conf >foo.conf

或者使用git checkout(根据William Pursell的评论;但请记住将其从索引中重新删除!):

git checkout @{1} -- foo.conf && git rm --cached foo.conf

如果他们在删除你的删除后采取了其他行动(或者他们将rebase拉入一个独立的HEAD),他们可能需要@{1}之外的其他内容。他们可以在删除之前使用git log -g来查找提交。


在评论中,您提到您要“未跟踪但保留”的文件是运行软件(直接从存储库中)所需的某种配置文件。

将文件保留为“默认”并手动/自动激活

如果继续在存储库中维护配置文件的内容并不完全不可接受,您可以将跟踪的文件从(例如)foo.conf重命名为foo.conf.default,然后指示您的用户应用重命名提交后到cp foo.conf.default foo.conf。 或者,如果用户已经使用存储库的某些现有部分(例如,脚本或存储库中的内容配置的其他程序(例如Makefile或类似的))来启动/部署您的软件,您可以使用默认值进入启动/部署过程的机制:

test -f foo.conf || test -f foo.conf.default &&
    cp foo.conf.default foo.conf

有了这样的默认机制,用户应该能够提取一个将foo.conf重命名为foo.conf.default的提交,而无需进行任何额外的工作。 此外,如果您将来再创建其他安装/存储库,则可以避免手动复制配置文件。

重写历史需要手动干预......

如果维护存储库中的内容是不可接受的,那么您可能希望使用类似git filter-branch --index-filter …的内容从历史记录中彻底消除它。 这相当于重写历史记录,这需要对每个分支/存储库进行手动干预(请参阅git rebase manpage中的“从上游重新恢复中恢复”部分)。 配置文件所需的特殊处理只是在从重写中恢复时必须执行的另一个步骤:

  1. 保存配置文件的副本。
  2. 从重写中恢复。
  3. 恢复配置文件。

  4. 忽略它以防止再次发生

    无论使用哪种方法,您可能希望将配置文件名包含在存储库中的.gitignore文件中,这样就不会再有人无意中git add foo.conf(这是可能的,但需要{{1} }} / -f)。 如果您有多个配置文件,您可以考虑将它们全部“移动”到一个目录中并忽略整个事情(通过'移动'我的意思是改变程序期望找到其配置文件的位置,并获取用户(或复制/移动文件到其新位置的启动/部署机制;你显然不希望 git mv 将文件放入你将忽略的目录中。

答案 1 :(得分:86)

本周我意外地提交了同样的问题,然后尝试从共享存储库中删除构建文件,并且:

http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html

对我来说很好,到目前为止还没有提到。

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

要从版本控制中删除您感兴趣的文件,请正常使用所有其他命令。

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

如果你想把它放回去。

编辑:请参阅Chris Johnsen和KPM的评论,这只适用于本地,如果他们不这样做,该文件仍然受其他用户的版本控制。接受的答案提供了更完整/正确的方法来处理这个问题。如果使用此方法,也可以从链接中获得一些注释:

  

显然,有很多警告可以发挥作用。   如果你直接添加文件,它将被添加到索引中。   将提交与此标志合并将导致合并失败   优雅,所以你可以手动处理它。

答案 2 :(得分:30)

要从索引中删除文件,请使用:

git reset myfile

这不应该影响您的本地副本或其他任何人。

答案 3 :(得分:15)

执行git rm --cached命令后,尝试将myfile添加到.gitignore文件中(如果不存在则创建一个)。这应该告诉git忽略myfile

.gitignore文件已版本化,因此您需要提交它并将其推送到远程存储库。

答案 4 :(得分:12)

  1. git rm --cached remove_file
  2. 将文件添加到gitignore
  3. git add .gitignore
  4. git commit -m "Excluding"
  5. 玩得开心;)

答案 5 :(得分:1)

我的解决方案是启用其他工作副本然后执行:

git log --pretty="format:" --name-only -n1 | xargs git checkout HEAD^1

表示获取最新评论中的所有文件路径,并从HEAD的父级中检出它们。完成工作。

答案 6 :(得分:0)

上述解决方案适用于大多数情况。 但是,如果您还需要删除该文件的所有痕迹(即密码等敏感数据),您还需要将其从整个提交历史记录中删除,因为仍然可以从那里检索文件。

这是一个解决方案,可以从整个提交历史记录中删除文件的所有痕迹,就像它从未存在过一样,但会将文件保留在系统中。

https://help.github.com/articles/remove-sensitive-data/

如果您在本地git存储库中,实际上可以跳到第3步,并且不需要执行干运行。就我而言,我只需要第3步和第6步,因为我已经创建了我的.gitignore文件,并且在我想要处理的存储库中。

要查看更改,您可能需要转到存储库的GitHub根目录并刷新页面。然后浏览链接以获取曾经拥有该文件的旧提交,以查看它现在已被删除。对我来说,只需刷新旧的提交页面就不会显示更改。

一开始看起来令人生畏,但实际上,它很容易就像魅力一样! : - )