Dodatek do zaakceptowanej odpowiedzi, jeśli Twój błędnie dodany plik był ogromny, prawdopodobnie zauważysz, że nawet po usunięciu go z indeksu za pomocą „ git reset
” nadal wydaje się, że zajmuje on miejsce w .git
katalogu.
Nie ma się czym martwić; plik jest rzeczywiście nadal w repozytorium, ale tylko jako „luźny obiekt”. Nie zostanie skopiowany do innych repozytoriów (przez klonowanie, wypychanie), a przestrzeń zostanie ostatecznie odzyskana - choć może nie wkrótce. Jeśli jesteś niespokojny, możesz uruchomić:
git gc --prune=now
Aktualizacja (następująca jest moja próba usunięcia pewnych nieporozumień, które mogą wyniknąć z najbardziej uprzywilejowanych odpowiedzi):
Więc, co jest prawdziwym cofania z git add
?
git reset HEAD <file>
?
lub
git rm --cached <file>
?
Ściśle mówiąc, a jeśli się nie mylę: brak .
git add
nie można tego cofnąć - ogólnie bezpiecznie.
Przypomnijmy najpierw, co git add <file>
właściwie robi:
Jeśli nie<file>
był wcześniej śledzony , git add
dodaje go do pamięci podręcznej z bieżącą zawartością.
Jeśli <file>
było już śledzone , git add
zapisuje bieżącą zawartość (migawkę, wersję) w pamięci podręcznej. W Git ta czynność jest nadal nazywana dodawaniem (a nie tylko aktualizacją ), ponieważ dwie różne wersje (migawki) pliku są traktowane jako dwa różne elementy: dlatego rzeczywiście dodajemy nowy element do pamięci podręcznej, aby ostatecznie popełnione później.
W świetle tego pytanie jest nieco dwuznaczne:
Pomyłkowo dodałem pliki za pomocą polecenia ...
Scenariusz PO wydaje się być pierwszym (nieśledzony plik), chcemy, aby „cofnięcie” usunęło plik (nie tylko bieżącą zawartość) ze śledzonych elementów. W takim przypadku można uruchomić git rm --cached <file>
.
I moglibyśmy także biec git reset HEAD <file>
. Jest to na ogół preferowane, ponieważ działa w obu scenariuszach: wykonuje również cofanie, gdy błędnie dodaliśmy wersję już śledzonego elementu.
Ale są dwa zastrzeżenia.
Po pierwsze: istnieje (jak wskazano w odpowiedzi) tylko jeden scenariusz, w którym git reset HEAD
nie działa, ale git rm --cached
działa: nowe repozytorium (bez zatwierdzeń). Ale tak naprawdę jest to praktycznie nieistotny przypadek.
Po drugie: pamiętaj, że git reset HEAD
nie można magicznie odzyskać wcześniej buforowanej zawartości pliku, po prostu ponownie synchronizuje go z HEAD. Jeśli nasz wprowadzony w błąd git add
nadpisał poprzednią zainscenizowaną niezaangażowaną wersję, nie możemy jej odzyskać. Właśnie dlatego, ściśle mówiąc, nie możemy cofnąć [*].
Przykład:
$ 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
Oczywiście nie ma to większego znaczenia, jeśli postępujemy zgodnie ze zwykłym leniwym obiegiem pracy polegającym na wykonywaniu polecenia „git add” tylko w celu dodawania nowych plików (przypadek 1) i aktualizujemy nową zawartość za pomocą git commit -a
polecenia zatwierdzenia .
* (Edycja: powyższe jest praktycznie poprawne, ale nadal mogą istnieć pewne nieco zhackowane / skomplikowane sposoby odzyskiwania zmian, które zostały wprowadzone, ale nie zostały zatwierdzone, a następnie zastąpione - patrz komentarze Johannesa Matokica i iolsmit)
HEAD
lubhead
mogą teraz używać@
zamiastHEAD
zamiast. Zobacz tę odpowiedź (ostatnia sekcja), aby dowiedzieć się, dlaczego możesz to zrobić.