Я по ошибке добавил файлы в Git с помощью команды:
git add myfile.txt
Я еще не запустил git commit
. Есть ли способ отменить это, чтобы эти файлы не были включены в коммит?
Вы можете отменить git add
перед фиксацией
git reset <file>
который удалит его из текущего индекса (списка «собирается быть совершенным»), не меняя ничего другого.
Вы можете использовать
git reset
без какого-либо имени файла, чтобы отменить все необходимые изменения. Это может пригодиться, когда слишком много файлов, чтобы их можно было перечислить один за другим за разумное время.
В старых версиях Git, приведенные выше команды эквивалентны git reset HEAD <file >
и git reset HEAD
соответственно, и потерпит неудачу, если HEAD
не определен (потому что у тебя есть # 39;пока не делали коммитов в вашем хранилище) или неоднозначно (потому что вы создали ветку под названием HEAD
, это глупо, что вы должны 'т делать). Это было изменено в Git 1.8.2, поэтому в современных версиях Git вы можете использовать приведенные выше команды даже до создания первого коммита:
«перезагрузка git» (без параметров или параметров) используется для устранения ошибок, когда у вас нет никаких коммитов в вашей истории, но теперь это дает вам пустой индекс (чтобы соответствовать несуществующему коммиту, на котором вы даже не находитесь).
Ты хочешь:
git rm --cached <added_file_to_undo>
Рассуждение:
Когда я был новичком в этом, я впервые попробовал
git reset .
(чтобы отменить все мое первоначальное добавление), только чтобы получить это (не очень) полезное сообщение:
fatal: Failed to resolve 'HEAD' as a valid ref.
Оказывается, это потому, что HEAD ref (ветвь?) не существует до момента первого коммита. То есть вы столкнетесь с той же проблемой новичка, что и я, если ваш рабочий процесс, как и мой, был чем-то вроде:
cd в мой замечательный новый каталог проектов, чтобы опробовать Git, новую жаркость
git init
Git добавить .
git status
много дерьмовых свитков ... = > Черт, я не хотел добавлять все это.
Google "undo git add"
= > найти переполнение стека - ура
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», ничего не уничтожая (и что, если я неправильно написал это).
Если вы печатаете:
git status
Git расскажет вам, что поставлено и т. Д., включая инструкции о том, как отцепить:
use "git reset HEAD <file>..." to unstage
Я считаю, что Git неплохо справляется со своей задачей, заставляя меня поступать правильно в подобных ситуациях.
Примечание: последние версии Git (1.8.4.x) изменили это сообщение:
(use "git rm --cached <file>..." to unstage)
Чтобы уточнить: 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
В дополнение к принятому ответу, если ваш файл с ошибочной добавленной стоимостью был огромным, вы, вероятно, заметите, что даже после удаления его из индекса с помощью «git reset» он все еще занимает место в «.git». каталог.
Об этом не о чем беспокоиться; файл действительно все еще находится в хранилище, но только как «свободный объект». Он не будет скопирован в другие репозитории (с помощью клона, push), и пространство будет в конечном итоге восстановлено - хотя, возможно, не очень скоро. Если вы беспокоитесь, вы можете бежать:
git gc --prune=now
Итак, что является реальным undo git add
?
git reset HEAD < file >
?
или
git rm --cached < file >
?
Строго говоря, и если я не ошибаюсь: нет .
git add
не может быть отменен - в общем, безопасно.
Давайте сначала вспомним, что на самом деле делает git add < file >
:
Если < file >
был ранее не отслеживался , git add
добавляет его в кэш с его текущим содержимым.
Если < 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 >
Undo файл, который уже был добавлен, довольно прост с помощью Git. Для сброса myfile.txt
, который уже добавлен, используйте:
git reset HEAD myfile.txt
Объяснение:
После того, как вы поставили ненужные файлы, чтобы отменить, вы можете сделать git reset
. Head
- это глава вашего файла в локальном, а последний параметр - это имя вашего файла.
Я создал шаги на изображении ниже в более подробной информации для вас, включая все шаги, которые могут произойти в этих случаях:
Запустить
git gui
и удалите все файлы вручную или выбрав их все и нажав кнопку unstage from commit .
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 >
Вопрос не совсем поставлен. Причина в том, что git add
имеет два значения:
git rm --cached file
.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 <file>..." to unstage)
new file: my_new_file.txt
modified: my_modified_file.txt
Согласно многим другим ответам, вы можете использовать git reset
НО:
Я нашел этот замечательный маленький пост, который фактически добавляет команду Git (ну, псевдоним) для git unadd
: см. git unadd для деталей или..
Просто,
git config --global alias.unadd "reset HEAD"
Теперь вы можете
git unadd foo.txt bar.txt
Используйте git add -i
, чтобы удалить файлы с добавленной стоимостью из предстоящего коммита. Пример:
Добавление файла, который вы не хотели:
$ git add foo
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: foo
#
# Untracked files:
# (use "git add <file>..." 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 <file>..." to include in what will be committed)
# [...]
# foo
nothing added to commit but untracked files present (use "git add" to track)
$
Вот способ избежать этой неприятной проблемы при запуске нового проекта:
git init
.Git делает действительно трудным выполнение git reset
, если у вас нет коммитов. Если вы создаете крошечный начальный коммит только ради его наличия, после этого вы можете git add -A
и git reset
столько раз, сколько захотите, чтобы все исправить.
Еще одним преимуществом этого метода является то, что если позже вы столкнетесь с проблемами с окончанием строки и вам нужно обновить все ваши файлы, это легко:
Обратите внимание, что если вы не указали ревизию, вы должны включить разделитель. Пример из моей консоли:
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)
Используйте команду *
для обработки нескольких файлов одновременно:
git reset HEAD *.prj
git reset HEAD *.bmp
git reset HEAD *gdb*
так далее.