Я по ошибке добавил файлы в Git с помощью команды:
git add myfile.txt
Я еще не запускал git commit
. Есть ли способ отменить это, чтобы эти файлы не были включены в коммит?
Я по ошибке добавил файлы в Git с помощью команды:
git add myfile.txt
Я еще не запускал git commit
. Есть ли способ отменить это, чтобы эти файлы не были включены в коммит?
Вы можете отменить git add
перед фиксацией с помощью
git reset <file>
, который удалит его из текущего индекса (списка «собирается быть зафиксированным») без каких-либо изменений.
Вы можете использовать
git reset
без имени файла, чтобы отключить все необходимые изменения. Это может пригодиться, когда файлов слишком много, чтобы их можно было перечислить один за другим за разумный промежуток времени.
В старых версиях Git приведенные выше команды эквивалентны git reset HEAD <file>
и git reset HEAD
соответственно и завершатся ошибкой, если HEAD
не определено (потому что вы еще не сделали никаких коммитов в своем репозитории) или неоднозначно ( потому что вы создали ветку с именем HEAD
, что является глупостью, которую вам не следует делать). Однако этот был изменен в Git 1.8.2, поэтому в современных версиях Git вы можете использовать приведенные выше команды еще до совершения первого коммита:
"git reset" (без опций или параметров) используется для вывода ошибки, когда в вашей истории нет никаких коммитов, но теперь это дает вам пустой индекс (для соответствия несуществующей фиксации, в которой вы даже не участвуете).
Документация: git reset
Конечно, это не настоящая отмена, потому что, если неправильная git add
перезаписала предыдущую поэтапную незавершенную версию, мы не сможем ее восстановить. Я попытался пояснить это в своем ответе ниже.
git reset HEAD *.ext
, где ext
- это файлы с заданным расширением, которые вы хотите отменить. Для меня это было *.bmp
и *.zip
git reset сказал, что он отменил изменения, но когда я перешел к другому статусу git, они все еще показывали измененные
Значит, противоположность «добавить» - это «сбросить»? А как насчет «удалить»?
@Jonny, индекс (он же промежуточная область) содержит все файлы, а не только измененные файлы. Он «запускает жизнь» (когда вы проверяете фиксацию или клонируете репо) как копию всех файлов в фиксации, на которые указывает HEAD. Итак, если вы удалите файл из индекса (git rm --cached
), это означает, что вы готовитесь совершить фиксацию, которая удалит этот файл. git reset HEAD <filename>
, с другой стороны, скопирует файл из HEAD в индекс, так что следующая фиксация не покажет никаких изменений, внесенных в этот файл.
Я только что обнаружил, что существует git reset -p
, как и git add -p
. Это круто!
-p
определенно потрясающий, и он используется во многих командах git (а не только в сбросе и добавлении). Но ответ на @ WeDoTDD.com и @Johnny, git reset
сам по себе просто проясняет, «знает ли Git об изменениях»; он не очищает сами изменения. Для этого вам нужно сделать git checkout someFile.txt
(для отдельных файлов) или git reset --hard
(чтобы все стереть). Однако ни одна из этих команд не вернется назад, поэтому будьте очень осторожны при их использовании.
но «git reset file» удаляет и другие файлы, которые также были подготовлены для фиксации. не хорошо.
На самом деле вы можете восстановить перезаписанные ранее поставленные, но незавершенные изменения , но не удобным для пользователя способом и не на 100% безопасным (по крайней мере, я не нашел): goto .git / objects, поиск файлов, созданных во время git add
, который вы хотите восстановить (61/3AF3...
-> идентификатор объекта 613AF3...
), затем git cat-file -p <object-id>
(возможно, стоит восстановить несколько часов работы, но также урок, который нужно совершать чаще ...)
Другой способ восстановить изменения, которые были поставлены, но не зафиксированы, а затем перезаписаны , например, другой git add
через git fsck --unreachable
, в котором будут перечислены все недостижимые объекты, которые вы затем можете проверить с помощью git show SHA-1_ID
или git fsck --lost-found
, которые будут> записывать оборванные объекты в .git/lost-found/commit/
или .git/lost-found/other/
, в зависимости от типа. Также git fsck --help
Начиная с git 2.23.0, теперь существует "git restore --staged <file>..." to unstage
. См. Coderhelper.com/a/16044987/40422
Я также добавил на сцену несколько файлов из общей библиотеки. Поскольку это угловое приложение, мне пришлось использовать git reset */commonlib/styles/*.scss
, чтобы найти все такие файлы, и это сработало.
Хорошо объяснено ... полезно для новичков
Спасибо, это было легко понять и было полезно.
Я не знаю, правильно ли я сделал это, но git reset <file>
, похоже, также удалил файл из моей файловой системы, что, очевидно, не то, что вам нужно.
Вы можете использовать эту команду после версии git 2.23:
git restore --staged <filename>
Или вы можете использовать эту команду:
git reset HEAD <filename>
Добро пожаловать в Stack Overflow. Если вы решите ответить на старый вопрос, на который есть хорошо обоснованные и правильные ответы, добавление нового ответа в конце дня может не принести вам никакого кредита. Если у вас есть какая-то особенная новая информация или вы убеждены, что все остальные ответы неверны, обязательно добавьте новый ответ, но «еще один ответ», дающий ту же основную информацию через долгое время после того, как вопрос был задан, обычно выигрывал » Я не заслуживаю большого уважения.
Вы можете отключить / отменить с помощью команды git или графического интерфейса git.
Один файл
git reset File.txt
Несколько файлов
git reset File1.txt File2.txt File3.txt
Пример -
Предположим, вы добавили Home.js , ListItem.js , Update.js по ошибке
и хотите отменить / сбросить =>
git reset src/components/home/Home.js src/components/listItem/ListItem.js src/components/update/Update.js
Тот же пример с использованием git GUI
git gui
открывает окно => Снимите отметку с ваших файлов с Поэтапные изменения (будут зафиксированы)
Если вы решите ответить на старый вопрос, на который есть хорошо обоснованные и правильные ответы, добавление нового ответа в конце дня может не принести вам никакого кредита. Если у вас есть какая-то особенная новая информация или вы убеждены, что все остальные ответы неверны, обязательно добавьте новый ответ, но «еще один ответ», дающий ту же основную информацию через долгое время после того, как вопрос был задан, обычно выигрывал » Я не заслуживаю большого уважения. Вы добавили «красивые картинки» - я не уверен, что все они так полезны. Они были бы неразборчивы, если бы я читал этот ответ по мобильному телефону.
В первый раз, когда у меня возникла эта проблема, я нашел здесь этот пост и из первого ответа понял, что мне нужно просто сделать git reset <filename>
. Работало нормально.
В конце концов, в моей основной папке git оказалось несколько подпапок. Мне было легко просто сделать git add .
, чтобы добавить все файлы во вложенные папки, а затем git reset
несколько файлов, которые я не хотел добавлять.
Сейчас у меня много файлов и подпапок. git reset
один за другим утомительно, но все же проще сначала просто git add .
, а затем сбросить несколько тяжелых / нежелательных, но полезных файлов и папок.
Я нашел следующий метод (который не записан здесь или здесь) относительно простым. Надеюсь, это будет полезно:
Допустим, у вас следующая ситуация:
Folder/SubFolder1/file1.txt
Folder/SubFolder2/fig1.png
Folder/SubFolderX/fig.svg
Folder/SubFolder3/<manyfiles>
Folder/SubFolder4/<file1.py, file2.py, ... file60.py, ...>
Вы хотите добавить все папки и файлы, но не fig1.png
, и не SubFolderX
, и не file60.py
, и список продолжает расти ...
Сначала создайте / создайте bash shell script
и дайте ему имя. Скажем, git_add.sh
:
Затем добавьте все пути ко всем папкам и файлам, которые вы хотите git reset
, перед которыми стоит git reset --
. Вы можете легко скопировать и вставить пути в сценарий git_add.sh
по мере роста вашего списка файлов. Скрипт git_add.sh
должен выглядеть так:
#!/bin/bash
git add .
git reset -- Folder/SubFolder2/fig1.png
git reset -- Folder/SubFolderX
git reset -- Folder/SubFolder4/file60.py
#!/bin/bash
важно. Затем выполните source git_add.sh
, чтобы запустить его. После этого вы можете сделать git commit -m "some comment"
, а затем git push -u origin master
, если вы уже настроили Bitbucket / Github.
Отказ от ответственности: я тестировал это только в Linux.
Если у вас много файлов и папок, которые вы всегда сохраняете в локальном репозитории git, но вы не хотите, чтобы git отслеживал изменения, когда вы делаете git add .
, скажем, файлы видео и данных, , вы должны узнать, как использовать .gitignore
. Может быть из здесь.
Если вы source
файл, он не обязательно должен быть исполняемым.
Рассматривали ли вы использование файла .gitignore
для предотвращения добавления файлов и каталогов, которые не следует добавлять?
Как указывалось другими в связанных вопросах (см. Здесь, здесь, здесь, здесь, здесь, здесь и здесь), теперь вы можете отключить один файл с помощью:
git restore --staged <file>
и деактивируют все файлы (из корня репо) с помощью:
git restore --staged .
git restore
был представлен в июле 2019 года и выпущен в версии 2.23.
С флагом --staged
он восстанавливает содержимое индекса (о чем здесь спрашивают).
При запуске git status
с поэтапными незафиксированными файлами теперь Git предлагает использовать для деактивации файлов (вместо git reset HEAD <file>
, как это было до версии 2.23).
Команда git reset
помогает вам изменить либо промежуточную область, либо промежуточную область и рабочее дерево. Способность Git создавать коммиты в точности так, как вы хотите, означает, что иногда вам нужно отменить изменения, внесенные вами с помощью git add
.
Вы можете сделать это, позвонив по телефону git reset HEAD <file to change>
. У вас есть два варианта, чтобы полностью избавиться от изменений. git checkout HEAD <file(s) or path(s)>
- это быстрый способ отменить изменения в промежуточной области и рабочем дереве.
Однако будьте осторожны с этой командой, потому что она удаляет все изменения в вашем рабочем дереве. Git не знает об этих изменениях, поскольку они никогда не фиксировались. После выполнения этой команды невозможно вернуть эти изменения.
Другая команда в вашем распоряжении - git reset --hard
. Это также разрушительно для вашего рабочего дерева - любые незафиксированные изменения или поэтапные изменения теряются после его запуска. Запуск git reset -hard HEAD
делает то же самое, что и git checkout HEAD
. Просто для работы не требуется файл или путь.
Вы можете использовать --soft
с git reset
. Он сбрасывает репозиторий на указанную вами фиксацию и выполняет все эти изменения. Никакие изменения, которые вы уже сделали, не затронуты, как и изменения в вашем рабочем дереве.
Наконец, вы можете использовать --mixed
для сброса рабочего дерева без промежуточных изменений. Это также отменяет постановку любых изменений.
Для конкретного файла:
- git reset my_file.txt
- git checkout my_file.txt
Для всех добавленных файлов:
- git reset.
- git checkout.
Примечание: checkout изменяет код в файлах и переходит в последнее обновленное (зафиксированное) состояние. сброс не меняет коды; он просто сбрасывает заголовок.
Объясните, пожалуйста, разницу между git reset <file>
и git checkout <file>
.
reset не изменяет файл, просто убирает его со сцены (= index, куда он был помещен git add)
checkout изменить коды в файле и перейти к последнему обновленному состоянию. сброс не меняет коды, он просто сбрасывает заголовок. Например, сбросить использование для добавленных или зафиксированных файлов, сбросить перед использованием push и checkout для возврата к последнему обновленному / зафиксированному этапу перед git add.
reset = удалить файл со сцены, однако изменения останутся. checkout = получает обновленный файл из репозитория и заменяет текущий файл
git reset filename.txt
Удалит файл с именем filename.txt из текущего индекса, области «готовится к фиксации», ничего не меняя.
git reset [имя файла] пример: git reset src / main / java / com / dao / ImportCsvDataDaoImpl.java
Отменить уже добавленный файл довольно просто с помощью Git. Для сброса уже добавленных myfile.txt
используйте:
git reset HEAD myfile.txt
Пояснение :
После того, как вы разместили ненужные файлы, чтобы отменить их, вы можете выполнить git reset
. Head
- это заголовок вашего файла в локальном, а последний параметр - это имя вашего файла.
Я создал для вас более подробную информацию о шагах на изображении ниже, включая все шаги, которые могут произойти в этих случаях:
Изображение: «Команда добавляет ...» → «Команда добавляет ...» (настоящее простое время, от третьего лица)
Изображение: хочу → хочу (здесь нет необходимости использовать сленг)
git add myfile.txt
# Это добавит ваш файл в список подлежащих фиксации
Совершенно противоположно этой команде,
git reset HEAD myfile.txt # This will undo it.
Итак, вы вернетесь в предыдущее состояние. Указанный будет снова в неотслеживаемом списке (предыдущее состояние).
Он сбросит вашу голову с указанным файлом. так что, если в вашей голове его нет, он просто сбросит его.
Одним из наиболее интуитивно понятных решений является использование Sourcetree.
Вы можете просто перетаскивать файлы из промежуточного и неустановленного
Предположим, я создаю новый файл, newFile.txt
:
Предположим, я добавляю файл случайно, git add newFile.txt
:
Теперь я хочу отменить это добавление перед фиксацией, git reset newFile.txt
:
Предположим, я нахожусь на 1-м рисунке, что означает, что я даже не делал "git.add". Кроме того, я совсем не хочу, чтобы все это изменялось. Я имею в виду, что когда я делаю git status, он не должен показывать никаких красных файлов. Я имею в виду, что он должен быть синхронизирован, как если бы ни один файл не был изменен с момента последнего git push. как этого добиться.
Итак, предположим, вы только на первом этапе. И вы хотите избавиться от всех сделанных вами изменений, в результате чего файл newFile.txt становится красным.
Когда я делаю git status. Я вообще не должен видеть никаких изменений. Все красные файлы должны быть возвращены.
Привет, я думаю, ваш вопрос заключается в том, как удалить неотслеживаемые файлы из текущего дерева. Для этого вы можете использовать «git clean -f -d». Это также удалит неотслеживаемые каталоги.
Если вы не хотите удалять неотслеживаемые файлы, просто игнорируйте флаг «-f».
Это не работает. Предположим, я сделал git push. Теперь, если я добавлю одну строку в свой код и проверю git status. Он покажет файл красного цвета. Предположим, я вообще не хочу менять одну строчку. Один из вариантов - я могу нажать cntrl + z. Но я хочу, чтобы git сделал это за меня. Я хочу, чтобы мой локальный проект синхронизировался с главным репозиторием. Я имею в виду, что когда я делаю «git status», я должен видеть сообщение «Он синхронизируется с мастером». И когда я открываю свой код, у меня должно быть сообщение типа «какой-то внешний источник вносит изменения», и когда я говорю «Да» в ответ на это приглашение, то одно изменение строки, которое я сделал, должно исчезнуть.
в основном мне нужна команда git, которая отменит все изменения, которые делают статус git, чтобы отображать "красные файлы"
Итак, я внес изменения в файл. Больше я ничего не делал. НЕТ команды git вообще (нет git push, даже git add или git commit). Но теперь мне нужна команда git, которая отменит эти изменения в моем локальном репо.
В более технических терминах «Как отменить изменения файла, сделанные в локальном репо, которые не были помещены в промежуточную область»
Разве вы не пробовали "git checkout file_name". Кроме того, вы можете сохранить изменения, используя «git stash».
Git reset без Head использует текущие поэтапные файлы. Используйте команду git reset head, чтобы указать другую фиксацию. Как git reset Head ~ 2, чтобы вернуться к предыдущим коммитам. 2 - количество коммитов
git reset filename.txt
Удалит файл с именем filename.txt из текущего индекса, области «собирается быть зафиксированным», без каких-либо изменений.
В Sourcetree вы можете легко сделать это через графический интерфейс. Вы можете проверить, какую команду Sourcetree использует для деактивации файла.
Я создал новый файл и добавил его в Git. Затем я отключил его с помощью графического интерфейса Sourcetree. Это результат:
Деактивация файлов [12.08.15 10:43] git -c diff.mnemonicprefix = false -c core.quotepath = false -c credential.helper = sourcetree reset -q - path / to / file / filename.java
Sourcetree использует reset
для деактивации новых файлов.
Да, тот же метод можно использовать с TortoiseGit, получая команды Git для общих случаев использования.
Также есть интерактивный режим:
git add -i
Выберите вариант 3, чтобы отменить добавление файлов. В моем случае я часто хочу добавить более одного файла, а в интерактивном режиме вы можете использовать такие числа для добавления файлов. Это займет все, кроме 4: 1, 2, 3 и 5
Чтобы выбрать последовательность, просто введите 1-5, чтобы взять все от 1 до 5.
«Я удивлен, что никто не упомянул интерактивный режим» - они сделали: coderhelper.com/a/10209776/1709587
Вопрос четко не сформулирован. Причина в том, что git add
имеет два значения:
git rm --cached file
. git reset HEAD file
. В случае сомнений используйте
git reset HEAD file
Потому что в обоих случаях он делает ожидаемую вещь.
Предупреждение: если вы сделаете git rm --cached file
для файла, который был изменен (файл, который существовал ранее в репозитории), то файл будет удален8183774289> ! Он по-прежнему будет существовать в вашей файловой системе, но если кто-то еще выполнит вашу фиксацию, файл будет удален из его рабочего дерева.
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
+1. Чрезвычайное количество высоко оцененных ответов и комментариев на этой странице просто категорически неверно о поведении git rm --cached somefile
. Я надеюсь, что этот ответ дойдет до страницы на видном месте, где он может защитить новичков от введения в заблуждение всеми ложными утверждениями.
один из лучших ответов здесь, к сожалению, он довольно низкий в списке
Используйте команду *
для одновременной обработки нескольких файлов:
git reset HEAD *.prj
git reset HEAD *.bmp
git reset HEAD *gdb*
и т. Д.
Помните, что * обычно не включает точечные файлы или «точечные каталоги», если вы явно не укажете .*
или .*.prj
В Git есть команды для всех мыслимых действий, но ему нужны обширные знания, чтобы все делать правильно, и поэтому это в лучшем случае нелогично ...
То, что вы делали раньше:
git add .
или git add <file>
. Что вы хотите:
Удалите файл из индекса, но оставьте его версионным и оставьте с незафиксированными изменениями в рабочей копии:
git reset HEAD <file>
Сбросить файл в последнее состояние из HEAD, отменив изменения и удалив их из индекса:
# Think `svn revert <file>` IIRC.
git reset HEAD <file>
git checkout <file>
# If you have a `<branch>` named like `<file>`, use:
git checkout -- <file>
Это необходимо, поскольку git reset --hard HEAD
не работает с отдельными файлами.
Удалить <file>
из индекса и управления версиями, сохранив файл без версий с изменениями в рабочей копии:
git rm --cached <file>
Полное удаление <file>
из рабочей копии и управления версиями:
git rm <file>
Я не могу понять разницу между git reset head <file> и git rm --cached <file>. Не могли бы вы это объяснить?
Файлы @jeswang либо «известны» git (изменения в них отслеживаются), либо не контролируются версиями. reset head
отменяет ваши текущие изменения, но файл все еще отслеживается git. rm --cached
выводит файл из системы управления версиями, поэтому git больше не проверяет его на наличие изменений (а также удаляет в конечном итоге проиндексированные текущие изменения, указанные git предыдущим add
), но измененный файл будет сохранен в вашей рабочей копии, это находится в вашей файловой папке на жестком диске.
Разница в git reset HEAD <file>
носит временный характер - команда будет применена только к следующей фиксации, но git rm --cached <file>
будет отключена до тех пор, пока не будет добавлена снова с git add <file>
. Кроме того, git rm --cached <file>
означает, что если вы нажмете эту ветку на удаленный компьютер, любой, кто потянет ветку, ДЕЙСТВИТЕЛЬНО удалит файл из своей папки.
именно то, что я искал git checkout -- <file>
, спасибо!
Эта команда откроет ваши изменения:
git reset HEAD filename.txt
Вы также можете использовать
git add -p
для добавления частей файлов.
Чтобы сбросить каждый файл в определенной папке (и ее подпапках), вы можете использовать следующую команду:
git reset *
Фактически, это не сбрасывает каждый файл, потому что * использует расширение оболочки и игнорирует точечные файлы (и точечные каталоги).
Вы можете запустить git status
, чтобы увидеть все, что осталось, и сбросить его вручную, то есть git reset file
.
Используйте 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.
$
Вот и все! Вот ваше доказательство, показывающее, что "foo" снова в списке неотслеживаемых:
$ 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 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>
(Git версии 1.7.5.4)
Я попробовал git reset <path>
, и он отлично работает без разделителя. Я также использую git 1.9.0. Может в старых версиях не работает?
Выполнить
git gui
и удалите все файлы вручную или выбрав их все и нажав кнопку unstage from commit .
Да, я это понимаю. Я только хотел косвенно предложить, чтобы вы указали, что в вашем ответе вроде «Вы можете использовать git-gui
....» :)
Он говорит: «git-gui: команда не найдена». Я не уверен, работает ли это.
Вау, это намного проще, чем вводить командные строки, которые вы не понимаете. Это определенно рекомендуется для таких новичков, как я. Спасибо, что написали это!
Спасибо. Не хотел рисковать, поэтому пришлось использовать графический интерфейс.
Вот способ избежать этой неприятной проблемы при запуске нового проекта:
git init
. Git сильно усложняет выполнение git reset
, если у вас нет никаких коммитов. Если вы создаете крошечную начальную фиксацию только для того, чтобы иметь ее, после этого вы можете git add -A
и git reset
сколько угодно раз, чтобы все было правильно.
Еще одним преимуществом этого метода является то, что если вы позже столкнетесь с проблемами, связанными с окончанием строки, и вам потребуется обновить все ваши файлы, это просто:
Подтвержденный! Пробовал сбросить git после добавления git. и git жаловался на поврежденную HEAD. Следуя вашему совету, я мог бы без проблем git add и reset туда и обратно :)
Вторая часть работает, но немного коряво. Как обрабатываются окончания строк, зависит от значения autocrlf
... Это не будет работать в каждом проекте, в зависимости от настроек.
Этот ответ был разумным в то время, когда он был опубликован, но сейчас он устарел; git reset somefile
и git reset
оба работают до совершения первой фиксации, сейчас. Так было с нескольких выпусков Git назад.
@MarkAmery, возможно, вы правы (было бы здорово, если бы вы разместили источник для своего утверждения), но все же есть смысл начать репо с чистой или двумя фиксациями.
Дополнение к принятому ответу: если ваш ошибочно добавленный файл был огромным, вы, вероятно, заметите, что даже после удаления его из индекса с помощью 'git reset
' он все еще занимает место в .git
каталог.
Не о чем беспокоиться; файл действительно все еще находится в репозитории, но только как «свободный объект». Он не будет скопирован в другие репозитории (через clone, 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 это действие по-прежнему называется добавить (а не просто обновить это), потому что две разные версии (снимки) файла рассматриваются как два разных элемента: следовательно, мы действительно добавление нового элемента в кеш, который в конечном итоге будет зафиксирован позже.
В свете этого вопрос несколько двусмысленный:
Я по ошибке добавил файлы с помощью команды ...
Сценарий 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 irrevocably lost "version 2"
-version 1
+version 3
Конечно, это не очень важно, если мы просто следуем обычному ленивому рабочему процессу, выполняя 'git add' только для добавления новых файлов (случай 1), и обновляем новое содержимое с помощью команды commit, git commit -a
.
* (Редактировать: приведенное выше практически правильно, но все же могут быть некоторые слегка хакерские / запутанные способы восстановления изменений, которые были поставлены, но не зафиксированы, а затем перезаписаны - см. Комментарии Йоханнеса Матокича и iolsmit)
Строго говоря, есть способ восстановить уже подготовленный файл, который был заменен git add. Как вы упомянули, git add создает объект git для этого файла, который станет свободным объектом не только при полном удалении файла, но и при перезаписи новым содержимым. Но нет команды для его автоматического восстановления. Вместо этого файл должен быть идентифицирован и извлечен вручную или с помощью инструментов, написанных только для этого случая (libgit2 позволяет это). Но это будет выплачиваться только в том случае, если файл очень важный и большой и не может быть восстановлен путем редактирования предыдущей версии.
Чтобы исправить себя: как только свободный объектный файл будет найден (используйте метаданные, такие как дата / время создания), git cat-file
можно использовать для восстановления его содержимого.
Другой способ восстановить изменения, которые были поставлены, но не зафиксированы, а затем перезаписаны , например, другой git add
через git fsck --unreachable
, который перечислит все недостижимые объекты, которые вы затем можете проверить с помощью git show SHA-1_ID
или git fsck --lost-found
, который будет> записывать висячие объекты в .git/lost-found/commit/
или .git/lost-found/other/
, в зависимости от типа. См. Также git fsck --help
Как и многие другие ответы, вы можете использовать git reset
НО :
Я нашел этот замечательный небольшой пост, который на самом деле добавляет команду Git (ну, псевдоним) для git unadd
: см. git unadd для подробностей или ..
Просто,
git config --global alias.unadd "reset HEAD"
Теперь вы можете
git unadd foo.txt bar.txt
Альтернативно / напрямую:
git reset HEAD foo.txt bar.txt
Для пояснения: git add
перемещает изменения из текущего рабочего каталога в промежуточную область (индекс).
Этот процесс называется промежуточным . Итак, наиболее естественная команда для стадии изменений (измененных файлов) очевидна:
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 stage
- это псевдоним для git add
, исторической команды как в Git, так и в других SCM. Он был добавлен в декабре 2008 года с коммитом 11920d28da в «репозиторий Git git», если можно так сказать.
Это может быть не связано, но я обнаружил, что проверка файла еще до того, как добавить полезную идею, может быть, например, check-command filename && git add filename, я заменил git на более короткий g на моем компьютере, и до сих пор он работал хорошо для меня: github.com/dataf3l/g, я не знаю, будет ли это кому-то полезно, но я помещу его сюда в надежде, что это сэкономит время некоторых людей.
Просто введите git reset
, он вернется обратно, и это похоже на то, что вы никогда не вводили git add .
с момента последней фиксации. Убедитесь, что вы сделали это раньше.
Так получилось, что была последняя фиксация ... но я специально спрашивал об удалении одного файла из фиксации, а не каждого файла из фиксации.
git rm --cached . -r
рекурсивно «удалит» все, что вы добавили из текущего каталога.
Я не собирался убирать все, только ОДИН конкретный файл.
Также полезно, если у вас нет предыдущих коммитов. В отсутствие предыдущей фиксации git reset HEAD <file>
скажет fatal: Failed to resolve 'HEAD' as a valid ref.
Нет, этот добавляет удаление всего в вашем текущем каталоге. Очень отличается от просто незавершенных изменений.
Если у вас начальная фиксация и вы не можете использовать git reset
, просто объявите «Git банкротство», удалите папку .git
и начните с
Один совет - скопируйте файл .git / config, если вы добавили удаленное происхождение, перед удалением папки.
Комментарий @ChrisJohnsen - это точно. Иногда вы хотите зафиксировать все файлы, кроме одного: git add -A && git rm --cached EXCLUDEFILE && git commit -m 'awesome commit'
(это также работает, когда нет предыдущих коммитов, из-за проблемы Failed to resolve 'HEAD'
)
Возможно, Git изменился с тех пор, как вы разместили свой вопрос.
$> git --version
git version 1.6.2.1
Теперь вы можете попробовать:
git reset HEAD .
Это должно быть то, что вы ищете.
Конечно, но тогда у вас есть следующий вопрос о том, как отменить добавление одного из двух (или более) добавленных файлов. Однако в руководстве «git reset» упоминается, что «git reset <paths>» является противоположностью «git add <paths>».
Чтобы удалить новые файлы из промежуточной области (и только в случае нового файла), как предложено выше:
git rm --cached FILE
Используйте rm --cached только для новых файлов, добавленных случайно.
Имейте в виду, что --cached
здесь действительно важная часть.
-1; нет, это не отменяет этапирование файла, а выполняет его удаление (без фактического удаления его из вашего рабочего дерева).
Вы хотите:
git rm --cached <added_file_to_undo>
Рассуждение:
Когда я был новичком в этом, я сначала попробовал
git reset .
(чтобы отменить все мое первоначальное добавление), только чтобы получить это (не очень) полезное сообщение:
fatal: Failed to resolve 'HEAD' as a valid ref.
Оказывается, это потому, что ссылка HEAD (ветвь?) Не существует до момента первой фиксации. То есть вы столкнетесь с той же проблемой новичка, что и я, если бы ваш рабочий процесс, как и мой, был примерно таким:
git init
git add .
git status
... много свитков дерьма от ...
=> Блин, я не хотел все это добавлять.
google "отменить git add"
=> найти переполнение стека - ура
git reset .
=> фатальный: не удалось разрешить "HEAD" как действительную ссылку.
Далее выясняется, что существует ошибка, записанная на фоне бесполезности этого в списке рассылки.
И что правильное решение было прямо там, в выводе статуса Git (которое, да, я замалчил как 'дерьмо)
... # Changes to be committed: # (use "git rm --cached <file>..." to unstage) ...
И решение действительно состоит в том, чтобы использовать git rm --cached FILE
.
Обратите внимание на предупреждения в другом месте - git rm
удаляет вашу локальную рабочую копию файла, но не , если вы используете --cached . Вот результат git help rm
:
- кэшировано Используйте эту опцию, чтобы деактивировать и удалить пути только из индекса. Файлы рабочего дерева, измененные или нет, останутся.
Я перехожу к использованию
git rm --cached .
, чтобы удалить все и начать заново. Однако это не сработало, потому что, хотя add .
является рекурсивным, оказывается, что rm
требует -r
для рекурсии. Вздох.
git rm -r --cached .
Хорошо, теперь я вернулся к тому, с чего начал. В следующий раз я собираюсь использовать -n
для пробного прогона и посмотреть, что будет добавлено:
git add -n .
Я заархивировал все в безопасное место, прежде чем доверять git help rm
насчет того, что --cached
ничего не разрушает (и что, если я ошибся в написании).
Не просто "git reset" без. делай что хочешь, или я что-то упускаю?
Ха. Я следовал тому же процессу. За исключением того, что я сдался и сказал rm -rf .git
, git init
, потому что не доверял git rm --cached
хранить свою рабочую копию. Это немного говорит о том, что git в некоторых местах все еще слишком сложен. git unstage
должна быть стандартной стандартной командой, мне все равно, могу ли я добавить ее в качестве псевдонима.
Сделал это, и он удалил все остальные мои существующие файлы - без изменений - из резервной копии git. Их повторное добавление делает все больше и разрушает настоящую историю. Git - это полностью незаконченный проект.
в последних версиях git (проверено v1.7.1.1) git rm -r --cached .
работает нормально
Если вам нравится git reset
, попробуйте git reset *
вместо git reset .
- он разложит все ранее поставленные файлы.
Блестящий ответ, который точно описал мой рабочий процесс. На самом деле это должен быть принятый ответ, чтобы быть первым, так как этот Q - это то, что находится в верхней части результатов поиска для "git unstage".
Вместо пробного прогона пройдите через добавление с git add -p
Для меня git говорит git reset HEAD <File>...
Вы также можете использовать git stash/git stash pop
, чтобы избежать архивирования / резервного копирования всего.
git rm --cached <file> на самом деле правильный ответ, если это начальный импорт <file> в репозиторий. Если вы пытаетесь отключить изменение файла, правильным ответом будет git reset. Люди, утверждающие, что это неверный ответ, думают о другом вопросе.
Это действительно сработает, но только при первой фиксации, если файл не существовал раньше, или когда команда git add
добавила новые файлы, , но не изменила существующие файлы .
Я определенно считаю, что если это совершенно новый репозиторий, удаление каталога .git
и повторная инициализация - лучший способ. Для случаев в хорошо используемом репо, где вы просто случайно добавили один файл, git rm --cached <file>
кажется лучшим, хотя после фиксации я получаю пугающий delete mode 100644 file
.
в соответствии с git status
выводом git версии 1.8.1.4 правильный способ деактивации новых файлов: git reset HEAD <file>...
просто показывает, насколько неинтуитивным и запутанным является git. вместо того, чтобы иметь параллельные команды «отменить», вы должны выяснить, как их отменить. Например, попытаться освободить ногу в быстром песке, а затем застрять в руке, а затем застрять вторую руку ... каждая команда должна выполняться через графический интерфейс с элементами раскрывающегося меню для параметров ... Подумайте обо всем пользовательском интерфейсе, прирост производительности у нас был, но у нас есть этот беспорядок интерфейса командной строки в стиле ретро. Это не похоже на то, что программы с графическим интерфейсом пользователя git делают это более интуитивно понятным.
@BarryKelly, нет, это неправильный ответ. На самом деле вам нужно либо git reset
, чтобы отменить все добавленные файлы, либо git reset <file>
, чтобы отменить определенный добавленный файл. git rm --cached
может работать на поверхности, но на самом деле он удаляет его из истории отслеживания, а это не то, что вы хотели бы делать, если только вы не добавили этот файл в файл gitignore, где этот файл не должен был быть отслеживается в первую очередь, тогда в этом случае все будет в порядке.
@ JoeMoe1984 git reset не работает с пустыми репозиториями (начальный импорт)
@BarryKelly Я пытался отредактировать свой комментарий, когда перечитывал ваш, но опоздал. Я пропустил ту часть того, что вы написали;). Но да, вы правы, это еще один пример использования git rm --cached
При первоначальном заполнении репозитория git "git reset" из верхнего ответа не работает: не удалось разрешить HEAD. Мы добавили слишком много одного файла к первоначальной фиксации. Как следует из этого ответа, в этом случае у меня работает «git rm --cached <file>». Может быть, "git rm --cached." делает больше, чем предназначено для некоторых людей, но (как предполагает git status) git rm --cached <file> работает ....
Почему бы просто не удалить скрытую папку .git lol .. и снова выполнить git init ... (при условии, что вы делаете репозиторий git в ПЕРВЫЙ раз и не выполняете никаких коммитов)
Если файлы еще не в индексе, используйте git rm --cache <filename>
, если файлы уже в индексе, но вы не хотите, чтобы они были в этой фиксации, используйте git reset <filename>
Возможно, это было применимо на момент написания, но, похоже, сейчас работает.
Это тоже неправильный ответ. Я не знаю, почему люди публикуют ответы, и тем более почему они голосуют за неправильные ответы ...
Эта команда ОЧИЩАЕТ / УДАЛЯЕТ МАТЕРИАЛЫ В ИНДЕКСЕ. На самом деле ОП и другие люди хотят ОТМЕНИТЬ ИЗМЕНЕНИЯ В ИНДЕКСЕ, а НЕ УДАЛИТЬ МАТЕРИАЛЫ. Сброс Git. это правильный ответ.
@ahnbizcad ... ну, когда вы знаете, что делаете, это намного проще ... и я считаю, что графический интерфейс слишком раздут и слишком много движений мыши ... так что это вопрос вашего мнения.
Я только что обнаружил, что есть git reset -p, как и git add -p. Это круто!
Если вы наберете:
git status
Git сообщит вам, что находится в постановке и т. Д., Включая инструкции по отключению:
use "git reset HEAD <file>..." to unstage
Я считаю, что Git неплохо подталкивает меня к правильным поступкам в подобных ситуациях.
Примечание. Последние версии Git (1.8.4.x) изменили это сообщение:
(use "git rm --cached <file>..." to unstage)
Сообщение будет отличаться в зависимости от того, отслеживался ли уже файл add
ed (add
только сохранил новую версию в кеше - здесь будет отображаться ваше сообщение). В другом месте, если файл ранее не создавался, будет отображаться use "git rm --cached <file>..." to unstage
Большой! git reset HEAD <file>
- единственный, который будет работать, если вы хотите отключить удаление файла.
Моя версия git 2.14.3 говорит, что git reset HEAD
отключить.
Начиная с Git v2.23 сообщение снова изменилось. Теперь там написано git restore --staged <file>
. См. Мой ответ ниже для получения обновлений.
git remove
или git rm
с флагом --cached
. Попробуйте:
git help rm
Разве это не удалит файл полностью?
git rm --cached ...
удалит файлы из репозитория git. Они по-прежнему будут существовать на вашем компьютере, но это ОЧЕНЬ отличается от неустановленных изменений в файл. Для тех, кто наткнулся на это, это неверный ответ на вопрос.
Начиная с Git v1.8.4, все ответы ниже, в которых используется
HEAD
илиhead
, теперь могут использовать@
вместоHEAD
. См. этот ответ (последний раздел), чтобы узнать, почему вы можете это сделать.Я сделал небольшое резюме, в котором показаны все способы деактивации файла: coderhelper.com/questions/6919121/…
@ErikReppen
git checkout
не удаляет поэтапные изменения из индекса фиксации. Он только возвращает неустановленные изменения к последней зафиксированной ревизии - что, кстати, тоже не то, что я хочу, я хочу эти изменения, я просто хочу, чтобы они были в более позднем коммите.Если вы используете Eclipse, это так же просто, как снять отметку с файлов в диалоговом окне фиксации.
Это отличный ресурс прямо из Github: Как отменить (почти) что угодно с Git
Прежде чем опубликовать новый ответ, подумайте, что на этот вопрос уже есть более 25 ответов. Убедитесь, что ваш ответ соответствует тому, чего нет среди существующих ответов
Я хотел бы проголосовать за это каждый раз, когда мне нужно вернуться сюда, чтобы сослаться на это
git удалить myfile.txt
Я всегда выполняю эту работу, используя
git reset <file_name>
. Для получения дополнительной информации обязательно ознакомьтесь с этой статьей.если читателям нравится использовать графический интерфейс, вы можете щелкнуть файл правой кнопкой мыши и нажать сбросить или отключить
git rm --cached <file>
отключает и отключает (помечено для удаления при следующей фиксации) данный файл, в то время какgit reset HEAD <file>
просто отключает файл