Git:如何从索引中删除文件而不从任何存储库中删除文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2604625/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Git: How to remove file from index without deleting files from any repository
提问by Fletcher Moore
When you use
当你使用
git rm --cached myfile
it doesn't delete from the local filesystem, which is the goal. But if you've already versioned and committed the file, pushed it to a central repository, and pulled it into yet another repository before using the command, it will delete the file from that system.
它不会从本地文件系统中删除,这是目标。但是,如果您已经对文件进行了版本控制和提交,将其推送到中央存储库,然后在使用该命令之前将其拉入另一个存储库,则它将从该系统中删除该文件。
Is there a way to just remove the file from versioning without deleting it from any filesystem?
有没有办法只从版本控制中删除文件而不从任何文件系统中删除它?
Edit: Clarified, I hope.
编辑:澄清,我希望。
采纳答案by Chris Johnsen
I do not think a Git commit can record an intention like “stop tracking this file, but do not delete it”.
我不认为 Git 提交可以记录“停止跟踪这个文件,但不要删除它”这样的意图。
Enacting such an intention will require intervention outside Git in any repositories that merge (or rebase onto) a commit that deletes the file.
制定这样的意图将需要在 Git 之外的任何存储库中进行干预,这些存储库合并(或变基到)删除文件的提交。
Save a Copy, Apply Deletion, Restore
保存副本、应用删除、还原
Probably the easiest thing to do is to tell your downstream users to save a copy of the file, pull your deletion, then restore the file.
If they are pulling via rebase and are ‘carrying' modifications to the file, they will get conflicts. To resolve such conflicts, use git rm foo.conf && git rebase --continue
(if the conflicting commit has changes besides those to the removed file) or git rebase --skip
(if the conflicting commit has only changed to the removed file).
可能最简单的方法是告诉您的下游用户保存文件的副本,删除您的删除内容,然后恢复文件。如果他们通过 rebase 拉取并“携带”对文件的修改,他们就会发生冲突。要解决此类冲突,请使用git rm foo.conf && git rebase --continue
(如果冲突提交除了已删除文件的更改之外还有更改)或git rebase --skip
(如果冲突提交仅更改为已删除文件)。
Restore File as Untracked After Pulling a Commit That Deletes It
在拉取删除文件的提交后将文件恢复为未跟踪
If they have already pulled your deletion commit, they can still recover the previous version of the file with git show:
如果他们已经拉取了您的删除提交,他们仍然可以使用git show恢复文件的先前版本:
git show @{1}:foo.conf >foo.conf
Or with git checkout(per comment by William Pursell; but remember to re-remove it from the index!):
或者使用git checkout(根据 William Pursell 的评论;但请记住将其从索引中重新删除!):
git checkout @{1} -- foo.conf && git rm --cached foo.conf
If they have taken other actions since pulling your deletion (or they are pulling with rebase into a detached HEAD), they may need something other than @{1}
. They could use git log -g
to find the commit just before they pulled your deletion.
如果他们在删除您的删除后采取了其他操作(或者他们正在将 rebase 拉入分离的 HEAD),则他们可能需要除@{1}
. 他们可以git log -g
在删除您的删除之前使用它来查找提交。
In a comment, you mention that the file you want to “untrack, but keep” is some kind of configuration file that is required for running the software (directly out of a repository).
在评论中,您提到要“取消跟踪但保留”的文件是运行软件所需的某种配置文件(直接从存储库中提取)。
Keep File as a ‘Default' and Manually/Automatically Activate It
将文件保留为“默认”并手动/自动激活它
If it is not completely unacceptable to continue to maintain the configuration file's content in the repository, you might be able to rename the tracked file from (e.g.) foo.conf
to foo.conf.default
and then instruct your users to cp foo.conf.default foo.conf
after applying the rename commit.
Or, if the users already use some existing part of the repository (e.g. a script or some other program configured by content in the repository (e.g. Makefile
or similar)) to launch/deploy your software, you could incorporate a defaulting mechanism into the launch/deploy process:
如果继续在存储库中维护配置文件的内容并非完全不可接受,您可以将跟踪文件从(例如)重命名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
With such a defaulting mechanism in place, users should be able to pull a commit that renames foo.conf
to foo.conf.default
without having to do any extra work.
Also, you avoid having to manually copy a configuration file if you make additional installations/repositories in the future.
有了这样的默认机制,用户应该能够拉取重命名foo.conf
为的提交,foo.conf.default
而无需做任何额外的工作。此外,如果您将来进行其他安装/存储库,则不必手动复制配置文件。
Rewriting History Requires Manual Intervention Anyway…
无论如何,重写历史都需要人工干预……
If it is unacceptable to maintain the content in the repository then you will likely want to completely eradicate it from history with something like git filter-branch --index-filter …
.
This amounts to rewriting history, which will require manual intervention for each branch/repository (see “Recovering From Upstream Rebase” section in the git rebasemanpage).
The special treatment required for your configuration file would be just another step that one must perform while recovering from the rewrite:
如果在存储库中维护内容是不可接受的,那么您可能希望使用类似git filter-branch --index-filter …
. 这相当于重写历史记录,这将需要对每个分支/存储库进行手动干预(请参阅git rebase 手册页中的“从上游 Rebase 恢复”部分)。配置文件所需的特殊处理只是从重写中恢复时必须执行的另一个步骤:
- Save a copy of the configuration file.
- Recover from the rewrite.
- Restore the configuration file.
- 保存配置文件的副本。
- 从重写中恢复。
- 恢复配置文件。
Ignore It to Prevent Recurrence
忽略它以防止复发
Whatever method you use, you will probably want to include the configuration filename in a .gitignore
file in the repository so that no one can inadvertently git add foo.conf
again (it is possible, but requires -f
/--force
).
If you have more than one configuration file, you might consider ‘moving' them all into a single directory and ignoring the whole thing (by ‘moving' I mean changing where the program expects to find its configuration files, and getting the users (or the launch/deploy mechanism) to copy/move the files to to their new location; you obviously would not want to git mva file into a directory that you will be ignoring).
无论您使用什么方法,您可能都希望将配置文件名.gitignore
包含在存储库中的文件中,以便任何人都不会无意中git add foo.conf
再次出现(这是可能的,但需要-f
/ --force
)。如果您有多个配置文件,您可能会考虑将它们全部“移动”到一个目录中并忽略整个内容(“移动”是指更改程序期望找到其配置文件的位置,并获取用户(或启动/部署机制)将文件复制/移动到它们的新位置;您显然不希望将文件git mv放入您将忽略的目录中)。
回答by Tom Power
Had the very same issue this week when I accidentally committed, then tried to remove a build file from a shared repository, and this:
本周我不小心提交时遇到了同样的问题,然后尝试从共享存储库中删除构建文件,这是:
http://gitready.com/intermediate/2009/02/18/temporarily-ignoring-files.html
http://gitready.com/intermediate/2009/02/18/temporously-ignoring-files.html
has worked fine for me and not mentioned so far.
对我来说效果很好,到目前为止还没有提到。
git update-index --assume-unchanged <file>
To remove the file you're interested in from version control, then use all your other commands as normal.
要从版本控制中删除您感兴趣的文件,然后照常使用所有其他命令。
git update-index --no-assume-unchanged <file>
If you ever wanted to put it back in.
如果你想把它放回去。
Edit: please see comments from Chris Johnsen and KPM, this only works locally and the file remains under version control for other users if they don't also do it. The accepted answer gives more complete/correct methods for dealing with this. Also some notes from the link if using this method:
编辑:请参阅 Chris Johnsen 和 KPM 的评论,这仅适用于本地,如果其他用户不这样做,则该文件仍处于版本控制之下。接受的答案提供了更完整/正确的方法来处理这个问题。如果使用此方法,还有来自链接的一些注意事项:
Obviously there's quite a few caveats that come into play with this. If you git add the file directly, it will be added to the index. Merging a commit with this flag on will cause the merge to fail gracefully so you can handle it manually.
显然,有很多注意事项与此有关。如果直接 git add 文件,它会被添加到索引中。合并带有此标志的提交将导致合并正常失败,因此您可以手动处理它。
回答by Armand
To remove the file from the index, use:
要从索引中删除文件,请使用:
git reset myfile
This should not affect your local copy or anyone else's.
这不应影响您的本地副本或其他任何人的副本。
回答by Анастасия Ермолик
git rm --cached remove_file
- add file to gitignore
git add .gitignore
git commit -m "Excluding"
- Have fun ;)
git rm --cached remove_file
- 将文件添加到 gitignore
git add .gitignore
git commit -m "Excluding"
- 玩得开心 ;)
回答by awgy
After doing the git rm --cached
command, try adding myfile
to the .gitignore
file (create one if it does not exist). This should tell git to ignore myfile
.
执行完git rm --cached
命令后,尝试添加myfile
到.gitignore
文件中(如果不存在则创建一个)。这应该告诉 git 忽略myfile
.
The .gitignore
file is versioned, so you'll need to commit it and push it to the remote repository.
该.gitignore
文件是版本化的,因此您需要提交它并将其推送到远程存储库。
回答by Tom Viner
My solution is to pull on the other working copy and then do:
我的解决方案是拉上另一个工作副本,然后执行以下操作:
git log --pretty="format:" --name-only -n1 | xargs git checkout HEAD^1
which says get all the file paths in the latest comment, and check them out from the parent of HEAD. Job done.
它说获取最新评论中的所有文件路径,并从 HEAD 的父项中检出。任务完成。
回答by SherylHohman
The above solutions work fine for most cases. However, if you also need to remove all traces of that file (ie sensitive data such as passwords), you will also want to remove it from your entire commit history, as the file could still be retrieved from there.
上述解决方案适用于大多数情况。但是,如果您还需要删除该文件的所有痕迹(即敏感数据,例如密码),您还需要从整个提交历史记录中删除它,因为仍然可以从那里检索该文件。
Here is a solution that removes all traces of the file from your entire commit history, as though it never existed, yet keeps the file in place on your system.
这是一个解决方案,可以从整个提交历史记录中删除文件的所有痕迹,就好像它从未存在过一样,但将文件保留在您的系统上。
https://help.github.com/articles/remove-sensitive-data/
https://help.github.com/articles/remove-sensitive-data/
You can actually skip to step 3 if you are in your local git repository, and don't need to perform a dry run. In my case, I only needed steps 3 and 6, as I had already created my .gitignore file, and was in the repository I wanted to work on.
如果您在本地 git 存储库中,则实际上可以跳到第 3 步,并且不需要执行试运行。就我而言,我只需要第 3 步和第 6 步,因为我已经创建了我的 .gitignore 文件,并且在我想要处理的存储库中。
To see your changes, you may need to go to the GitHub root of your repository and refresh the page. Then navigate through the links to get to an old commit that once had the file, to see that it has now been removed. For me, simply refreshing the old commit page did not show the change.
要查看更改,您可能需要转到存储库的 GitHub 根目录并刷新页面。然后通过链接导航到曾经拥有该文件的旧提交,以查看它现在已被删除。对我来说,简单地刷新旧的提交页面并没有显示更改。
It looked intimidating at first, but really, was easy and worked like a charm ! :-)
起初看起来很吓人,但实际上,它很容易,而且效果很好!:-)