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 dev
或git checkout feature
或git checkout master
,则Git可以通过比较该提交的提交来切换到该分支上的提交。文件到当前索引中的文件。它只需要更改不同的文件-或者,当然,删除当前提交中但不在待签出提交中的文件,或者添加不在当前提交中但属于当前提交的新文件。在要签出的提交中。因此,索引不仅加快了git commit
的速度,还加快了git checkout
的速度。
1由于core.eol
设置以及Git所谓的污迹过滤器之类的事情使事情变得复杂,因此我们忽略它们。 :-)
(当然,索引在合并中具有特殊的作用。实际上,对于每个文件,索引最多具有四个插槽,而不是只有一个插槽。这些称为“阶段号”,Git只会在每个文件最多三个阶段编号。合并使用阶段1、2和3,而正常操作仅使用阶段0;索引实际上仅存储文件哈希ID;文件数据(每个文件的实际内容)保存在Git的存储库中的对象。)
总而言之,索引就是您下一次提交的内容。使用git add
和git rm
文件更新索引,然后git commit
将索引内容(所有跟踪文件的集合)转换为新提交。索引中的内容将成为该提交中的内容。进行新的提交会使当前分支扩展一个提交,因此分支名称指向您刚进行的新提交。
任何新的提交都不会更改现有的提交。实际上,Git不能通过设计更改任何对象(提交,树,文件或带注释的标签)。似乎更改了某些内容的命令(例如git commit --amend
或git 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/