如何在提交前撤消'git add'?

How do I undo 'git add' before commit?
投票:8511回答:33

我錯誤地使用以下命令將文件添加到了Git:

git add myfile.txt

我還沒有運行git commit 有一種方法可以撤消此操作,以便這些文件不會包含在提交中?

tags:git,version-control,git-commit,git-stage
33回答
44
投票

使用git add -i從即將到來的提交中刪除剛添加的文件。 例:

添加您不想要的文件:

$ git add foo
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   foo
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
# [...]#

進入交互式添加以撤消添加(在git此處鍵入的命令為“ r”(還原),“ 1”(列表還原中的第一項顯示),“返回”以退出還原模式和“ q” (放棄):

$ git add -i
           staged     unstaged path
  1:        +1/-0      nothing foo

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> r
           staged     unstaged path
  1:        +1/-0      nothing [f]oo
Revert>> 1
           staged     unstaged path
* 1:        +1/-0      nothing [f]oo
Revert>> 
note: foo is untracked now.
reverted one path

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> q
Bye.
$

而已! 這是您的證明,表明“ foo”又回到了未跟踪列表中:

$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
# [...]
#       foo
nothing added to commit but untracked files present (use "git add" to track)
$

31
投票

如上所述,要從登台區域中刪除新文件(並且僅在新文件的情況下):

git rm --cached FILE

rm --cached僅用於意外添加的新文件。


25
投票

要重置特定文件夾(及其子文件夾)中的每個文件,可以使用以下命令:

git reset *

14
投票

此命令將取消存儲您的更改:

git reset HEAD filename.txt

您也可以使用

git add -p 

添加文件的一部分。


82
投票

Git有可以想像到的每個動作的命令,但是它需要廣泛的知識來使事情正確,因此,它充其量是違反直覺的。

您之前做了什麼:

  • 更改文件並使用git add . git add <file>

你想要什麼:

  • 從索引中刪除文件,但保持版本不變,並保留工作副本中未提交的更改:

     git reset head <file> 
  • 將文件重置為HEAD的最後一個狀態,撤消更改並將其從索引中刪除:

     # Think `svn revert <file>` IIRC. git reset HEAD <file> git checkout <file> # If you have a `<branch>` named like `<file>`, use: git checkout -- <file> 

    這是必需的,因為git reset --hard HEAD不適用於單個文件。

  • 從索引和版本控制中刪除<file> ,保留未版本化的文件以及工作副本中的更改:

     git rm --cached <file> 
  • 從工作副本和版本中完全刪除<file>

     git rm <file> 

34
投票

自您發布問題以來,Git也許已經發展了。

$> git --version
git version 1.6.2.1

現在,您可以嘗試:

git reset HEAD .

這應該是您想要的。


64
投票

如果您正在執行初始提交,並且不能使用git reset ,則只需聲明“ Git破產”並刪除.git文件夾並重新開始


25
投票

使用*命令一次處理多個文件:

git reset HEAD *.prj
git reset HEAD *.bmp
git reset HEAD *gdb*

等等


92
投票
git rm --cached . -r

將遞歸“取消添加”從當前目錄添加的所有內容


75
投票

這個問題沒有明確提出。 原因是git add具有兩個含義:

  1. 將一個新文件添加到暫存區,然後使用git rm --cached file撤消。
  2. 將一個修改過的文件添加到暫存區域,然後使用git reset HEAD file撤消。

如有疑問,請使用

git reset HEAD file

因為在兩種情況下都可以完成預期的操作。

警告:如果對修改過的文件(倉庫中以前存在的文件)執行git rm --cached file ,則該文件將在git commit刪除! 它仍將存在於您的文件系統中,但是如果其他人拉您的提交,該文件將從他們的工作樹中刪除。

git status會告訴您該文件是新文件還是已修改的 文件

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   my_new_file.txt
    modified:   my_modified_file.txt

23
投票

只需輸入git reset它就會還原,就像您從未輸入git add . 自上次提交以來。 確保您之前已作出承諾。


14
投票

還有交互模式:

git add -i

選擇選項3取消添加文件。 就我而言,我經常想添加多個文件,並且在交互模式下,您可以使用像這樣的數字來添加文件。 除了4:1、2、3和5外,這將佔用所有其他內容

要選擇一個序列,只需輸入1-5即可將1取為5。

Git暫存文件


9
投票

在Sourcetree中,您可以通過GUI輕鬆完成此操作。 您可以檢查Sourcetree用於取消暫存文件的命令。

我創建了一個新文件並將其添加到Git。 然後,我使用Sourcetree GUI取消登台。 結果如下:

取消暫存文件[08/12/15 10:43] git -c diff.mnemonicprefix = false -c core.quotepath = false -c credential.helper = sourcetree reset -q-路徑/到/文件/文件名.java

Sourcetree使用reset取消登台新文件。


43
投票

可以使用git removegit rm ,帶有--cached標誌。 嘗試:

git help rm

9686
投票

您可以在提交之前撤消git add

git reset <file>

這會將其從當前索引(“即將提交”列表)中刪除,而無需進行其他任何更改。

您可以使用

git reset

沒有任何文件名可以取消所有應有的更改。 當在合理的時間內有太多文件不能一一列出時,這可能會派上用場。

在舊版本的Git中,上述命令分別等效於git reset HEAD <file>git reset HEAD ,並且如果HEAD未定義(因為尚未在存儲庫中進行任何提交)或模棱兩可(因為創建了一個名為HEAD的分支,這是愚蠢的事情,您不應該這樣做)。 但是, 在Git 1.8.2中對此進行了更改 ,因此在現代版本的Git中,甚至可以在進行首次提交之前使用上述命令:

當您的歷史記錄中沒有任何提交時,“ git reset”(無選項或參數)會出錯,但是現在它為您提供了一個空索引(以匹配您甚至沒有提交的不存在的提交)。


520
投票

如果輸入:

git status

Git會告訴您已登台的內容等,包括有關如何取消登台的說明:

use "git reset HEAD <file>..." to unstage

我發現Git在這種情況下勉強我做正確的事情做得很好。

注意:最新的Git版本(1.8.4.x)更改了此消息:

(use "git rm --cached <file>..." to unstage)

242
投票

需要說明的是: git add將更改從當前工作目錄移動到暫存區 (索引)。

此過程稱為暫存 所以最自然的命令階段的變化(變更的文件)是明顯的:

git stage

git add只是git stage易於使用的別名

可惜的是沒有git unstage也不git unadd命令。 相關的難以猜測或記住,但很明顯:

git reset HEAD --

我們可以輕鬆為此創建一個別名:

git config --global alias.unadd 'reset HEAD --'
git config --global alias.unstage 'reset HEAD --'

最後,我們有了新命令:

git add file1
git stage file2
git unadd file2
git unstage file1

我個人使用更短的別名:

git a # For staging
git u # For unstaging

10
投票
git reset filename.txt

將從當前索引“即將提交”區域中刪除一個名為filename.txt的文件,而不進行其他任何更改。


57
投票

根據許多其他答案,您可以使用git reset

但:

我發現了這篇很棒的小文章,實際上為git unadd添加了Git命令(還有一個別名):有關詳細信息,請參見git unadd

只是,

git config --global alias.unadd "reset HEAD"

現在你可以

git unadd foo.txt bar.txt

14
投票

要撤消git add ,請使用:

git reset filename

19
投票

假設我創建一個新文件newFile.txt

在此處輸入圖片說明

假設我不小心添加了文件, git add newFile.txt

在此處輸入圖片說明

現在我想在提交之前撤消此添加, git reset newFile.txt

在此處輸入圖片說明


7
投票

最直觀的解決方案之一是使用SourceTree

您可以從暫存和未暫存中拖放文件 在此處輸入圖片說明


10
投票

git add myfile.txt #這會將您的文件添加到待提交列表中

與該命令完全相反的是,

git reset HEAD myfile.txt  # This will undo it.

因此,您將處於以前的狀態。 指定將再次出現在未跟踪列表中(以前的狀態)。

它將使用該指定文件重置您的頭部。 因此,如果您的頭沒有它的意思,它將簡單地將其重置。


98
投票

使用Git 撤消已經添加的文件非常容易。 要重置已添加的myfile.txt ,請使用:

git reset HEAD myfile.txt

說明:

暫存不需要的文件後,要撤消,可以執行git reset Head是本地文件的頭,最後一個參數是文件名。

我已為您在下圖中創建了更詳細的步驟,包括在這些情況下可能發生的所有步驟:

git reset HEAD文件


8
投票
git reset filename.txt  

將從當前索引“即將提交”區域中刪除一個名為filename.txt的文件,而不進行其他任何更改。


19
投票

對於特定文件:

  • git reset my_file.txt
  • git checkout my_file.txt

對於所有添加的文件:

  • git reset。
  • git checkout。

注意: 檢出會更改文件中的代碼,並移至上次更新(提交)狀態。 重置不會更改代碼; 它只是重置標題。


164
投票

除了已接受的答案之外,如果您錯誤添加的文件很大,您可能會注意到,即使使用' git reset '將其從索引中刪除後,它似乎仍然佔據.git目錄中的空間。

這沒什麼好擔心的。 該文件確實仍在存儲庫中,但僅作為“鬆散對象”。 不會將其複製到其他存儲庫(通過克隆,推送),最終將回收該空間-儘管可能不會很快。 如果您著急,可以運行:

git gc --prune=now

更新 (以下是我的嘗試,以消除因最不滿意的答案而引起的一些混亂):

那麼,哪個是git add的真正撤消

git reset HEAD <file>

要么

git rm --cached <file>

嚴格來說,如果我沒記錯的話: 沒有

git add 無法撤消 -通常來說安全的。

讓我們首先回顧一下git add <file>實際作用:

  1. 如果<file> 先前未被跟踪 ,則git add 會將其及其當前內容添加到緩存中

  2. 如果<file> 已經跟踪git add 會將當前內容 (快照,版本)保存到緩存中。 在Git中,此操作仍稱為add ,(不僅僅是更新它),因為文件的兩個不同版本(快照)被視為兩個不同的項目:因此,我們確實在向緩存中添加了一個新項目,最終以後提交。

鑑於此,這個問題有點模棱兩可:

我錯誤地使用命令添加了文件...

OP的場景似乎是第一個(未跟踪的文件),我們希望“撤消”從跟踪的項目中刪除文件(而不僅僅是當前內容)。 如果是這種情況,那麼可以運行git rm --cached <file>

我們也可以運行git reset HEAD <file> 通常,這是可取的,因為它在兩種情況下都可以工作:當我們錯誤地添加已跟踪項目的版本時,它也可以撤消操作。

但是有兩個警告。

第一:(在答案中指出)只有一種情況,其中git reset HEAD不起作用,但是git rm --cached起作用:新的存儲庫(無提交)。 但是,實際上,這實際上是無關緊要的情況。

其次:請注意git reset HEAD無法神奇地恢復以前緩存的文件內容,它只是從HEAD重新同步它。 如果我們誤導的git add覆蓋了先前暫存的未提交版本,我們將無法恢復它。 因此,嚴格來說,我們不能撤消[*]。

例:

$ git init
$ echo "version 1" > file.txt
$ git add file.txt   # First add of file.txt
$ git commit -m 'first commit'
$ echo "version 2" > file.txt
$ git add  file.txt   # Stage (don't commit) "version 2" of file.txt
$ git diff --cached file.txt
-version 1
+version 2
$ echo "version 3" > file.txt
$ git diff  file.txt
-version 2
+version 3
$ git add  file.txt    # Oops we didn't mean this
$ git reset HEAD file.txt  # Undo?
$ git diff --cached file.txt  # No dif, of course. stage == HEAD
$ git diff file.txt   # We have irrevocably lost "version 2"
-version 1
+version 3

當然,如果我們僅遵循通常的懶惰工作流程(僅用於添加新文件)進行“ git add”(案例1),然後通過commit git commit -a命令更新新內容,這並不是很關鍵。


*(編輯:以上內容實際上是正確的,但仍可能有一些稍微有些混亂/令人費解的方法來恢復已上演但未提交但隨後被覆蓋的更改-請參閱Johannes Matokic和iolsmit的評論)


2102
投票

你要:

git rm --cached <added_file_to_undo>

推理:

當我是新手時,我首先嘗試

git reset .

(撤消我的整個初始添加),只是得到了此信息(不是這樣),有幫助:

fatal: Failed to resolve 'HEAD' as a valid ref.

事實證明,這是因為HEAD ref(分支?)在第一次提交之後才存在。 也就是說,如果您的工作流程(例如我的)類似於以下內容,您將遇到與我相同的初學者問題:

  1. cd到我偉大的新項目目錄中,嘗試Git,新熱點
  2. git init
  3. git add .
  4. git status

    ...很多廢話

    =>該死,我不想添加所有這些內容。

  5. 谷歌“撤消git添加”

    =>查找堆棧溢出-是

  6. git reset .

    =>致命:無法將“ HEAD”解析為有效的引用。

事實證明,在郵件列表中有一個針對此問題的日誌記錄一個錯誤

而且正確的解決方案就在Git狀態輸出中(是的,我掩飾為“廢話”)

 ... # Changes to be committed: # (use "git rm --cached <file>..." to unstage) ... 

解決方案的確是使用git rm --cached FILE

請注意此處其他地方的警告git rm刪除文件的本地工作副本,但如果使用--cached則 不會刪除。 這是git help rm的結果:

--cached使用此選項可取消登台並僅從索引中刪除路徑。 無論是否修改,都會保留工作樹文件。

我繼續使用

git rm --cached .

刪除所有內容,然後重新開始。 不過沒有用,因為在add . 是遞歸的,結果表明rm需要-r來遞歸。 嘆。

git rm -r --cached .

好的,現在我回到了起點。 下次,我將使用-n進行空運行並查看將添加的內容:

git add -n .

在信任git help rm關於--cached不會破壞任何內容(以及我拼錯的內容該怎麼辦)之前,我將所有內容壓縮到一個安全的地方。


38
投票

當您開始一個新項目時,這是一種避免此煩惱的方法:

  • 為新項目創建主目錄。
  • 運行git init
  • 現在創建一個.gitignore文件(即使它為空)。
  • 提交您的.gitignore文件。

如果您沒有任何提交,Git使得執行git reset真的很困難。 如果您只是為了擁有一個而創建一個微小的初始提交,那麼您可以根據需要進行git add -Agit reset多次,以使所有操作正確。

此方法的另一個優點是,如果以後遇到行尾麻煩並且需要刷新所有文件,則很容易:

  • 簽出該初始提交。 這將刪除您的所有文件。
  • 然後再次檢查您最近的提交。 這將使用您當前的行尾設置來檢索文件的新副本。

87
投票

git gui

並手動刪除所有文件,或者選擇所有文件並單擊從提交中取消登台按鈕。


34
投票

請注意,如果您未能指定修訂版本,則必須包含分隔符。 我的控制台示例:

git reset <path_to_file>
fatal: ambiguous argument '<path_to_file>': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

git reset -- <path_to_file>
Unstaged changes after reset:
M    <path_to_file>

(Git版本1.7.5.4)


©2020 sofbug.com - All rights reserved.