В дополнение к принятому ответу, если ваш ошибочно добавленный файл был огромным, вы, вероятно, заметите, что даже после удаления его из индекса с помощью git reset
он все равно занимает место в .git
каталог. Об этом не стоит беспокоиться, файл действительно все еще находится в репозитории, но только как «свободный объект», он не будет скопирован в другие репозитории (через клон, push), и пространство в конечном итоге будет освобождено - хотя возможно, не очень скоро. Если вы беспокоитесь, вы можете запустить:
git gc --prune=now
Обновление (далее я попытаюсь прояснить некоторую путаницу, которая может возникнуть в результате ответов с наибольшим количеством голосов):
Итак, что является настоящим отменить из git add
?
git reset HEAD <file>
?
или
git rm --cached <file>
?
Собственно говоря, и если я не ошибаюсь: нет .
git add
не может быть отменено - в общем, безопасно.
Давайте сначала вспомним, что на самом деле делает git add <file>
1034 *
Если <file>
был ранее не отслеживался , git add
добавляет его в кэш с его текущим содержимым.
Если <file>
было уже отслежено , git add
сохраняет текущее содержимое (снимок, версия) в кэш. В GIT это действие по-прежнему называется add (а не просто update it), поскольку две разные версии (снимки) файла рассматриваются как два разных элемента: следовательно, мы действительно добавление нового элемента в кеш, который в конечном итоге будет добавлен позже.
В свете этого вопрос несколько двусмысленный:
Я ошибочно добавил файлы с помощью команды ...
Кажется, что сценарий OP является первым (неотслеживаемый файл), мы хотим, чтобы «отмена» удаляла файл (не только текущее содержимое) из отслеживаемых элементов. Если это так, тогда можно запустить 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 lost irrevocably "version 2"
-version 1
+version 3
Конечно, это не очень важно, если мы просто следуем обычному ленивому рабочему процессу выполнения 'git add' только для добавления новых файлов (случай 1), и мы обновляем новое содержимое с помощью команды commit, git commit -a
.
* (Редактировать: вышеупомянутое практически правильно, но все же могут быть несколько хакерские / запутанные способы восстановления изменений, которые были поставлены, но не зафиксированы, а затем перезаписаны - см. Комментарии Йоханнеса Матокича и iolsmit)