Git:如何从索引中删除文件而不删除任何存储库中的文件
当你使用
git rm --cached myfile
它不会从本地文件系统中删除,这是目标。 但是,如果您已经对文件进行了版本化和提交,将其推送到中央存储库,并在使用该命令之前将其引入另一个存储库,则会将该文件从该系统中删除。
有没有办法从版本中删除文件而不从任何文件系统中删除?
编辑:澄清,我希望。
我不认为Git的提交可以logging像“停止跟踪这个文件,但不要删除它”的意图。
制定这样的意图将需要在合并(或重新绑定)删除文件的提交的任何存储库中的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
来find提交之前,他们拉你删除。
在一个评论中,你提到你想要“解开但是保留”的文件是运行软件所需的某种configuration文件(直接存储在仓库中)。
保持文件为“默认”并手动/自动激活它
如果继续维护存储库中configuration文件的内容并不是完全不可接受的,那么您可以将跟踪的文件(例如foo.conf
)重命名为foo.conf.default
,然后指导用户使用cp foo.conf.default foo.conf
应用重命名提交后, cp foo.conf.default foo.conf
。 或者,如果用户已经使用存储库的某些现有部分(例如脚本或由存储库中的内容(例如, Makefile
或类似内容)configuration的其他程序)来启动/部署您的软件,则可以将默认机制并入启动/部署过程:
test -f foo.conf || test -f foo.conf.default && cp foo.conf.default foo.conf
有了这样的默认机制,用户应该能够提交一个提交,将foo.conf
重命名为foo.conf.default
而无需做任何额外的工作。 另外,如果将来还要创build其他安装/存储库,则不必手动复制configuration文件。
无论如何,重写历史需要手动干预…
如果维护存储库中的内容是不可接受的,那么您可能希望从历史中彻底根除它,例如git filter-branch --index-filter …
这相当于重写历史logging,这将需要对每个分支/存储库进行手动干预(请参阅git rebase联机帮助页中的“从上游Rebase恢复”一节)。 configuration文件所需的特殊处理只是从重写中恢复时必须执行的另一步骤:
- 保存configuration文件的副本。
- 从重写中恢复。
- 恢复configuration文件。
忽略它以防止复发
不pipe你使用什么方法,你可能都希望在configuration文件名中包含.gitignore
文件,这样任何人都不会无意中再次git add foo.conf
(这是可能的,但需要-f
/ --force
)。 如果你有多个configuration文件,你可能会考虑将它们全部“移动”到一个目录中,而忽略整个目录(“移动”是指改变程序希望findconfiguration文件的位置,启动/部署机制)复制/移动文件到他们的新位置;你显然不希望将mv文件拖入一个你将忽略的目录中)。
如果我不小心犯了这个问题,那么这个问题本来就是一样的,然后试图从一个共享库中删除一个构build文件,这个:
http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html
对我来说工作得很好,到目前为止还没有提到。
git update-index --assume-unchanged <file>
要从版本控制中删除您感兴趣的文件,请正常使用所有其他命令。
git update-index --no-assume-unchanged <file>
如果你想把它放回去。
编辑:请参阅克里斯·约翰森和KPM的评论,这只适用于本地和文件保持在其他用户的版本控制,如果他们也不这样做。 被接受的答案提供了更完整/正确的方法来处理这个问题。 如果使用这种方法,还有一些链接的注释:
显然有很多的警告发挥这一点。 如果你直接添加文件,它会被添加到索引。 合并提交与此标志将导致合并失败优雅,所以你可以手动处理它。
要从索引中删除文件,请使用:
git reset myfile
这不应该影响您的本地副本或其他人的。
在完成git rm --cached
命令之后,尝试将myfile
添加到.gitignore
文件(如果不存在,请创build一个)。 这应该告诉git忽略myfile
。
.gitignore
文件是版本化的,所以您需要提交它并将其推送到远程存储库。
-
git rm --cached remove_file
- 添加文件到gitignore
-
git add .gitignore
-
git commit -m "Excluding"
- 玩的开心 ;)
我的解决scheme是拉对方的工作副本,然后做:
git log --pretty="format:" --name-only -n1 | xargs git checkout HEAD^1
其中说在最新的评论中得到所有的文件path,并从HEAD的父亲检查出来。 任务完成。
上述解决scheme在大多数情况下工作正常。 但是,如果您还需要删除该文件的所有痕迹(例如密码等敏感数据),则还需要将其从整个提交历史logging中删除,因为仍然可以从该文件中检索该文件。
这是一个从整个提交历史logging中删除文件的所有痕迹的解决scheme,就好像它从来没有存在过,但是保留在你的系统上的文件。
https://help.github.com/articles/remove-sensitive-data/
如果您在本地git存储库中,则可以跳到步骤3,而不需要执行空运行。 就我而言,我只需要步骤3和步骤6,因为我已经创build了我的.gitignore文件,并且在我想要处理的存储库中。
要查看更改,可能需要转到存储库的GitHub根目录并刷新页面。 然后浏览链接,find曾经拥有该文件的旧提交,看看它现在已被删除。 对我来说,只需刷新旧的提交页面并没有显示出这个改变。
起初看起来很吓人,但是真的很容易,像魅力一样工作! 🙂