是否git rm <object>仅影响所有分支机构或HEAD?根据我的理解,答案是肯定的,因为要使该命令有效,必须遵循一个commit命令,但这就是我的问题.
那么git rm --cache <object>,因为它不会从工作目录树中删除文件而是被跟踪并将对象添加到.gitignore
我的问题:
dirn的答案是正确的,所以这有点多余,并且还有很多关于这两个问题git rm及其对于跟踪或忽略文件意味着什么的问题,但基于评论,我认为这可能是解释这些问题的更好方法几个项目:
短的(并非100%准确但足够接近)答案是,如果文件在索引中,则会跟踪该文件.
git rm办?该git rm命令默认执行两项操作:
它从索引中删除文件 - 除了此删除被延迟.由于技术原因,它将"要删除"条目写入索引,而不是仅删除索引条目.
它从工作树中删除文件.
当你添加--cached(如在git rm --cached file1 dir/file2)时,Git只执行第一步,跳过第二步.也就是说,它从索引中删除(延迟删除)文件:对于作为参数给出的每个文件,它将一个条目写入索引,该条目显示"下次提交时,将该文件保留在该提交之外. " 也就是说,该文件目前仍然被跟踪,但作为特殊的"以便被删除"而不是"通常被跟踪".
请注意,git rm根本不会触及.gitignore任何方式 - 除非您运行git rm .gitignore(在这种情况下,它会添加"要删除"索引条目并删除工作树文件).
索引在合并中具有很大且非常特殊的作用,但忽略了这一点,索引主要用作Git一次一个段地进行"下一次提交"的方式,因此它git commit本身非常快.许多其他版本控制系统根本没有索引,而是通过扫描每个文件在提交时构造类似于它的东西.这需要很长时间.而Git所做的是"预先准备"每个提交:索引始终保持下一个提交.
这意味着在进行提交后,索引会完全匹配提交.1 这也意味着如果你现在运行git checkout devor git checkout feature或者git checkout master,Git可以通过将该提交的文件与当前索引中的文件进行比较来切换到该分支上的该提交.它只需要改变的是,文件是不同的 -或者,当然,删除在当前的文件提交,但不是在对被检出的提交,或添加不在当前提交,但新文件是在待检查的提交中.所以索引不仅加速git commit,而且速度也加快git checkout.
1这会因core.eol设置和Git称为污迹过滤器之类的东西而变得复杂,所以让我们忽略它们.:-)
(当然,索引在合并中具有特殊的作用.事实上,对于每个文件,索引最多有四个插槽,而不仅仅是一个插槽.这些被称为"阶段编号",而Git只用于每个文件最多三个阶段数.合并使用阶段1,2和3,而正常操作仅使用阶段零.索引实际上只存储文件哈希ID.文件数据 - 每个文件的实际内容 - 保存在Git中对象,在存储库内.)
综上所述,虽然指数是什么将进入下一个承诺,你做.您git add和git rm文件更新索引,然后您git commit将索引内容(所有跟踪文件的集合)转换为新提交.无论索引中的内容是什么,都会成为该提交中的内容.进行新提交会导致当前分支延长一次提交,以便分支名称指向刚刚进行的新提交.
任何新提交都不会更改现有提交.事实上,Git 无法通过设计更改任何对象(提交,树,文件或带注释的标记).似乎改变某些东西的命令,比如git commit --amend或者git rebase,实际上是假的:它们做出新的提交,将旧的提交保留在原地,不受干扰,然后拉出舞台魔术师的伎俩,使用烟雾和镜子使其看起来好像是新的已经取代旧的.
.gitignore办?(有关未跟踪文件的更多信息)我想说这.gitignore是这个文件的错误名称,因为它实际上不是一个文件列表,甚至是忽略的 glob模式.忽略更多的是副作用而不是其他任何东西.真正的问题是提交的内容,正如我们刚才所指出的,这是由索引中的内容决定的.换句话说,真正的问题是跟踪哪些文件,哪些文件没有被跟踪.
当你运行时git status- 你应该经常这样做 - 你得到这样的输出(实际输出,但为了发布目的而略微修剪):
On branch master
Changes to be committed:
modified: pack.c
Changes not staged for commit:
modified: pytest/client.py
Untracked files:
pytest/README
Run Code Online (Sandbox Code Playgroud)
什么git status(除其他外)是运行两个差异,一个从当前提交到索引 - 这是它找到"要提交的更改" - 以及从索引到工作树的一个.后者发现"没有为提交pytest/client.py暂停的更改",例如此处,以及"未跟踪文件",例如pytest/README此处.
我们已经注意到未跟踪的文件是不在索引中的文件.所以pytest/README不在索引中(事实上它不是).
现在,还有一大堆*.o文件(来自C代码)和*.pyc文件(来自Python代码).这些都还没有在索引中,但git status没有抱怨他们.那是因为它们是通过glob模式在.gitignore文件中提到的.
在git status投诉未跟踪文件之前,git status查看文件中的信息.gitignore.如果文件未跟踪,但也标记为已忽略,则会git status抑制其投诉.所以在这个意义上,文件.gitignore是"不要抱怨".
与此同时,虽然,我可以做git add .或git add *多个文件添加到索引中.如果文件已经存在,这将更新索引条目,否则将添加新条目.然而,就在git add实际向索引添加新文件之前,它会查看从文件中获取的信息.如果文件未跟踪(尚未在索引中)并标记为已忽略,则不会添加该文件.但是如果已经跟踪了该文件,则永远不要关闭这个特定的代码路径,Git会更新该文件..gitignoregit addgit add
换句话说,对于已经跟踪的文件,条目.gitignore无效.从这个意义上说,文件中.gitignore的"不会自动添加这些文件,但如果已经添加它们就会更新它们".请注意,您可以使用git add -f(或--force)添加列为已忽略的文件,即强制超过此"不添加"指令.
但是,列出的文件.gitignore还有第三个属性.通常,当Git正在执行一些可能破坏文件的操作时 - 例如检出不同的提交,当你现在修改了(跟踪的)文件但没有提交更改,并且新签出的提交有不同的版本该文件通常,在这种情况下,Git将停止并抱怨您的请求将覆盖未保存或已提交更改的文件.但如果该文件被列为忽略,Git认为该文件"非珍贵"或"可交易".在这种情况下,Git将继续并覆盖该文件.
那么,这三个含义是.gitignore:不要抱怨未跟踪的文件,不要自动添加它们,并随意丢弃它们.因此,涵盖所有案例的单个文件名将是.git-dont-complain-about-and-dont-add-but-do-trash-these-files或类似的.您可以看到为什么要调用它.gitignore.:-)
git rm --cached使用的一个主要原因git rm --cached是错误地提交文件的常见情况.
例如,假设这src.tar是一个包含所有其他文件的tarball文件,并且它处于早期提交状态,并且从那时起就一直存在.它充满了现在过时的代码,应该删除.这不是问题:你只是git rm src.tag提交并继续前进.什么都没有使用它,它只是杂乱无章.它永远在存储库中,但没有人真正关心.
另一方面,假设database.sql意外得到了承诺,它是一个庞大而活跃的数据库,必须留在工作树中,但从来没有被认为是已经提交.在这种情况下,你git rm --cached database.sql,并添加database.sql或*.sql以.gitignore确保它不会git add在以后错误地获取,然后git commit.嗯,这对你来说很好:你已经做了一个新的提交,其中文件不再存在,现在它已经脱离了索引,git status不再抱怨它,等等.
但是,如果你有git checkout一个较旧的承诺,现在你遇到了麻烦.在较旧的提交中,database.sql存在.因此,Git将破坏文件的当前版本,将其替换为旧版本.如果文件不在.gitignore,你至少会得到一个警告 - 但它是.gitignore这样的,所以Git会随意破坏数据库.
没有完美的治疗方法.您可以将其保留为不被忽略,以便Git不会随意破坏它.但是,这会阻止您检出旧的提交.(这可能没问题,因为您可能不应该在实时服务器上执行此操作.)它还会让某人意外地重新添加数据库.(这可能没问题,因为人们可能不应该在实时服务器上进行Git工作.)而且,它会不断出现git status.(人们可能不应该在实时服务器上做Git工作.这里有一个主题...... :-))
还有其他类似的不恰当提交文件的情况,并且与所有这些文件一样,没有完美的方法来实现它们.请记住,当你git checkout提交的是确实有该文件,Git会尝试检查出到工作树,而当你再从去那个承诺一个不具有文件,Git会尝试将其删除.
| 归档时间: |
|
| 查看次数: |
6027 次 |
| 最近记录: |