简体   繁体   English

Git:如何取消跟踪文件而不将它们暂存以进行删除

[英]Git: how to untrack files without staging them for deletion

I have some config files that I want to change locally but not risk accidentally committing those changes.我有一些我想在本地更改的配置文件,但不会冒意外提交这些更改的风险。 They also cannot be added to gitignore because they need to be tracked for the project as a whole.它们也不能添加到 gitignore 中,因为它们需要在整个项目中进行跟踪。 When I modify those files to suit my environment's needs, my git status looks like this:当我修改这些文件以满足我的环境需要时,我的git status如下所示:

Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   config1.cfg
        modified:   config2.cfg

Untracked files:
    (use "git add <file>..." to include in what will be committed)

        whatever.html
        somethingElse.js

then I run:然后我运行:

git rm --cached config1.cfg config2.cfg

and git status looks like this:git status看起来像这样:

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    config1.cfg
        deleted:    config2.cfg

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    config1.cfg
    config2.cfg
    whatever.html
    somethingElse.js
    

Running git reset --HEAD config1.cfg config2.cfg returns them to the staging area, predictably.运行git reset --HEAD config1.cfg config2.cfg可预见地将它们返回到暂存区。 But it kind of doesn't make sense that something could be untracked and still staged at the same time, even if that staging is for deletion.但是,即使该暂存是为了删除,某些内容可以未被跟踪并仍然同时上演,这有点没有意义。 But also -- I didn't delete the files, but if I commit now then they will be deleted.但也 - 我没有删除文件,但如果我现在提交,那么它们将被删除。

I realize that this might be a better use case for smudge and clean filters, but is it possible to reach a state where a previously tracked file is untracked and it is as if it has never been tracked?我意识到这可能是污迹和清洁过滤器的更好用例,但是是否有可能达到以前跟踪的文件未被跟踪并且就好像它从未被跟踪过的状态? If not, is there a good reason it isn't possible?如果没有,是否有充分的理由不可能?

Editing to clarify now that I understand the situation a little better: the scenario I'm trying to create is one where the files are untracked on my local while I'm working, without affecting their tracking status on the remote.编辑以澄清现在我对情况的理解更好一点:我尝试创建的场景是在我工作时在本地未跟踪文件的场景,而不影响它们在遥控器上的跟踪状态。

but if I commit now then they will be deleted.但如果我现在提交,那么它们将被删除。

No. The files (the things you see in front of you in the work tree) will not be deleted.不会。文件(您在工作树中看到的内容)不会被删除。 Committing has no effect on the work tree.提交对工作树没有影响

The commit will record them as deleted, as it must do, because they were present in the previous commit and now you are saying they should not be present in this next commit.提交会将它们记录为已删除,这是必须的,因为它们存在于上一次提交中,现在您说它们不应该出现在下一次提交中。 That is what a deletion is: something that was present is now no longer present.这就是删除:曾经存在的东西现在不再存在。

The Three Places of Git Git 的三个地方

It sounds like you might benefit from knowing a bit about what Git "is".听起来您可能会从了解 Git“是什么”中受益。 Git exercises sway over three places: Git 练习影响了三个地方:

  • The work tree .工作树 This is what Git shows you.这就是 Git 向您展示的内容。 It is a rendering of a folder full of files onto disk so that you can edit those files.它是将一个充满文件的文件夹渲染到磁盘上,以便您可以编辑这些文件。

  • The index .指数 Also called the staging area or cache.也称为暂存区或缓存。 This is an invisible collection of references to files that constructs what your next commit will consist of.这是一个不可见的文件引用集合,用于构建您的下一次提交将包含的内容。

  • The actual repository .实际的存储库 An invisible collection of commits .一个不可见的提交集合。 The commits themselves each contain files, in a certain sense of the word "contain" whose details are not important here.提交本身每个都包含文件,从某种意义上说,“包含”这个词的细节在这里并不重要。

When you check out a branch, you are checking out a commit.当您检出一个分支时,您正在检出一个提交。 The commit is used to populate the work tree and the index;提交用于填充工作树和索引; they all match up at that moment.他们都在那一刻匹配。

If you change one file in the work tree (which is the only place where you can change anything) and add it and commit, then only that one file changed, true, but all the other files are still there in the work tree and the index, so this commit contains all the files — not just the file that you changed (that is a common misconception).如果您更改工作树中的一个文件(这是您可以更改任何内容的唯一位置)并添加它并提交,那么只有那个文件更改了,是的,但所有其他文件仍然存在于工作树中,并且index,所以这次提交包含所有文件——而不仅仅是你更改的文件(这是一个常见的误解)。 Every commit is a snapshot of the whole state of the index at the time it was created, which in turn is a reflection of the whole state of the work tree, mediated by what you have elected to add to the index.每次提交都是索引创建时整个状态的快照,这反过来又反映了工作树的整个状态,由您选择添加到索引的内容介导。

So the index is the place where you get to manipulate the relationship between what you did in the work tree and what will go into the next commit.因此,索引是您可以操纵您在工作树中所做的事情与将进入下一次提交的内容之间的关系的地方。 When you say git add .当你说git add . , you are saying, in effect, "the index should reflect everything I did in the work tree". ,您实际上是在说“索引应该反映我在工作树中所做的一切”。 But that is a very broad command;但这是一个非常广泛的命令; you have absolute file-by-file fine control of what the index should look like in the run-up to the next commit.您对索引在下一次提交的准备阶段应该是什么样子有绝对的逐个文件精细控制。

What You Did你做了什么

When you said git rm --cached config1.cfg , you said, "Remove the reference to config1.cfg from the index ."当你说git rm --cached config1.cfg ,你说,“从索引中删除对config1.cfg引用。” This will have no effect on the work tree when you commit;当您提交时,这不会对工作树产生影响; it will just make a commit in which config1.cfg happens to be absent.它只会进行一次提交,其中config1.cfg恰好不存在。

But now you are thinking about that, and you are realizing that isn't what you meant to say, because the next commit will constitute a deletion of config1.cfg .但是现在您正在考虑这一点,并且您意识到这不是您的意思,因为下一次提交将构成对config1.cfg删除 You don't like that.你不喜欢那样。 You do want the next commit to still contain config1.cfg ;确实希望下一次提交仍包含config1.cfg you just don't want it to be changed from the previous commit.你只是不希望它从以前的提交中改变

That, I take it, is what you mean when you say:我认为,这就是您说的意思:

I have some config files that I want to change locally but not risk accidentally committing those changes我有一些我想在本地更改的配置文件,但不会冒意外提交这些更改的风险

What You Should Have Done你应该做的

Your goal was not to make a commit in which config1.cfg was not present.您的目标不是进行不存在config1.cfg的提交。 Your goal was to make a commit in which config1.cfg was unchanged from its previous state, even though you have in fact edited it in the work tree.您的目标是进行提交,其中config1.cfg与其之前的状态没有变化,即使您实际上已经在工作树中对其进行了编辑。

Okay, so what should you have done in order to make that happen?好的,那么你应该怎么做才能做到这一点? Well, the first line of defense is: don't say git add .嗯,第一道防线是:不要说git add . or some blanket globbing statement like that.或一些像这样的笼统声明。 Instead, in order to not add changed files to the index, don't add them .相反,为了将更改的文件添加到索引中,请不要添加它们 Just add to the index the changed files that you do want to reflect in the next commit.只需添加到索引修改过的文件,想在反映下一个承诺。

But let's say you recklessly blew past that safeguard and you did add config1.cfg in its changed state to the index.但是,假设您不顾一切地突破了该保护措施,并且确实将处于更改状态的config1.cfg添加到索引中。 (You did.) Then say git restore --staged config1.cfg . (你做到了。)然后说git restore --staged config1.cfg This copies config1.cfg out of the last commit (every commit contains all the files, remember?) into the index.会将 config1.cfg从上次提交(每个提交都包含所有文件,还记得吗?)复制到索引中。 So now the config1.cfg in the index looks like the previous commit, not like the work tree version.所以现在索引中的config1.cfg看起来像以前的提交,而不像工作树版本。 The status will be then that git knows you have modified config1.cfg in the work tree (unless you have added it to the gitignores file), but that change is not slated to be included in the next commit you make.状态将是 git 知道您已经修改了工作树中的config1.cfg (除非您已将其添加到 gitignores 文件中),但该更改不会包含在您进行的下一次提交中。

(Before Git version 2.25.0, you would have used a form of git reset to accomplish this goal, namely git reset config1.cfg . But git reset is scary, so if you have a sufficiently new Git, use restore instead.) (在 Git 2.25.0 版本之前,你会使用一种git reset形式来实现这个目标,即git reset config1.cfg 。但是git reset很可怕,所以如果你有一个足够新的 Git,请改用restore 。)

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

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