[英]Undo git command - git checkout --
有一種方法可以撤消以下git命令:
git checkout -- .
我試圖刪除已添加到repo目錄中但未暫存或未提交的文件。 該命令似乎沒有執行此操作,而是更改了一些其他文件。
更新:
未跟蹤的文件和未暫存的文件之間有區別。 在這種情況下,我想找到一種丟棄未跟蹤和未暫存文件的方法。 當我運行git checkout -- .
,我以為它會刪除未跟蹤的文件,但據我所知,它只會刪除未暫存的文件。
git checkout -- path
從索引/暫存區到工作樹的git checkout -- path
副本 如果您命名的path
是目錄,則Git將從該目錄開始並包括所有子目錄,將其知道的所有文件(在索引/暫存區域中找到)復制到工作樹中。
但是,要利用此答案,您需要了解每個文件的三個活動副本。
請記住,在Git中,每個文件始終有多達三個版本處於活動狀態。 例如,假設您在存儲庫中已提交名為README.txt
和a.ext
文件。 有三個副本 README.txt
,以及三份 a.ext
在任何給定的時間,提供給您。 三份副本中的兩份采用特殊的僅Git格式。
如果我們使用git show
用來訪問僅Git格式文件的語法,則可以通過以下方式描述這三個副本:
HEAD index work-tree
--------------- ----------- ----------
HEAD:README.txt :README.txt README.txt
HEAD:a.ext :a.ext a.ext
如果現在創建一個新的未跟蹤文件b.dat
,則具有以下內容:
HEAD index work-tree
--------------- ----------- ----------
HEAD:README.txt :README.txt README.txt
HEAD:a.ext :a.ext a.ext
b.dat
在索引/暫存區域中尚無b.dat
副本。 即使在HEAD
和index中它們相同,其他兩個文件在邏輯上也有兩個副本。 (當它們相同時,Git會自動共享基礎副本,因此不需要額外的空間。)
工作樹中存儲的任何文件的任何副本都只是一個普通文件。 您可以使用計算機執行的任何操作。 Git不在乎您如何處理此類文件。 如果您詢問Git有什么不同,Git 會告訴您工作樹副本與索引副本不同。
git add path
副本從工作樹git add path
到暫存區 假設此時,您可以使用任意喜歡的編輯器來修改README.txt
,該編輯器將編輯工作樹副本(除非它非常了解Git,否則它根本無法使用或觸摸索引副本)。 現在,工作樹副本不同於索引副本。 索引副本采用特殊的僅Git格式,可以進行下一次提交。
現在,您將需要運行git add README.txt
,以將更新的工作樹文件復制到索引中。 完成此操作后,舊版本的README.txt
仍處於HEAD
提交中, 並且仍采用特殊的僅Git格式,但是現在HEAD:README.txt
與:README.txt
有所不同,而:README.txt
是與README.txt
相同。
HEAD
提交副本都是只讀的; 索引副本不是 任何提交中的任何內容都無法更改。 因此,您提交的README.txt
副本和您提交的a.ext
副本將永遠安全地保存在存儲庫中1 。 索引/暫存區中的副本可能與HEAD
提交上的副本相同或不同, 可以隨時覆蓋。 它開始時一樣的人在HEAD
犯,2,但git add
從工作樹副本, 到索引中。
1如果放棄或刪除提交(通常通過git reset
或git rebase -i
進行刪除),則可能導致Git丟失凍結副本:凍結副本僅持續到包含該副本的提交為止。 但是,大多數Git都是基於添加新提交而不刪除舊提交的想法構建的。
2如果當前分支上有未提交的更改而簽出另一個分支,則可以克服 “簽出或提交后HEAD和索引匹配”的正常情況。 這個答案沒有足夠的空間來詳細說明這些細節。
git commit
所有索引副本凍結到一個新提交中 git commit
所做的是以當時索引中具有的格式獲取當時索引中的每個文件,並將其凍結為只讀的提交副本。 此提交的文件集成為新的HEAD
提交。 一旦git commit
運行完畢並返回提示,便有了一個新的提交,並且HEAD
提交和索引匹配了-因為Git 從索引中進行了新的提交!
Git非常簡單地定義了一個未跟蹤的文件 :它是不在索引中的文件。 就這樣—就是所有的一切—但卻有很強的后果:如果b.dat
不在索引中,則git commit
不會將其放入新提交中。 而且, git checkout --
找不到 b.dat
,因為它不在索引中,所以它不能覆蓋工作樹副本。
請注意,僅僅是因為某些文件存在於存儲庫中的某些提交中,並不意味着就對該文件進行了跟蹤! 該文件被跟蹤,當且僅當該文件是在索引現在 。 如果您對確實包含該文件的提交運行git checkout
, 那么 -那時-Git將把文件從提交中復制到索引中,再復制到工作樹中。 當時的文件將被跟蹤。 如果再明確從索引中刪除文件, 在某一時刻的文件將不再被跟蹤。 因此,您必須始終牢記或測試索引中是否存在某些特定文件的副本,以了解是否已跟蹤該文件。
git checkout commit -- path
從提交到索引和工作樹的git checkout commit -- path
副本 在這里,使用git reset
,通過將多個不同的東西塞到一個命令中,Git變得過於復雜。 當您將git checkout
與路徑一起使用,但沒有提交或樹說明符時,Git從索引復制到工作樹。 當您使用git checkout
與兩條路徑和提交,或樹,Git會復制到索引和工作樹兩種 。
git reset -- path
從提交到索引的git reset -- path
復制,不考慮工作樹 git reset
這種特殊形式,與路徑一起使用,從提交復制到索引/登台區域。 請記住,索引已經包含所有跟蹤文件的副本,因此這只會用其他副本覆蓋這些副本。 默認情況下, git reset
用於獲取文件的提交是HEAD
提交-因此此副本從活動的HEAD
副本復制到索引中。
任何文件的工作樹副本都將保留。 該文件存在於HEAD
提交中的事實意味着該文件可能已被跟蹤:取消跟蹤該文件的唯一方法是簽出該提交,然后顯式刪除了索引副本。 在這種情況下, git reset -- path
將文件放回到索引中,以便再次對其進行跟蹤。
但是請注意,您可以使用git reset commit -- path
從某些特定的提交復制文件。 如果該文件不在 HEAD
提交中,則在進行git reset
操作之前,該文件可能會被取消跟蹤(不在索引中),但之后會被跟蹤(在索引中)。 這完全取決於您已經對索引進行了哪些更改。
運行git status
兩個比較:
第一個比較是HEAD
vs索引。 無論有什么不同,這里都會進行提交 。
HEAD
中的文件也可能在索引中(因此將跟蹤所有這些文件)。 如果索引中的副本與HEAD
的副本不同,則Git調用准備提交的副本。 如果在索引中的副本是一樣什么在HEAD
,文件本身仍然是跟蹤和上演,這只是git status
不會刻意去提它。
這里的關鍵思想是,即使每個提交都是所有文件的完整快照,我們對一個提交的了解也往往是:與以前的提交相比,此提交有何不同? 因此, git status
告訴我們,如果我們采用當前暫存區域(建議的新提交),然后將其實際轉換為新提交,會有什么不同。
第二個比較是索引與工作樹。 無論有什么不同,這里都不會提交 。
跟蹤索引中的文件。 對於那些與工作樹中的內容相匹配的內容, git status
只是不用理會它們。 對於那些不同的內容, git status
提及它們,而不是提交 。 對於不在該指數在所有,但都是在工作樹中的文件,Git的抱怨道關於他們是未經跟蹤 。
再一次,這里的總體思路是,我們關心與之前的提交相比,每次提交實際上有什么不同。 如果我們已取消暫存或什至未跟蹤的文件與暫存副本不同(或缺少暫存副本),則可以使用git add
將它們復制到暫存區域。 如果我們有一個與暫存的a.ext
與HEAD:a.ext
完全相同的工作樹a.ext
,我們可能根本不在乎,所以我們根本就不會看到它。
要關閉Git絕對不應該提交的未跟蹤文件,可以在.gitignore
指令中列出那些未跟蹤的文件(按名稱或glob模式,例如*.o
或*.pyc
)。 這樣可以防止Git自動在en-masse git add .
或git add --all
,並保持git status
不變。 但是請注意,如果某個文件已經在索引中(無論它已經到達那里了),則在.gitignore
列出該文件的名稱或模式將無效 。
復制文件的主要操作是:
git add path
:從工作樹復制到索引 git checkout -- path
:從索引復制到工作樹 git checkout commit -- path
:從commit
復制到索引和工作樹 git reset [ commit ] -- path
:從commit
(默認HEAD
)復制到索引 刪除文件的主要操作是:
git add path
:如果path
在索引中但是從工作樹中丟失,則從索引中刪除 git rm --cached path
:從索引中刪除,但不從工作樹中刪除 git rm path
:從索引和工作樹中刪除 git reset [ commit ] -- path
:如果未在commit
包含path
,則從索引中刪除(默認HEAD
) 除了這些,還有一些你可以觸發特殊情況下git commit --only paths
或git commit --include paths
,但這些基本上等同於做git add
對這些通路第一。 始終牢記索引,並注意git status
總結了索引的差異 ,而不是列出索引的內容,因此,如果您有30,000個大型文件項目,則只會看到很少的有趣文件,而不會看到所有30,000個文件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.