git - “git rm”命令的作用范围是什么,它对所有分支或HEAD分支都有效吗

标签 git

git rm <object>对所有分支或仅对HEAD都有效吗?
据我所知,答案是肯定的,因为要使该命令生效,必须紧跟commit命令,但这是我的问题。

git rm --cache <object>怎么样,因为它不会从工作目录树中删除文件,而是从跟踪中删除文件并将其添加到.gitignore

我的问题:


它会删除所有分支中的对象吗?
是否将对象添加到.gitignore中,以便在下一次提交存储库分支(HEAD和无HEAD)或仅当前分支(HEAD)时将其忽略?

最佳答案

dirn's answer是正确的,所以这有点多余,关于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 devgit checkout featuregit checkout master,则Git可以通过比较该提交的提交来切换到该分支上的提交。文件到当前索引中的文件。它只需要更改不同的文件-或者,当然,删除当前提交中但不在待签出提交中的文件,或者添加不在当前提交中但属于当前提交的新文件。在要签出的提交中。因此,索引不仅加快了git commit的速度,还加快了git checkout的速度。



1由于core.eol设置以及Git所谓的污迹过滤器之类的事情使事情变得复杂,因此我们忽略它们。 :-)



(当然,索​​引在合并中具有特殊的作用。实际上,对于每个文件,索引最多具有四个插槽,而不是只有一个插槽。这些称为“阶段号”,Git只会在每个文件最多三个阶段编号。合并使用阶段1、2和3,而正常操作仅使用阶段0;索引实际上仅存储文件哈希ID;文件数据(每个文件的实际内容)保存在Git的存储库中的对象。)

总而言之,索引就是您下一次提交的内容。使用git addgit rm文件更新索引,然后git commit将索引内容(所有跟踪文件的集合)转换为新提交。索引中的内容将成为该提交中的内容。进行新的提交会使当前分支扩展一个提交,因此分支名称指向您刚进行的新提交。

任何新的提交都不会更改现有的提交。实际上,Git不能通过设计更改任何对象(提交,树,文件或带注释的标签)。似乎更改了某些内容的命令(例如git commit --amendgit rebase)实际上是伪造的:它们进行新的提交,将旧的提交保留在原地,不受干扰,但是然后使用烟雾镜将舞台魔术师的诡计拉开好像新的取代了旧的。

.gitignore是做什么的? (有关未跟踪文件的更多信息)

我想说.gitignore是此文件的错误名称,因为它实际上并不是要忽略的文件列表,甚至不是全局模式。无视比其他任何事情都更具副作用。真正的问题是提交中包含什么内容,正如我们刚刚指出的,这取决于索引中的内容。换句话说,真正的问题是哪些文件被跟踪,哪些文件未被跟踪。

当您运行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


git status的作用(除其他事项外)是运行两个差异,一个差异从当前提交到索引(在这里它找到“要提交的更改”),另一个差异从索引到工作树。后者在此处找到“未暂存的更改”(例如pytest/client.py)和“未跟踪的文件”(例如pytest/README)。

我们已经注意到,未跟踪的文件是不在索引中的文件。因此pytest/README不在索引中(实际上不在)。

现在,还有一大堆*.o文件(来自C代码)和*.pyc文件(来自Python代码)。这些也不在索引中,但是git status没有抱怨它们。这是因为,在.gitignore文件中,以全局模式提到了它们。

git status抱怨未跟踪的文件之前,git status查看.gitignore文件中的信息。如果文件未跟踪,但也被标记为已忽略,则git status禁止投诉。因此,从这个意义上说,.gitignore中的文件是“不要抱怨”。

但是,同时,我可以执行git add .git add *将多个文件添加到索引中。如果文件已经存在,这将更新索引条目;否则,将添加新条目。但是,在git add实际将新文件添加到索引之前,它会查看从.gitignore文件获取的信息。如果文件未跟踪(尚未在索引中)并且被标记为已忽略,则git add不会添加它。但是,如果已经跟踪了文件,则git add永远不会沿着该特定代码路径运行,并且Git更新文件。

换句话说,对于已经跟踪的文件,.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。因此,Git将破坏文件的当前版本,将其替换为旧版本。如果文件不在database.sql中,则至少会收到警告-但它在.gitignore中,因此Git可以随意破坏数据库。

没有完美的解决方案。您可以将其保留为不被忽略,以使Git不会随意破坏它。但是,这将阻止您检出较早的提交。 (这可能是可以的,因为您可能不应该在实时服务器上执行此操作。)这还会使某人意外地重新添加数据库。 (这可能是可以的,因为人们可能不应该在实时服务器上进行Git工作。)而且,它将一直显示在.gitignore中。 (人们可能不应该在实时服务器上进行Git工作。这里有一个主题... :-))

但是,还有其他类似情况,例如,文件提交不当,并且与所有文件一样,提交文件并没有完美的解决方案。只需记住,当您git status确实包含文件的提交时,Git将尝试将其检出到工作树中,然后当您从该提交转到不包含该文件的提交时,Git将尝试执行以下操作:去掉它。

关于git - “git rm”命令的作用范围是什么,它对所有分支或HEAD分支都有效吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39709358/

相关文章:

linux - 如何修复 git 中大量文件的 merge 冲突?

git - 为什么git不 pull ?

Git 在单个文件的历史记录中搜索字符串

git - 如何在 git 配置别名内的 bash 片段内的命令替换内使用括号字符?

node.js - Docker NPM 安装时出现奇怪的 Git 错误

Git 功能分支依赖项

bash - 阻止 .git/index 更改其权限

安卓工作室 3.1 : Proxy configuration: Unable to set https user password for git operations

git - 当我使用 "git branch"时是否可以显示最新的提交?

git - 将免费源代码控制转换为 CM Synergy