version-control git取消add - 如何在提交前撤消'git add'?




revert用法 git取消commit (25)

git reset filename.txt  

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

我使用命令錯誤地將文件添加到git:

git add myfile.txt

我還沒有運行git commit 。 有沒有辦法撤消這個,所以這些文件不會包含在提交中?

到目前為止有48個答案(有些已刪除)。 除非您有一些新信息,否則請不要添加新的。


此命令將取消暫停您的更改:

git reset HEAD filename.txt

你也可以使用

git add -p 

添加部分文件。


git reset filename.txt

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


使用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)
$

對於已接受的答案的補充,如果您錯誤添加的文件很大,您可能會注意到,即使在使用' 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 會將其 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 lost irrevocably "version 2"
-version 1
+version 3

當然,如果我們只是按照通常的懶惰工作流程來執行'git add'僅用於添加新文件(案例1),並且我們通過commit, git commit -a命令更新新內容,這不是非常關鍵。

*(編輯:以上幾乎是正確的,但仍然可能有一些稍微ha / /的複雜方式來恢復已上演但未提交然後被覆蓋的更改 - 請參閱Johannes Matokic和iolsmit的評論)


git add myfile.txt #這將把你的文件添加到提交列表中

與此命令完全相反的是,

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

所以,你將處於以前的狀態。指定將再次處於未跟踪列表(先前狀態)。

它將使用指定的文件重置您的頭部。所以,如果你的頭沒有它的意思,它只會重置它


使用git 撤消已添加的文件非常簡單,重置已添加的myfile.txt ,使用:

git reset HEAD myfile.txt

說明:

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

我將在下面的圖片中為您創建更多詳細信息,包括在這些情況下可能發生的所有步驟:


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

假設我意外添加了文件, git add newFile.txt

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


只需鍵入git reset它就會恢復,就像你從未輸入git add . 自上次提交以來。 確保你之前已經承諾。


你要:

git rm --cached <added_file_to_undo>

推理:

當我剛接觸這個時,我首先嘗試過

git reset .

(撤消我的整個初始添加),只是為了得到這個(不那麼)有用的消息:

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

事實證明,這是因為HEAD ref(branch?)直到第一次提交後才存在。 也就是說,如果你的工作流程像我一樣,你會遇到和我一樣的初學者問題:

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

    ......很多廢話捲軸......

    =>該死,我不想加上所有這些。

  5. 谷歌“撤消git添加”

    =>查找 - yay

  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沒有破壞任何東西(如果我拼錯它會怎麼樣)。


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

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

等等


為了澄清: git add將更改從當前工作目錄移動到暫存區域 (索引)。

此過程稱為分段 。 因此,最自然的命令來進行更改(更改文件)是顯而易見的:

git stage

git add更容易為git stage輸入別名

可惜沒有git unadd也沒有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

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

git rm --cached FILE

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


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

git reset *

在SourceTree中,您可以通過gui輕鬆完成此操作。您可以檢查sourcetree使用哪個命令來取消暫存文件。

我創建了一個新文件並將其添加到git中。然後我使用SourceTree gui取消了它。這是結果:

Unstaging文件[08/12/15 10:43]
git -c diff.mnemonicprefix = false -c core.quotepath = false -c credential.helper = sourcetree reset -q - path / to / file / filename.java

SourceTree用於取消暫存reset新文件。


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

但:

我發現這個偉大的小帖子實際上為git unadd添加了Git命令(以及別名):有關詳細信息,請參閱git unadd或..

只是,

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

現在你可以

git unadd foo.txt bar.txt

git gui

並手動刪除所有文件或選擇所有文件並單擊“ 提交”按鈕。


如果您輸入:

git status

git會告訴你什麼是上演的,包括如何取消演出的說明:

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

我發現git在推動我在這樣的情況下做正確的事情方面做得非常好。

注意:最近的git版本(1.8.4.x)已更改此消息:

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

git rm --cached . -r

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


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

git help rm

我很驚訝沒有人提到交互模式:

git add -i

選擇選項3以取消添加文件。在我的情況下,我經常想要添加多個文件,使用交互模式,您可以使用這樣的數字來添加文件。這將採取除4:1,2,3,5之外的所有

要選擇一個序列,只需輸入1-5即可從1到5。

Git臨時文件


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


對於特定文件:

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

對於所有添加的文件:

  • git重置。
  • git checkout。

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


問題沒有明確提出。 原因是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

git pull和之間有什麼區別git fetch

要理解這一點,首先需要了解本地git不僅維護本地存儲庫,還維護遠程存儲庫的本地副本。

git fetch使您的遠程存儲庫的本地副本保持最新。例如,如果您的遠程存儲庫是GitHub - 您可能希望將遠程存儲庫中所做的任何更改提取到遠程存儲庫的本地副本。這將允許您執行比較或合併等操作。

git pull另一方面,將遠程存儲庫中的更改記錄到您保留自己的代碼的位置。通常,git pullgit fetch首先使遠程存儲庫的本地副本更新,然後將更改合併到您自己的代碼存儲庫以及可能的工作副本中。







git version-control git-commit git-stage