簡體   English   中英

“git rm --cached”、“git restore --staged”和“git reset”有什么區別

[英]What's the difference between 'git rm --cached', 'git restore --staged', and 'git reset'

為了取消暫存由命令“git add”暫存的文件,我遇到了以下三種方法

git rm --cached <file>
git restore --staged <file>
git reset <file>

當我一一運行這些命令時,它們的行為看起來完全一樣。 它們之間究竟有什么區別?

兩個是一樣的; 一個不是,除非在特殊情況下。

要理解這一點,請記住:

  • 提交包含 Git 知道的所有文件的快照,就像你說提交它們時它們的形式一樣;
  • 快照是Git 索引中的文件制作的,即暫存區域,也稱為緩存(同一事物的三個術語);
  • git add意味着使索引/暫存區域/緩存中的副本與我的工作樹中的副本匹配(如果工作樹副本更新,則從工作樹中復制,或者如果工作樹副本被刪除,則從索引中刪除)。

因此,索引/暫存區域始終包含您建議的下一次提交,並且最初是在您執行git checkoutgit switch以獲取該提交時從當前提交中播種的。 1因此,您的工作樹包含每個文件的第三個副本2 ,前兩個副本是當前提交中的副本,即HEAD副本,以及索引中的副本。

考慮到這一點,以下是您的每個命令的作用:

  • git rm --cached file :從索引/暫存區域中刪除文件的副本,而不涉及工作樹副本。 提議的下一次提交現在缺少該文件。 如果當前提交該文件,而實際上此時您確實進行了下一次提交,則上一次提交與新提交之間的區別在於該文件已消失。

  • git restore --staged file : Git 將文件從HEAD提交復制到索引中,而不觸及工作樹副本。 索引副本和HEAD副本現在匹配,無論它們之前是否匹配。 現在進行的新提交將具有與當前提交相同的文件副本。

    如果當前提交缺少該文件,這具有從索引中刪除該文件的效果。 所以在這種情況下,它與git rm --cached做同樣的事情。

  • git reset file :這會將文件的HEAD版本復制到索引,就像git restore --staged file一樣。

(請注意, git restore與這種特殊形式的git reset不同,如果您要求它這樣做,它可以覆蓋某些文件的工作樹副本。 --staged選項,沒有--worktree選項,指示它只寫到索引。)

旁注:很多人最初認為 index/staging-area 只包含更改,或者只包含更改的文件。 事實並非如此,但如果您這樣想, git rm --cached似乎與其他兩個相同。 由於這不是索引的工作方式,因此不是。


1有一些奇怪的邊緣情況,當你進行一些事情時,然后做一個新的git checkout 本質上,如果可以保留不同的分階段副本,Git 會這樣做。 有關血淋淋的詳細信息,請參見Checkout another branch when there are uncommitted changes on the current branch

2提交的副本和任何暫存的副本實際上都以內部 Git blob object的形式保存,它會刪除重復的內容。 因此,如果這兩個匹配,它們實際上只是共享一個底層副本。 如果暫存副本與HEAD副本不同,但匹配任何(甚至許多)其他現有已提交副本或副本,則暫存副本與所有其他提交共享底層存儲。 所以稱每個人為“副本”是矯枉過正的。 但作為一個精神 model,它工作得很好:沒有一個可以被覆蓋; 如果需要,一個新的git add將創建一個新的 blob object,如果沒有人使用一些 blob object 最后,Z0BCC731105ADF277B66B 最終丟棄它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM