繁体   English   中英

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

[英]Git: How to remove file from index without deleting files from any repository

当你使用

git rm --cached myfile

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

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

编辑:澄清,我希望。

我不认为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联机帮助页中的“从上游重新库中恢复”部分)。 配置文件所需的特殊处理只是在从重写中恢复时必须执行的另一个步骤:

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

忽略它以防止再次发生

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

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

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的评论,这只适用于本地,如果他们不这样做,该文件仍然受其他用户的版本控制。 接受的答案提供了更完整/正确的方法来处理这个问题。 如果使用此方法,也可以从链接中获得一些注释:

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

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

git reset myfile

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

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

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

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

我的解决方案是拉上另一个工作副本然后执行:

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM