Как отменить «git add» перед фиксацией?

Я по ошибке добавил файлы в Git с помощью команды:

git add myfile.txt

Я еще не запустил git commit. Есть ли способ отменить это, чтобы эти файлы не были включены в коммит?

Комментарии к вопросу (10)
Решение

Вы можете отменить git add перед фиксацией

git reset 

который удалит его из текущего индекса (списка «собирается быть совершенным»), не меняя ничего другого.

Вы можете использовать

git reset

без какого-либо имени файла, чтобы отменить все необходимые изменения. Это может пригодиться, когда слишком много файлов, чтобы их можно было перечислить один за другим за разумное время.

В старых версиях Git, приведенные выше команды эквивалентны git reset HEADи git reset HEAD соответственно, и потерпит неудачу, если HEAD не определен (потому что у тебя есть # 39;пока не делали коммитов в вашем хранилище) или неоднозначно (потому что вы создали ветку под названием HEAD, это глупо, что вы должны 'т делать). Это было изменено в Git 1.8.2, поэтому в современных версиях Git вы можете использовать приведенные выше команды даже до создания первого коммита:

«перезагрузка git» (без параметров или параметров) используется для устранения ошибок, когда у вас нет никаких коммитов в вашей истории, но теперь это дает вам пустой индекс (чтобы соответствовать несуществующему коммиту, на котором вы даже не находитесь).

Комментарии (11)

Ты хочешь:

git rm --cached 

Рассуждение:

Когда я был новичком в этом, я впервые попробовал

git reset .

(чтобы отменить все мое первоначальное добавление), только чтобы получить это (не очень) полезное сообщение:

fatal: Failed to resolve 'HEAD' as a valid ref.

Оказывается, это потому, что HEAD ref (ветвь?) не существует до момента первого коммита. То есть вы столкнетесь с той же проблемой новичка, что и я, если ваш рабочий процесс, как и мой, был чем-то вроде:

  1. cd в мой замечательный новый каталог проектов, чтобы опробовать Git, новую жаркость

  2. git init

  3. Git добавить .

  4. git status

    много дерьмовых свитков ... = > Черт, я не хотел добавлять все это.

  5. Google "undo git add"

= > найти переполнение стека - ура

  1. Git сбросить .

= > смертельно: не удалось разрешить «HEAD» в качестве действительного реф.

Далее выясняется, что есть зарегистрированная ошибка против бесполезности этого в списке рассылки.

И что правильное решение было прямо в выводе статуса Git (который, да, я приукрасил как «дерьмо»)

...

Изменения, которые должны быть совершены:

(используйте "git rm --cached < file >..."отклеивать)

...

И решение действительно состоит в том, чтобы использовать git rm --cached FILE.

Обратите внимание на предупреждения в другом месте здесь - git rm удаляет локальную рабочую копию файла, но not, если вы используете - кэшированный . Вот результат git help rm:

--Cached Используйте эту опцию, чтобы отклеивать и удалять пути только из индекса. Рабочие файлы дерева, измененные или нет, будут оставлены.

Я продолжаю использовать

git rm --cached .

удалить все и начать заново. Не сработало, потому что пока добавить .рекурсивно, оказывается, rm нуждается в -r, чтобы рекурсировать. Вздох.

git rm -r --cached .

Хорошо, теперь я вернулся туда, откуда начал. В следующий раз я собираюсь использовать -n, чтобы сделать пробный запуск и посмотреть, что будет добавлено:

git add -n .

Я отправил все в безопасное место, прежде чем доверять «git help rm» о «-cached», ничего не уничтожая (и что, если я неправильно написал это).

Комментарии (23)

Если вы печатаете:

git status

Git расскажет вам, что поставлено и т. Д., включая инструкции о том, как отцепить:

use "git reset HEAD ..." to unstage

Я считаю, что Git неплохо справляется со своей задачей, заставляя меня поступать правильно в подобных ситуациях.

Примечание: последние версии Git (1.8.4.x) изменили это сообщение:

(use "git rm --cached ..." to unstage)
Комментарии (3)

Чтобы уточнить: git add перемещает изменения из текущего рабочего каталога в область постановки (индекс).

Этот процесс называется постановка . Таким образом, самая естественная команда для stage изменений (измененных файлов) является очевидной:

git stage

git add - это просто простой в использовании псевдоним для git stage

Жаль, что нет команд "git unstage" или "git unadd". Соответствующее сложнее угадать или запомнить, но это довольно очевидно:

git reset HEAD --

Мы можем легко создать псевдоним для этого:

git config --global alias.unadd 'reset HEAD --'
git config --global alias.unstage 'reset HEAD --'

И, наконец, у нас есть новые команды:

git add file1
git stage file2
git unadd file2
git unstage file1

Лично я использую еще более короткие псевдонимы

git a # For staging
git u # For unstaging
Комментарии (4)

В дополнение к принятому ответу, если ваш файл с ошибочной добавленной стоимостью был огромным, вы, вероятно, заметите, что даже после удаления его из индекса с помощью «git reset» он все еще занимает место в «.git». каталог.

Об этом не о чем беспокоиться; файл действительно все еще находится в хранилище, но только как «свободный объект». Он не будет скопирован в другие репозитории (с помощью клона, push), и пространство будет в конечном итоге восстановлено - хотя, возможно, не очень скоро. Если вы беспокоитесь, вы можете бежать:

git gc --prune=now

  • Обновление * (следует моя попытка прояснить некоторую путаницу, которая может возникнуть из-за наиболее проголосовавших ответов):

Итак, что является реальным undo git add?

git reset HEAD < file > ?

или

git rm --cached < file >?

Строго говоря, и если я не ошибаюсь: нет .

git add не может быть отменен - в общем, безопасно.

Давайте сначала вспомним, что на самом деле делает git add < file >:

  1. Если < file >был ранее не отслеживался , git add добавляет его в кэш с его текущим содержимым.

  2. Если < file >был уже отслежен , git add сохраняет текущий контент (снимок, версия) в кеше. В Git это действие все еще называется add (а не просто update it), потому что две разные версии (снимки) файла рассматриваются как два разных элемента: следовательно, мы действительно добавляем новый элемент в кэш, который в конечном итоге будет передан позже.

В свете этого вопрос немного неоднозначен:

Я по ошибке добавил файлы с помощью команды...

Сценарий OP кажется первым (не отслеживаемый файл), мы хотим, чтобы «undo» удалял файл (а не только текущее содержимое) из отслеживаемых элементов. Если это так, то можно запустить 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), и мы обновляем новое содержимое с помощью команды commit, git commit -a.


& Лт; sup >

  • (Редактирование: вышеизложенное практически правильно, но все же могут быть некоторые слегка хакистские / запутанные способы восстановления изменений, которые были организованы, но не совершены, а затем перезаписаны - см. Комментарии Йоханнеса Матокича и iolsmit) & Лт; / sup >
Комментарии (3)

Undo файл, который уже был добавлен, довольно прост с помощью Git. Для сброса myfile.txt, который уже добавлен, используйте:

git reset HEAD myfile.txt

Объяснение:

После того, как вы поставили ненужные файлы, чтобы отменить, вы можете сделать git reset. Head - это глава вашего файла в локальном, а последний параметр - это имя вашего файла.

Я создал шаги на изображении ниже в более подробной информации для вас, включая все шаги, которые могут произойти в этих случаях:

Комментарии (2)
git rm --cached . -r

будет рекурсивно «откладывать» все, что вы добавили из своего текущего каталога

Комментарии (3)

Запустить

git gui

и удалите все файлы вручную или выбрав их все и нажав кнопку unstage from commit .

Комментарии (4)

Git имеет команды для каждого мыслимого действия, но ему нужны обширные знания, чтобы все исправить, и поэтому он в лучшем случае нелогичен...

Что ты делал раньше:

  • Изменил файл и использовал git add .илиgit add < file >.

Что вы хотите:

  • Удалите файл из индекса, но сохраните его в версии и оставьте с незафиксированными изменениями в рабочей копии:

     git reset head < file >
  • Сбросьте файл до последнего состояния из HEAD, отменив изменения и удалив их из индекса:

    & Лт;!- язык: lang-bash - >

     # Подумайте, `svn revert < file > `IIRC .
     git reset HEAD < file >
     git checkout < file >
    
     # Если у вас есть `< branch > `, названный как `< file > `, используйте:
     git checkout - < file >

    Это необходимо, так как git reset --hard HEAD не будет работать с отдельными файлами.

  • Удалить < file > из индекса и версии, сохраняя неверсионный файл с изменениями в рабочей копии:

     git rm --cached < file >
  • Удалить < file > из рабочей копии и полностью изменить версию:

     git rm < file >
Комментарии (3)

Вопрос не совсем поставлен. Причина в том, что git add имеет два значения:

  1. добавление нового файла в область постановки, затем отменить с помощью git rm --cached file.
  2. добавление измененного файла в область постановки, затем отменить с помощью git reset HEAD file.

Если есть сомнения, используйте

git reset HEAD file

Потому что это делает ожидаемую вещь в обоих случаях.

Предупреждение: если вы делаете git rm --cached file в файле, который был изменен (файл, который существовал ранее в хранилище), то файл будет удален в git commit ,! Он все еще будет существовать в вашей файловой системе, но если кто-то еще извлечет ваш коммит, файл будет удален из их рабочего дерева.

git status сообщит вам, был ли файл новым файлом или измененным :

On branch master
Changes to be committed:
  (use "git reset HEAD ..." to unstage)

    new file:   my_new_file.txt
    modified:   my_modified_file.txt
Комментарии (2)

Если вы используете свой первоначальный коммит и не можете использовать git reset, просто объявите «Git branch», удалите папку .git и начните все сначала

Комментарии (2)

Согласно многим другим ответам, вы можете использовать git reset

НО:

Я нашел этот замечательный маленький пост, который фактически добавляет команду Git (ну, псевдоним) для git unadd: см. git unadd для деталей или..

Просто,

git config --global alias.unadd "reset HEAD"

Теперь вы можете

git unadd foo.txt bar.txt
Комментарии (0)

Используйте git add -i, чтобы удалить файлы с добавленной стоимостью из предстоящего коммита. Пример:

Добавление файла, который вы не хотели:

$ git add foo
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#       new file:   foo
#
# Untracked files:
#   (use "git add ..." to include in what will be committed)
# [...]#

Переход к интерактивному добавлению для отмены вашего добавления (команды, введенные в git здесь, это «r» (реверт), «1» (первая запись в списке реверт-шоу), «return» для выхода из режима реверта и «q» (бросить):

$ git add -i
           staged     unstaged path
  1:        +1/-0      nothing foo

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> r
           staged     unstaged path
  1:        +1/-0      nothing [f]oo
Revert>> 1
           staged     unstaged path
* 1:        +1/-0      nothing [f]oo
Revert>> 
note: foo is untracked now.
reverted one path

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> q
Bye.
$

Вот и все! Вот ваше доказательство, показывающее, что «фу» вернулся в список без отслеживания:

$ git status
# On branch master
# Untracked files:
#   (use "git add ..." to include in what will be committed)
# [...]
#       foo
nothing added to commit but untracked files present (use "git add" to track)
$
Комментарии (0)

git remove или git rm можно использовать для этого с флагом - cached. Попробуй:

git help rm
Комментарии (2)

Вот способ избежать этой неприятной проблемы при запуске нового проекта:

  • Создайте основной каталог для вашего нового проекта.
  • Запустите git init.
  • Теперь создайте файл .gitignore (даже если он пуст).
  • Зафиксируйте файл .gitignore.

Git делает действительно трудным выполнение git reset, если у вас нет коммитов. Если вы создаете крошечный начальный коммит только ради его наличия, после этого вы можете git add -A и git reset столько раз, сколько захотите, чтобы все исправить.

Еще одним преимуществом этого метода является то, что если позже вы столкнетесь с проблемами с окончанием строки и вам нужно обновить все ваши файлы, это легко:

  • Проверьте этот начальный коммит. Это удалит все ваши файлы.
  • Затем проверьте ваш последний коммит снова. Это позволит получить свежие копии ваших файлов, используя ваши текущие настройки окончания строки.
Комментарии (4)

Обратите внимание, что если вы не указали ревизию, вы должны включить разделитель. Пример из моей консоли:

git reset <path_to_file>
fatal: ambiguous argument '<path_to_file>': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

git reset -- <path_to_file>
Unstaged changes after reset:
M    <path_to_file>

(Гит версия 1.7.5.4)

Комментарии (1)

Возможно, Git развивался с тех пор, как вы опубликовали свой вопрос.

$> git --version
git version 1.6.2.1

Теперь вы можете попробовать:

git reset HEAD .

Это должно быть то, что вы ищете.

Комментарии (1)

Удалять новые файлы из области подготовки (и только в случае нового файла), как предложено выше:

git rm --cached FILE

Используйте rm --cached только для случайно добавленных новых файлов.

Комментарии (2)

Чтобы сбросить каждый файл в определенной папке (и ее подпапках), вы можете использовать следующую команду:

git reset *
Комментарии (2)

Используйте команду * для обработки нескольких файлов одновременно:

git reset HEAD *.prj
git reset HEAD *.bmp
git reset HEAD *gdb*

так далее.

Комментарии (1)