Proč jsou v systému Git dva způsoby, jak zrušit etapu souboru?

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
#
Řešení

`git rm --cached

Komentáře (13)

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 :)

Komentáře (3)

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 ..." 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 ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#   modified:   to-be-modified
#   deleted:    to-be-removed
#
# Untracked files:
#   (use "git add ..." 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 ..." to unstage)

... což funguje pro všechny tři typy změn

Komentáře (1)