„Git rm --cached x” czy „git reset head - x”?

163

GitRef.org - Podstawowy :

git rmusunie wpisy z obszaru przemieszczania. To jest trochę inne niż w git reset HEADprzypadku plików "unstages". Mówiąc „unstage”, mam na myśli, że przywraca strefę inscenizacji do tego, co było, zanim zaczęliśmy modyfikować rzeczy. git rmz drugiej strony po prostu wyrzuca plik ze sceny, tak że nie jest on uwzględniany w następnej migawce zatwierdzenia, tym samym skutecznie go usuwając.

Domyślnie a git rm filecałkowicie usunie plik z obszaru przemieszczania, a także z twojego dysku> (katalog roboczy). Aby pozostawić plik w katalogu roboczym, możesz użyć git rm --cached.

Ale jaka dokładnie jest różnica między git rm --cached asdi git reset head -- asd?

Pacerier
źródło

Odpowiedzi:

219

Istnieją trzy miejsca, w których może znajdować się plik - powiedzmy, drzewo, indeks i kopia robocza. Kiedy dodajesz plik do folderu, dodajesz go do kopii roboczej.

Kiedy robisz coś takiego git add file, dodajesz to do indeksu. A kiedy to zatwierdzasz, dodajesz to również do drzewa.

Prawdopodobnie pomoże ci to poznać trzy bardziej powszechne flagi w resetowaniu git:

reset git [- <mode>] [ <commit>]

Ten formularz resetuje nagłówek bieżącej gałęzi do <commit>i prawdopodobnie aktualizuje indeks (resetując go do drzewa <commit>) i drzewo robocze w zależności od tego <mode>, które musi być jednym z następujących:
--soft

W ogóle nie dotyka pliku indeksu ani drzewa roboczego (ale resetuje głowicę do <commit>, tak jak robią to wszystkie tryby). To pozostawia wszystkie zmienione pliki jako „Zmiany do zatwierdzenia”, jak określiłby to status git.

--mieszany

Resetuje indeks, ale nie drzewo robocze (tj. Zmienione pliki są zachowane, ale nie są oznaczone do zatwierdzenia) i informuje, co nie zostało zaktualizowane. To jest akcja domyślna.

--ciężko

Resetuje indeks i drzewo robocze. Wszelkie zmiany w śledzonych plikach w drzewie roboczym <commit>są odrzucane.

Teraz, gdy zrobisz coś takiego git reset HEAD- to, co faktycznie robisz, git reset HEAD --mixedto „zresetuje” indeks do stanu, w jakim był przed rozpoczęciem dodawania plików / dodawania modyfikacji do indeksu (przez git add). W tym przypadku kopia robocza i plik index (lub staging) były zsynchronizowane, ale HEAD i indeks zostały zsynchronizowane po zresetowaniu.

git rmz drugiej strony usuwa plik z katalogu roboczego i indeksu, a po zatwierdzeniu plik jest również usuwany z drzewa. git rm --cachedjednak usuwa plik z samego indeksu i zachowuje go w kopii roboczej. Jest to dokładne przeciwieństwo git add file W tym przypadku, utworzyłeś indeks różniący się od HEAD i działającego, w którym HEAD ma wcześniej zatwierdzoną wersję pliku, kopia robocza miała ostatnią modyfikację, jeśli w ogóle, lub zawartość z HEAD plik i usunąłeś plik z indeksu. Zatwierdzenie teraz zsynchronizuje indeks i drzewo, a plik zostanie usunięty.

manojlds
źródło
Zauważyłem, że po polecenie nie wykazują żadnych diff, ale pokazuje diff, jakby wciąż jest buforowane. Jednak pokazuje plik jako . Wydaje się to niespójne. git rm --cachedgit diffgit diff --cachedgit statusUntracked
haridsv
7
Nieważne ... Powinienem był użyć git reset --mixed. Byłem trochę zdezorientowany stwierdzeniem, które git rm --cachedjest przeciwieństwem git add. Dosłownie jest to nieprawidłowe i może spowodować szkody. W moim przypadku git adddodawałem zmodyfikowany plik do obszaru przemieszczania i chciałem mieć przeciwieństwo „tego dodania”, a nie początkowego dodania pliku. + Odpowiedź Grega Hewgilla pomogła mi uzyskać jaśniejszy obraz.
haridsv
12
Uważam, że użycie kopii roboczej, drzewa i drzewa roboczego jest trochę zagmatwane. Czy drzewo robocze jest kopią roboczą czy drzewem?
Nealv
3
Jak wspomniał @haridsv, powiedzenie git rm --cached„jest dokładnym przeciwieństwem git add file” jest mylące. git reset filejest bliżej bycia przeciwieństwem git add file.
Matt Browne,
@Nealv spóźniony, ale dla innych, którzy znajdą ten wątek: kopia robocza, drzewo i drzewo robocze odnoszą się do tego samego (w kontekście git).
De Novo
83

Może przykład pomoże:

git rm --cached asd
git commit -m "the file asd is gone from the repository"

przeciw

git reset HEAD -- asd
git commit -m "the file asd remains in the repository"

Zauważ, że jeśli nie zmieniłeś niczego innego , drugie zatwierdzenie tak naprawdę nic nie da.

Greg Hewgill
źródło
3
Czy możesz mi powiedzieć, co właściwie oznacza ten podwójny łącznik - po HEAD?
yuva
30
@yuva: --służy do oddzielania opcji poleceń od nazw plików. Gdyby istniała zarówno gałąź, jak i plik o nazwie asd, git reset HEAD asdbyłoby to niejednoznaczne. --Mówi „wszystko po to nazwa pliku”.
Greg Hewgill
Czy git reset HEAD <file>dokładnie to samo co git rm --cached <file>i wtedy git add --intent-to-add <file>?
alkohol jest zły
1
@alcoholisevil no, z wyjątkiem specjalnego przypadku. Zobacz doskonałą, zwięzłą odpowiedź.
De Novo
45

git rm --cached filebędzie usunąć plik ze sceny. Oznacza to, że po zatwierdzeniu plik zostanie usunięty. git reset HEAD -- filepo prostu zresetuje plik w obszarze pomostowym do stanu, w którym znajdował się w zatwierdzeniu HEAD, tj. cofnie wszelkie zmiany, które zrobiłeś od ostatniego zatwierdzenia. Jeśli ta zmiana dotyczy nowego dodania pliku, będą one równoważne.

yuriks
źródło
7
W połączeniu z pojęciem (jak wspomniano w innych odpowiedziach), które git rm --cached filejest czymś przeciwnym git add, odpowiedź ta miała dla mnie dużo sensu i była dość zwięzła. Prawie tak krótki, jak ten komentarz;)
rbatt
2
@rbatt tylko po to, aby umieścić tutaj komentarz i wyjaśnić, git rm --cached filenie jest przeciwieństwemgit add file . Zachowanie jest odwrotne niż git add filew konkretnym przypadku, gdy dodano nowy, wcześniej nieśledzony plik. W każdym innym przypadku przeciwieństwem git add filejest git reset HEAD file. git reset HEAD filerównież odwraca git add filew pierwszym przypadku (dodając nieśledzony plik) i w każdym przypadku, dlatego właśnie to sugeruje git, jeśli chcesz odwrócić git add.
De Novo