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


Я ошибочно добавил файлы в git, используя команду:

git add myfile.txt

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


На данный момент существует 48 ответов (некоторые удалены). Не добавляйте новую, если у вас нет новой информации.


7339


источник


Ответы:


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

git reset <file>

который удалит его из текущего индекса (список «about to be commit») без изменения чего-либо еще.

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

git reset

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

В старых версиях Git приведенные выше команды эквивалентны git reset HEAD <file>а также git reset HEADсоответственно, и не удастся, если HEAD(поскольку вы еще не сделали никаких коммитов в своем репо) или неоднозначно (потому что вы создали ветвь, называемую HEAD, что глупо, чего вы не должны делать). Эта был изменен в Git 1.8.2 , тем не менее, поэтому в современных версиях Git вы можете использовать вышеприведенные команды еще до того, как сделаете свою первую фиксацию:

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


8220



Вы хотите:

git rm --cached <added_file_to_undo>

Обоснование:

Когда я был новым, я сначала попробовал

git reset .

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

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

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

  1. cd в мой новый новый каталог проектов, чтобы опробовать Git, новую горячку
  2. git init
  3. git add .
  4. git status

    ... множество свитков с дерьмом ...

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

  5. google "undo git add"

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

  6. git reset .

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

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

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

...
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
...

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

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

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

Я приступаю к использованию

git rm --cached .

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

git rm -r --cached .

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

git add -n .

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


1940



Если вы наберете:

git status

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

use "git reset HEAD <file>..." to unstage

Я считаю, что git делает довольно хорошую работу, подталкивая меня к тому, чтобы делать правильные вещи в подобных ситуациях.

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

(use "git rm --cached <file>..." to unstage)

481



Чтобы уточнить: 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

220



В дополнение к принятому ответу, если ваш ошибочно добавленный файл был огромным, вы, вероятно, заметите, что даже после его удаления из индекса с помощью ' git reset', он все еще, кажется, занимает пространство в .gitкаталог. Это не о чем беспокоиться, файл действительно находится в репозитории, но только как «свободный объект», он не будет скопирован в другие репозитории (через clone, push), и пространство будет в конечном итоге возвращено - хотя возможно, не очень скоро. Если вы беспокоитесь, вы можете запустить:

git gc --prune=now

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

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

git reset HEAD <file>?

или

git rm --cached <file>?

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

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

Напомним сначала, что git add <file>фактически делает:

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

  2. Если <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 lost irrevocably "version 2"
-version 1
+version 3

Конечно, это не очень важно, если мы просто следуем обычному ленивому рабочему процессу «git add» только для добавления новых файлов (случай 1), и мы обновляем новое содержимое через commit, git commit -aкоманда.


136



git rm --cached . -r

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


85



Run

git gui

and remove all the files manually or by selecting all of them and clicking on the unstage from commit button.


76



Git has commands for every action imaginable, but needs extensive knowledge to get things right and because of that it is counter-intuitive at best...

What you did before:

  • Changed a file and used git add ., or git add <file>.

What you want:

  • Remove the file from the index, but keep it versioned and left with uncommitted changes in working copy:

    git reset head <file>
    
  • Reset the file to the last state from HEAD, undoing changes and removing them from the index:

    # Think `svn revert <file>` IIRC.
    git reset HEAD <file>
    git checkout <file>
    
    # If you have a `<branch>` named like `<file>`, use:
    git checkout -- <file>
    

    This is needed since git reset --hard HEAD won't work with single files.

  • Remove <file> from index and versioning, keeping the un-versioned file with changes in working copy:

    git rm --cached <file>
    
  • Remove <file> from working copy and versioning completely:

    git rm <file>
    

73