从Git删除文件,但不要删除远程用户,只需忽略它 [英] Remove a file from Git, but don't delete for remote users, merely ignore it

查看:162
本文介绍了从Git删除文件,但不要删除远程用户,只需忽略它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

I和其他几个人都可以访问包含IDE自动生成的一个文件的存储库.该文件是特定于PC的,因此不应该在源代码控制中,但当前是.我想将其删除并将其添加到.gitignore,但是我不希望其他协作者在提取我的更改时将其删除.关于删除文件但保留我的本地副本有很多问题.但他们不会涵盖其他用户,因此即使我保留我的权限,当他们拉动他们时,他们仍然会丢失其副本:

I, and several other people, all have access to a repository that includes one file auto-generated by the IDE. This file is quite PC-specific, so shouldn't be in source control, but currently is. I want to delete it and add it to .gitignore, but I don't want it to be deleted for other collaborators when they pull my changes. There are plenty of questions about deleting a file but keeping my local copy; but they don't cover other users, so when they pull they'll still lose their copy despite me keeping mine:

删除Git存储库中的文件,而无需将其从本地文件系统中删除

如何git rm没有从磁盘删除文件的文件?

还有一些问题和解决方案,以确保在拉动时不丢失本地文件,因此它们可以保留文件,但这需要那些拉动中的显式操作,我不想去告诉所有人确切的拉动方式就这一次.我确实发现了两个重复的问题.那里的答案是无法做到的,但都是在5年前-过渡期间有什么变化吗?

There are also questions and solutions for not losing local files when pulling, so they can keep the files, but this requires explicit actions from those pulling, and I don't want to have to go and tell everyone exactly how to pull just this one time. I did find two questions which are duplicates. The answers there were that it can't be done, but they were both 5 years ago - has anything changed in the interim?

Git删除跟踪的文件,但保持本地和远程

Git忽略文件,但不删除它

这很重要,因为在您首次导入整个项目时该文件是自动生成的,并且包含有关本地编译器/库版本的信息.因此,删除它需要重新导入.如果有什么不同,它是.idea/scala_compiler.xml.idea/scala_settings.xml(实际上应该忽略整个.idea目录).基本上,我希望Git将文件设置为不再跟踪,但不要将其删除.

This is important because the file is auto-generated when you first import the whole project and contains information on local compiler/library versions. So deleting it will require re-importing. If it makes any difference, it's .idea/scala_compiler.xml and .idea/scala_settings.xml (really the whole .idea directory should be ignored). Basically I want to have Git set a file as no longer tracked, but not delete it for anyone.

推荐答案

您不能.

嗯,让我再试一次: 不能,但是 他们可以.嗯,您可以,但只能为您 ,而他们可以,但只能为您 .您或他们必须在正确的时间运行git rm --cached .当然,这是您不想使用的解决方案.

Hm, let me try this again: you can't, but they can. Well, you can, but only for you, and they can, but only for them. You, or they, must run git rm --cached at just the right time. Of course, that's the solution you don't want to use.

更有用地说(有可能重复前面的问题):就Git提交而言,您只能对这些文件做的事情是从以后的Git提交中忽略它们.由于不在提交状态,它们也不会通过推送和获取操作进行传输.

To put it more usefully (at the risk of duplicating the earlier questions): the only thing you can do about these files, in terms of Git commits, is to omit them from future Git commits. By not being in commits, they will not be transferred by push and fetch operations either.

请记住,每次提交都会保存Git知道的所有文件的完整快照.(稍后我们将对其进行进一步完善.)如果Git知道.idea/* ,Git会将它们放入新的提交中,当您推送这些提交时(您不能推送 files ,只有 commits ),那些带有这些文件的提交将进入大约.再次获取新的提交时-您将获得整个 commits 而不是文件-这些提交将随这些文件一起提供.

Remember, each commit holds a full and complete snapshot of all the files that Git knows about. (We'll refine this a bit further in a moment.) If Git knows about .idea/*, Git will put them in new commits, and when you push those commits—you can't push files, only commits—those commits, complete with those files, will go around. When you fetch new commits—again, you get entire commits, not files—those commits will come with those files.

然后,基本问题变成了这样:

The fundamental problem then becomes this:

  • 您(或他们)正在进行Git知道.idea/*的提交.您当前的提交包含文件.
  • 您(或他们)已经获取了一些新的提交.这些新的提交不包含这些.idea/*文件.
  • 如果您(或他们)现在要求您(或他们的)Git将您的切换到当前提交,一个缺少文件,您的Git看到您(或他们)明确告诉您的Git 删除.因此它将这样做.
  • You, or they, are on a commit in which Git knows about .idea/*. Your current commit has the files.
  • You, or they, have fetched some new commit(s). These new commits don't contain these .idea/* files.
  • If you (or they) now ask your (or their) Git to switch you from the current commit, to a commit that lacks the files, your (or their) Git sees that you (or they) are explicitly telling your (their) Git to remove the files. So it will do so.

解决此问题的方法是:

  • 您(他们)必须告诉您(他们的)Git现在忘记这些文件,以便这些文件的工作树副本被未跟踪:

  • You (they) must tell your (their) Git to forget these files now, so that the work-tree copies of these files are untracked:

 git rm -r --cached .idea      # note the --cached

  • 现在(告诉他们)您的Git:切换到新提交.未跟踪的文件根本不在Git的视图中,也不在新的提交中,因此Git 不会删除这些文件的工作树副本.

  • Now you (they) tell your Git: switch to the new commit. The untracked files aren't in Git's view at all, and aren't in the new commit either, so Git won't remove the work-tree copies of these files.

    请注意,如果您将 back 切换到确实包含这些文件的 old 提交,则Git将覆盖您的工作树文件以及已提交的文件. (它们的Git将在相同条件下对它们的工作树文件执行相同的操作.)因此,当返回包含这些文件的历史提交时,请格外小心.有关更多详细信息,请参见下面的详细说明.

    Note that if you ever switch back to an old commit that does contain these files, your Git will overwrite your work-tree files with the committed files. (Their Git will do the same to their work-tree files under the same conditions.) So be very careful when returning to historic commits that contain these files. See the long explanation below for further details.

    正如我们刚刚提到的,每个提交都有每个文件的完整快照.这些快照以特殊的只读Git格式保存.我喜欢将此格式称为冻干.这种形式的文件会自动进行重复数据删除,因此大多数提交大部分都会重复使用前一次提交中的大多数文件,这意味着新提交几乎不会占用任何磁盘空间.

    As we just noted, each commit has a full and complete snapshot of every file. These snapshots are saved in a special, read-only, Git-only format. I like to call this format freeze-dried. The files in this form are automatically de-duplicated, so the fact that most commits mostly re-use most files from a previous commit means that the new commits take hardly any disk space.

    对于Git来说,重新使用这些冻干的文件是安全的,因为任何任何提交(包括保存的文件)的任何部分都无法更改.您可以进行与现有提交不同的新提交,但是不能更改现有提交.甚至Git本身也不能做到这一点.

    It is safe for Git to re-use these freeze-dried files, because no part of any existing commit, including the saved files, can ever be altered. You can make new commits that are different from existing ones, but you cannot change the existing ones. Not even Git itself can do that.

    由于您实际上无法使用这些文件来完成任何实际工作,因此Git必须提取一个提交.这就是git checkout(或者,由于Git 2.23,git switch)所做的:它将某些提交中的冻干文件提取为一种您可以实际使用(并更改)的形式.您选择提取的提交,然后与和/或一起使用的提交是您的当前提交.

    Because you literally can't use these files to do any actual work, Git has to extract a commit. This is what git checkout (or, since Git 2.23, git switch) does: it extracts the freeze-dried files from some commit, into a form that you can actually use (and change). The commit you choose to extract, and then work with and/or on, is your current commit.

    这意味着从当前提交中提取的每个文件实际上都有两个副本:冻干的一个与提交本身一起存储,以及常规格式的重新水化的副本,您正在使用它们进行实际工作.

    This means there are literally two copies of every file taken from the current commit: the freeze-dried one stored with the commit itself, and the regular-format, rehydrated one you're using to do real work.

    要进行 new 提交,任何使用这种方案的版本控制系统(尽管内部细节差异很大,但大多数都这样做)必须采用当前工作树的版本并将其转换返回适当的提交版本.在大型存储库中,这可能需要一段时间.为了使自己更容易,Git实际上根本没有这样做.

    To make a new commit, any version control system that uses this kind of scheme—and most do, though internal details vary a great deal—must take your current work-tree versions and turn them back into the appropriate committed versions. This can take quite a while, in large repositories. To make it easier for itself, Git doesn't actually do this at all.

    相反,Git保留了一个第三副本-确切地说,不是一个真正的副本副本,因为它使用的是冻干,去重的格式-与Git相同调用其 index staging区域,或(最近很少)调用 cache .文件的此缓存,冻结干燥格式,预先删除重复的副本已准备好进入您将要进行的下一次提交.

    Instead, Git keeps a third copy—well, not really a copy, exactly, because it uses the freeze-dried, de-duplicated format—in what Git calls its index, or staging area, or (rarely these days) cache. This cached, freeze-dried-format, pre-de-duplicated copy of the file is ready to go into the next commit you will make.

    让我们用黑体重复一下,因为这是这里的关键: Git的索引包含将进入 next 提交的文件,其格式为冻干,随时可以去. git checkoutgit switch操作从提交(现在为 current 提交)中填充Git的索引和工作树.现在,所有三个副本都匹配,除了工作树副本实际上是可用的,而不是冻干的.

    Let's repeat that in bold because it's the key here: Git's index contains the files that will go into the next commit, in the freeze-dried format, ready to go. A git checkout or git switch operation fills Git's index and your work-tree from a commit, which is now the current commit. All three copies now match, except that the work-tree copy is actually usable, instead of being freeze-dried.

    如果更改工作树副本,则必须在其上运行git add. git add命令告诉Git:使您的索引副本与我的工作树副本匹配. Git现在将读取工作树副本并将其压缩并重复数据删除到冻干的中.格式,准备进行下一次提交.因此,索引中的文件不再与当前提交中的文件匹配.换句话说, index commit 之间的主要区别在于,您可以 通过替换这样批发的文件来更改索引内容.

    If you change the work-tree copy, you must run git add on it. The git add command tells Git: Make your index copy match my work-tree copy. Git will now read the work-tree copy and compress and de-duplicate it into the freeze-dried format, ready to go into the next commit. So the files in the index no longer match the files in the current commit. In other words, a key difference between the index and the commit is that you can change the index contents, by replacing files wholesale like this.

    从字面上看,这些索引副本是Git知道的文件.它们是将在 next 提交中的文件.要确保下一个提交 没有文件,只需将其从Git的索引中删除即可.

    These index copies are, literally, the files that Git knows about. They are the files that will be in the next commit. To make sure the next commit doesn't have some file, you simply remove it from Git's index.

    git rm命令从Git的索引中删除文件.如果没有--cached,它将从您的工作树中删除这些文件.您想保留工作树副本,因此需要告诉Git:通过在git rm中添加--cached来保持我的工作树副本:仅从索引中删除(缓存" ;).

    The git rm command removes files from Git's index. Without --cached, it also removes these files from your work-tree. You want to keep your work-tree copy, so you need to tell Git: keep my work-tree copy by adding --cached to your git rm: remove only from the index ("cache").

    现在,文件或文件在Git的索引中没有,它们将不在 next 提交中.因此,一旦删除了文件,就可以重新提交拥有文件:

    Now that the file, or files, aren't in Git's index, they won't be in the next commit. So once you remove the files, you can make a new commit that doesn't have the files:

    git rm -r --cached .idea && git commit
    

    例如.

    当您使用git checkoutgit switch从一个提交切换到另一个提交时(例如,通过更改您所在的分支),您会告诉Git:删除与相关的所有内容当前提交并切换到另一个提交.这使Git清空了索引,删除了每个相应文件(Git知道的文件)的工作树副本.然后,Git可以重新填充其索引,并使用您要进行/使用的提交中的文件副本(即您当前的新提交)重新填充您的工作树.

    When you use git checkout or git switch to switch from one commit to another—as by changing which branch you're on, for instance—you are telling Git: Remove everything related to the current commit and switch to the other commit. This has Git empty out its index, removing your work-tree copy of each corresponding file—the files that Git knows about. Then Git can re-fill its index and re-populate your work-tree with copies of the files from the commit you'd like to work on/with: your new current commit.

    如果Git知道.idea/*,这就是删除.idea/*文件的原因.如果它们不是新提交中的 ,则不会从新提交中 返回.

    If Git knows about .idea/*, this is what makes the .idea/* files get removed. If they're not in the new commit, they don't come back from the new commit.

    .gitignore文件的名称有些错误. .gitignore中列出的文件不一定是未跟踪的,并且如果被跟踪(如果Git知道它们是因为它们在Git的索引中),它们就不会被忽略.

    The .gitignore file is somewhat misnamed. Files listed in .gitignore are not necessarily untracked, and if they are tracked—if Git knows about them because they are in Git's index—they're not ignored at all.

    在这里,请注意,一个未跟踪的文件是目前在您的工作树 中的文件,但是在Git索引中的不是现在.这意味着,如果跟踪了.idea/*(例如,从当前提交中退出了),但是您只运行了git rm --cached .idea/*git rm -r --cached .idea,则这些工作树副本现在将不被跟踪.它们是否在当前的 commit中无关紧要:重要的是它们是否现在位于Git的 index 中.

    Let's note here that an untracked file is one that is in your work-tree right now but not in Git's index right now. That means that if .idea/* were tracked—came out of the current commit, for instance—but you just ran git rm --cached .idea/* or git rm -r --cached .idea, those work-tree copies are now untracked. It doesn't matter if they are in the current commit: what matters is whether they are in Git's index right now.

    .gitignore的作用是告诉Git三件事.前两个通常是重要的两个.最后一个是陷阱.

    What .gitignore does is tell Git three things. The first two are usually the important two. The last one is the trap.

    1. 如果未跟踪文件的名称或模式出现在.gitignore中,则git status命令不会抱怨有关被跟踪文件的信息.

    1. If an untracked file's name, or pattern, appears in .gitignore, the git status command won't complain about the file being untracked.

    如果未跟踪文件的名称或格式出现在.gitignore中,则git add不会将文件添加到 Git的索引中(您可以强制git add如果需要,可以覆盖它).这意味着该文件将在正常的每天git add s内保持未跟踪状态.

    If an untracked file's name or pattern appears in .gitignore, git add won't add the file to Git's index (you can force git add to override this if you want). This means the file will remain untracked across normal everyday git adds.

    如果.gitignore中列出了未跟踪的文件的名称或格式,则Git有时会更聪明地文件.

    If an untracked file's name or pattern is listed in .gitignore, Git will sometimes feel free to clobber the file.

    当您切换提交时,Git尝试不破坏未保存的工作

    您可能熟悉此问题:开始处理某个文件(即工作树中的副本),然后意识到:我想在另一个分支上进行此工作. /em>您运行git checkout branchgit switch branch,然后Git用某种神秘的方式说:我不能那样做. Git告诉您您有未保存的更改,这些更改将被破坏.

    When you switch commits, Git tries not to clobber unsaved work

    You may be familiar with this problem: you start working on some file—the copy in your work-tree, that is—and then realize: Whoops, I wanted to do this work on a different branch. You run git checkout branch or git switch branch, and Git says, in its somewhat cryptic way: I can't do that. Git tells you that you have unsaved changes that would be clobbered.

    (有时Git仍将允许您切换分支.这又与Git的索引有关.有关血腥的详细信息,请参见当前分支上有未提交的更改时签出另一个分支)

    (Sometimes Git will let you switch branches anyway. This all has to do with Git's index, again. For the gory details, see Checkout another branch when there are uncommitted changes on the current branch)

    如果此未保存的作品位于跟踪文件中,或者位于.gitignore中未列出 的未跟踪文件中,则此安全检查将使您不会丢失数据.但是在.gitignore中列出文件会有时允许Git覆盖或删除工作树副本.发生这种情况的确切时间并不明显-有时即使正确执行,Git也会告诉您先保存文件-但这是一个问题.

    If this unsaved work is in a tracked file, or is in an untracked file that's not listed in a .gitignore, this safety check will keep you from losing data. But listing a file in .gitignore will sometimes allow Git to overwrite or remove the work-tree copy. It's not obvious precisely when this happens—sometimes even with this in place, Git tells you to save your files first—but it is a problem.

    不幸的是,解决此问题的唯一真正方法是与问题本身一样痛苦或更痛苦:您可以使用具有包含文件的提交的存储库,然后使用该存储库来构建新的,不兼容的已编辑内容,历史存储库仅包含根本没有文件的提交.

    Unfortunately, the only real solution to this problem is as painful as, or more painful than, the problem itself: you can take the repository that has commits that have the files, and use that to build a new, incompatible edited-history repository that contains only commits that never had the files at all.

    要执行此操作,请使用git filter-branchgit filter-repo(相对较新,但尚未随Git本身分发),BFG或任何此类Git-commit-history编辑系统.所有这些工作的必要方式是将它们(具有文件的旧提交)复制到具有不同哈希ID的新提交中,这些文件永远不会出现.然后,该变化在时间上波动随着时间下降".进入所有后续提交.这就是使新存储库与旧存储库不兼容的原因.

    To do this, use git filter-branch, or git filter-repo (relatively new and still not distributed with Git itself yet), or The BFG, or any such Git-commit-history-editing system. The way these all work, of necessity, is that they copy old commits—those that have the files—to new commits, with different hash IDs, in which those files never appear. This change then ripples "down through time" into all subsequent commits. That's what makes the new repository incompatible with the old one.

    如果您让旧的存储库和新的存储库相遇,并且有任何相关的历史记录没有发生变化, 1 这两个Git将把旧的存储库和新的存储库合并在一起.新的历史记录,那么您实际上将使存储库的大小增加一倍,同时回加所有您已经想到摆脱的提交.

    If you ever let the old repository and new one meet, and there's any related history that didn't change,1 the two Gits will join up the old and new histories and you'll essentially double the size of your repository while adding back all the commits you thought you had gotten rid of.

    1 这将是历史提交,它早于有害文件的存在.例如,如果您使用GitHub的以README.mdLICENSE文件开头的技巧,则该提交将不需要重写,并且将保持不变,并在新旧存储库之间建立通用的提交历史记录.

    1This would be historical commits that predate the existence of the unwanted files. For instance, if you use GitHub's trick of starting with a README.md and LICENSE file, that commit would not require rewriting, and would remain unchanged and establish a common commit history between the old and new repositories.

    此外,如果您使用的旧Git可以追溯到--allow-unrelated-histories标志之前,或者将--allow-unrelated-histories提供给git merge,那么也可以将旧的历史融合到新的历史中.

    Besides this, if you use an old Git that dates back to before the --allow-unrelated-histories flag, or supply --allow-unrelated-histories to git merge, that can also fuse the old history back into the new one.

    这篇关于从Git删除文件,但不要删除远程用户,只需忽略它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆