На додаток до прийнятої відповіді, якщо ваш помилково доданий файл був величезним, ви, ймовірно, помітите, що навіть після вилучення його з індексу із символом ' git reset
' він як і раніше займає місце в .git
каталозі.
Це не про що турбуватися; файл дійсно все ще знаходиться у сховищі, але лише як "вільний об'єкт". Він не буде скопійований в інші сховища (через клон, push), і простір буде врешті повернено - хоча, можливо, не дуже скоро. Якщо ви хвилюєтеся, можете запустити:
git gc --prune=now
Оновлення (далі - моя спроба усунути певну плутанину, яка може виникнути з найбільш схвалених відповідей):
Отже, що реальний відкат від git add
?
git reset HEAD <file>
?
або
git rm --cached <file>
?
Строго кажучи, і якщо я не помиляюсь: ні .
git add
не можна скасувати - безпечно, загалом.
Давайте спочатку згадаємо, що git add <file>
насправді робить:
Якщо <file>
був раніше не відслідковуються , git add
додає його в кеш , з його поточним утриманням.
Якщо <file>
його вже відстежували , git add
зберігає поточний вміст (знімок, версію) в кеш. У Git ця дія все ще називається додати (не просто її оновити ), оскільки дві різні версії (знімки) файлу розглядаються як два різні елементи: отже, ми дійсно додаємо новий елемент у кеш, щоб бути зрештою вчинено пізніше.
Зважаючи на це, питання є дещо неоднозначним:
Я помилково додав файли за допомогою команди ...
Сценарій ОП, здається, перший (неповернутий файл), ми хочемо, щоб "скасувати" видалив файл (не лише поточний вміст) з відстежуваних елементів. Якщо це так, то нормально бігати 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 irrevocably lost "version 2"
-version 1
+version 3
Звичайно, це не дуже важливо, якщо ми просто дотримуємося звичайного ледачого робочого процесу, роблячи «git add» лише для додавання нових файлів (випадок 1), і ми оновлюємо новий вміст за допомогою команди комітування, git commit -a
команда.
* (Редагувати: вищезазначене практично правильно, але все ж можуть бути кілька зловмисних / заплутаних способів відновлення змін, які були інсценовані, але не скоєні та перезаписані - див. Коментарі Йоханнеса Матокича та iolsmit)
HEAD
абоhead
можуть тепер використовувати@
замістьHEAD
замість цього. Дивіться цю відповідь (останній розділ), щоб дізнатися, чому ви можете це зробити.