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

Fle*_*ore 157 git version-control gitignore git-rm

当你使用

git rm --cached myfile
Run Code Online (Sandbox Code Playgroud)

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

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

编辑:澄清,我希望.

Chr*_*sen 113

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

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


保存副本,应用删除,还原

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

在删除删除它的提交后将文件还原为未跟踪

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

git show @{1}:foo.conf >foo.conf
Run Code Online (Sandbox Code Playgroud)

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

git checkout @{1} -- foo.conf && git rm --cached foo.conf
Run Code Online (Sandbox Code Playgroud)

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


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

将文件保留为"默认"并手动/自动激活它

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

test -f foo.conf || test -f foo.conf.default &&
    cp foo.conf.default foo.conf
Run Code Online (Sandbox Code Playgroud)

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

重写历史需要手动干预无论如何......

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

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

忽略它以防止再次发生

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

  • 令人难以置信的彻底回应.谢谢! (5认同)

Tom*_*wer 86

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

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

对我来说工作得很好,到目前为止还没有提到.

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

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

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

如果你想再把它放回去.

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

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

  • 这不是所提到的具体问题的答案.它只适用于您自己的本地存储库,因此每个用户都必须自己执行此操作.这是一种痛苦. (7认同)

Arm*_*and 30

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

git reset myfile
Run Code Online (Sandbox Code Playgroud)

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

  • 这回答了标题为"如何从索引中删除文件而不从任何存储库中删除文件"的问题.尽管OP确实在问"如何在不删除本地副本的情况下解开文件". (4认同)
  • 如果文件不在当前 HEAD 提交中,则“reset”仅从索引中删除该文件,否则它只是将索引版本恢复为当前 HEAD 版本。 (3认同)

小智 16

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

  • @Julien 我的想法完全正确,不知道为什么接受的答案必须是博士论文 (4认同)
  • @lasec0203 因为这样 Git 仍然会在其他人拉取后立即删除该文件。问题是如何从索引中获取某些内容而不在拉取时删除它。这似乎是近乎不可能的事情。 (4认同)
  • 这是最简单的。 (2认同)

awg*_*wgy 15

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

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