Někdy git navrhuje git rm --cached
k odstranění souboru z archivu, jindy git reset HEAD file
. Kdy mám použít který z nich?
EDIT:
D:\code\gt2>git init
Initialized empty Git repository in D:/code/gt2/.git/
D:\code\gt2>touch a
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# a
nothing added to commit but untracked files present (use "git add" to track)
D:\code\gt2>git add a
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: a
#
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a
D:\code\gt2>touch b
D:\code\gt2>git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# b
nothing added to commit but untracked files present (use "git add" to track)
D:\code\gt2>git add b
D:\code\gt2>git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: b
#
git rm --cached <filepath>
neodstraní soubor, ale odstraní soubor(y) z repozitáře (za předpokladu, že již byl předtím odevzdán), ale ponechá soubor v pracovním stromu (a vám zůstane nesledovaný soubor).
git reset -- <filepath>
odstraní všechny nastřádané změny pro daný soubor (soubory).
To znamená, že pokud byste použili git rm --cached
na nový soubor, který je ve fázi staged, v podstatě by to vypadalo, že jste ho právě odfajfkovali, protože nikdy předtím nebyl odevzdán.
git rm --cached
slouží k odstranění souboru z indexu. V případě, že je soubor již v repozitáři, git rm --cached
odstraní soubor z indexu a ponechá jej v pracovním adresáři a odevzdání jej nyní odstraní i z repozitáře. V podstatě byste po odevzdání souboru zrušili jeho verzi a ponechali si jeho místní kopii.
Příkaz git reset HEAD file
( který ve výchozím nastavení používá příznak --mixed
) se liší v tom, že v případě, kdy je soubor již v repozitáři, nahradí indexovou verzi souboru verzí z repozitáře (HEAD), čímž fakticky zruší jeho modifikace.
V případě souboru bez verze se provede unstage celého souboru, protože soubor v HEAD nebyl. V tomto ohledu jsou git reset HEAD file
a git rm --cached
stejné, ale nejsou stejné ( jak bylo vysvětleno v případě souborů, které již v repozitáři jsou).
K otázce Proč jsou v gitu dva způsoby, jak zrušit uložení souboru?
- v gitu nikdy neexistuje jen jeden způsob, jak něco udělat. v tom je jeho krása :)
Toto vlákno je trochu staré, ale přesto chci přidat malou ukázku, protože to stále není intuitivní problém:
me$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: to-be-added
# modified: to-be-modified
# deleted: to-be-removed
#
me$ git reset -q HEAD to-be-added
# ok
me$ git reset -q HEAD to-be-modified
# ok
me$ git reset -q HEAD to-be-removed
# ok
# or alternatively:
me$ git reset -q HEAD to-be-added to-be-removed to-be-modified
# ok
me$ git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: to-be-modified
# deleted: to-be-removed
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# to-be-added
no changes added to commit (use "git add" and/or "git commit -a")
git reset HEAD
(bez -q
) vydá varování o změněném souboru a jeho exit kód je 1, což bude ve skriptu považováno za chybu.
Edit: git checkout HEAD to-be-modified to-be-removed
funguje i pro unstaging, ale odstraní změnu kompletně z pracovního prostoru.
Aktualizace git 2.23.0: Příkazy se čas od času mění. Nyní git status
říká:
(use "git restore --staged <file>..." to unstage)
... což funguje pro všechny tři typy změn