Как удалить из индекса git
Перейти к содержимому

Как удалить из индекса git

  • автор:

Как полностью убрать файлы из .git репозитория?

Когда файлы были добавлены в репозиторий и перестали быть нужны, то их можно оттуда убрать. Но недостаточно просто взять и добавить файлы в .gitignore файл. Даже в этом случае файлы остаются в кэше репозитория в прошлых коммитах. Чтобы убрать файлы и из кеша нужно сделать следующие шаги:

1 шаг. Закоммитить все изменения

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

2 шаг. Удалить файлы из кэша репозитория

Допустим, мы хотим удалить файл scripts.js, который каждый раз собирается автоматически из исходных файлов.

Чтобы убрать его из репозитория необходимо выполнить следующую команду:

Как отменить git add в Git

Чтобы отменить выполнение команды git add необходимо выполнить команду:

git reset

Данная команда удалит из индекса все файлы (которые были добавлены в индекс командой git add ).

Если необходимо удалить из индекса только один файл, то после git reset необходимо указать путь до данного файла (вместо myfile.cpp укажите свой файл):

git reset myfile.cpp

Пример

Например, вы выполнили команду git add . и в результате добавили в индекс 2 файла:

$ git add . $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD . " to unstage) modified: myfile1.cpp modified: myfile2.cpp

Теперь вы хотите удалить из индекса один из файлов, например файл myfile2.cpp. Для этого необходимо выполнить команду:

$ git reset myfile2.cpp Unstaged changes after reset: M myfile2.cpp $ git status On branch master Your branch is up-to-date with 'origin/master'. Changes to be committed: (use "git reset HEAD . " to unstage) modified: myfile1.cpp Changes not staged for commit: (use "git add . " to update what will be committed) (use "git checkout -- . " to discard changes in working directory) modified: myfile2.cpp

Как вы можете видеть, файл myfile2.cpp был удален из индекса и попал в список «Changes not staged for commit».

Смотрите также:

  • Как изменить файлы в старом коммите (не последнем)
  • Как добавить все файлы в коммит, кроме одного
  • Как создать ветку из предыдущего коммита
  • Команда Git stash. Как прятать изменения в Git
  • Как показать файлы, которые будут добавлены в текущий коммит
  • Как клонировать репозиторий
  • Как посмотреть ветки
  • Как переключиться на ветку
  • Как удалить ветку
  • Как переименовать ветку
  • Опубликовано: 09.09.2018
  • yuriy

Удалить файл из репозитория Git, не удаляя его локально

Git стал широко используемой распределенной системой контроля версий. В этом руководстве мы рассмотрим, как удалить файл или каталог из репозитория Git, но сохранить его локальную копию.

2. Введение в проблему​

Как обычно, давайте разберемся с проблемой на примере. Допустим, мы работаем с репозиторием Git myRepo :

 $ ls -l  total 12  drwxr-xr-x 2 kent kent 60 May 12 23:00 logs/ -rw-r--r-- 1 kent kent 26 May 11 13:22 README.md -rw-r--r-- 1 kent kent 21 May 11 13:22 some-file.txt -rw-r--r-- 1 kent kent 16 May 12 22:40 user-list.txt 

Мы клонировали репозиторий на локальный, и, как видно из вывода ls , у нас есть три файла и каталог журналов в репозитории.

Теперь предположим, что мы хотели бы удалить файл user-list.txt и каталог журналов из репозитория Git. Однако мы не хотим удалять их из нашей локальной рабочей копии.

Обычный сценарий: мы зафиксировали некоторые файлы или каталоги, а затем поняли, что должны игнорировать некоторые файлы. Поэтому мы удалим связанные файлы из репозитория, сохраним локальные копии и добавим соответствующие шаблоны в файл .gitignore , чтобы Git больше не отслеживал эти файлы.

Мы знаем, что команда git rm user-list.txt удалит файл из репозитория. Но он также удаляет локальный файл.

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

Далее, давайте посмотрим, как решить эту проблему более эффективно.

3. Использование команды git rm –cached​

Мы упоминали, что git rm FILE по умолчанию удалит файлы из индекса и локального рабочего дерева .

Однако команда git rm предоставляет параметр –cached , позволяющий нам удалять файлы только из индекса репозитория и оставлять локальный файл нетронутым.

Далее попробуем с файлом user-list.txt :

 $ git rm --cached user-list.txt  rm 'user-list.txt' 

Как видно из приведенного выше вывода, файл user-list.txt был удален. Итак, теперь давайте выполним команду git status , чтобы проверить это:

 $ git status On branch master Your branch is up to date with 'origin/master'.   Changes to be committed:  (use "git restore --staged . " to unstage)   deleted: user-list.txt  Untracked files:  (use "git add . " to include in what will be committed)   user-list.txt 

Как мы видим, файл user-list.txt « удален ». Кроме того, поскольку его локальная копия все еще существует, он помечен как «неотслеживаемый».

Аналогичным образом мы можем удалить каталог журналов . Однако, поскольку это каталог, нам нужно дополнительно передать параметр -r (рекурсивно) команде git rm :

 $ git rm --cached -r logs  rm 'logs/server.log' 

Теперь давайте зафиксируем наши изменения:

 $ git commit -m 'remove user-list.txt and logs'   [master ee8cfe8] remove user-list.txt and logs  2 files changed, 4 deletions(-)   delete mode 100644 logs/server.log  delete mode 100644 user-list.txt 

Затем давайте проверим текущие подготовленные файлы с помощью команды git ls-files :

 $ git ls-files -c  .gitignore README.md some-file.txt 

Как видно из вывода, целевого файла и каталога больше нет. Кроме того, сохраняются локальные копии. Таким образом, мы решили проблему.

При желании мы можем добавить их в файл .gitignore , чтобы Git больше не мог их отслеживать.

4. Удалите все файлы, определенные в .gitignore ​

Иногда мы хотим проверить индекс Git и удалить все файлы, определенные в .gitignore . Предположим, что мы закончили с нашим определением .gitignore . Тогда простым способом будет трехэтапный процесс:

  • Сначала удалите все файлы из индекса: git rm -r –cached
  • Затем снова подготовьте все файлы. Файлы, определенные в .gitignore , будут автоматически игнорироваться: git add
  • Зафиксируйте наши изменения: git commit -m «правильное сообщение фиксации»

В качестве альтернативы мы можем найти и удалить только те файлы, которые в настоящее время отслеживаются, но их следует игнорировать . Команда git ls-files может помочь нам найти файлы.

Давайте вернем нашу предыдущую фиксацию и снова удалим файл user-list.txt и каталог журналов . На этот раз давайте сначала добавим их в файл .gitignore :

 $ cat .gitignore user-list.txt logs/ 

Далее давайте выясним, какие файлы мы хотели бы удалить из индекса Git:

 $ git ls-files -i -c -X .gitignore logs/server.log user-list.txt 

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

Теперь давайте объединим команды git rm –cached и git ls-files , чтобы удалить их одним выстрелом :

 $ git rm --cached $(git ls-files -i -c -X .gitignore)   rm 'logs/server.log'   rm 'user-list.txt' 

Стоит отметить, что команда удалит все файлы в каталоге журналов , поэтому, наконец, она удалит пустой каталог журналов из индекса. Итак, в этом примере у нас есть только один файл в каталоге журналов .

Теперь, если мы проверим поставленные файлы, удаленные исчезнут:

 $ git ls-files -c  .gitignore README.md some-file.txt 

И, конечно же, user-list.txt и logs/ все еще находятся в нашем локальном рабочем дереве:

 $ ls -l  total 12  drwxr-xr-x 2 kent kent 60 May 13 00:45 logs/ -rw-r--r-- 1 kent kent 26 May 11 13:22 README.md -rw-r--r-- 1 kent kent 21 May 11 13:22 some-file.txt -rw-r--r-- 1 kent kent 16 May 13 00:45 user-list.txt 

5. Удаленные файлы остаются в истории Git​

Мы решили нашу проблему с помощью команды git rm –cached . Однако мы должны помнить, что мы просто удалили файл из индекса отслеживания Git . Мы по-прежнему можем видеть файл и его содержимое в истории коммитов Git. Например, мы все еще можем увидеть содержимое user-list.txt , проверив предыдущую фиксацию:

 $ git show 668fa2f user-list.txt commit 668fa2f... Author: ... Date: ...   add user-list.txt and some-file.txt   diff --git a/user-list.txt b/user-list.txt new file mode 100644  index 0000000..3da7fab --- /dev/null +++ b/user-list.txt @@ -0,0 +1,3 @@ +kent +eric +kevin 

Знать это важно, поскольку иногда мы забываем добавить некоторые конфиденциальные файлы в файл .gitingore , например учетные данные. Но мы зафиксировали их и отправили изменения в удаленный репозиторий. После того, как мы это осознаем, мы можем полностью стереть конфиденциальные файлы из истории Git.

6. Заключение​

В этой статье мы показали, как удалить файл или каталог из репозитория Git, но сохранить его локальную копию на примерах.

Кроме того, мы рассмотрели быстрый способ удаления всех файлов, определенных в файле .gitignore . Наконец, мы должны помнить, что файлы, удаленные git rm –cached, все еще живут в истории коммитов Git.

  • 1. Обзор
  • 2. Введение в проблему
  • 3. Использование команды git rm –cached
  • 4. Удалите все файлы, определенные в .gitignore
  • 5. Удаленные файлы остаются в истории Git
  • 6. Заключение

2.4 Основы Git — Операции отмены

В любой момент вам может потребоваться что-либо отменить. Здесь мы рассмотрим несколько основных способов отмены сделанных изменений. Будьте осторожны, не все операции отмены в свою очередь можно отменить! Это одна из редких областей Git, где неверными действиями можно необратимо удалить результаты своей работы.

Отмена может потребоваться, если вы сделали коммит слишком рано, например, забыв добавить какие-то файлы или комментарий к коммиту. Если вы хотите переделать коммит — внесите необходимые изменения, добавьте их в индекс и сделайте коммит ещё раз, указав параметр —amend :

$ git commit --amend

Эта команда использует область подготовки (индекс) для внесения правок в коммит. Если вы ничего не меняли с момента последнего коммита (например, команда запущена сразу после предыдущего коммита), то снимок состояния останется в точности таким же, а всё что вы сможете изменить — это ваше сообщение к коммиту.

Запустится тот же редактор, только он уже будет содержать сообщение предыдущего коммита. Вы можете редактировать сообщение как обычно, однако, оно заменит сообщение предыдущего коммита.

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

$ git commit -m 'Initial commit' $ git add forgotten_file $ git commit --amend

В итоге получится единый коммит — второй коммит заменит результаты первого.

Примечание

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

Очевидно, смысл изменения коммитов в добавлении незначительных правок в последние коммиты и, при этом, в избежании засорения истории сообщениями вида «Ой, забыл добавить файл» или «Исправление грамматической ошибки».

Отмена индексации файла

Следующие два раздела демонстрируют как работать с индексом и изменениями в рабочем каталоге. Радует, что команда, которой вы определяете состояние этих областей, также подсказывает вам как отменять изменения в них. Например, вы изменили два файла и хотите добавить их в разные коммиты, но случайно выполнили команду git add * и добавили в индекс оба. Как исключить из индекса один из них? Команда git status напомнит вам:

$ git add * $ git status On branch master Changes to be committed: (use "git reset HEAD . " to unstage) renamed: README.md -> README modified: CONTRIBUTING.md

Прямо под текстом «Changes to be committed» говорится: используйте git reset HEAD …​ для исключения из индекса. Давайте последуем этому совету и отменим индексирование файла CONTRIBUTING.md :

$ git reset HEAD CONTRIBUTING.md Unstaged changes after reset: M CONTRIBUTING.md $ git status On branch master Changes to be committed: (use "git reset HEAD . " to unstage) renamed: README.md -> README Changes not staged for commit: (use "git add . " to update what will be committed) (use "git checkout -- . " to discard changes in working directory) modified: CONTRIBUTING.md

Команда выглядит несколько странно, но — работает! Файл CONTRIBUTING.md изменен, но больше не добавлен в индекс.

Примечание

Команда git reset может быть опасной если вызвать её с параметром —hard . В приведённом примере файл не был затронут, следовательно команда относительно безопасна.

На текущий момент этот магический вызов — всё, что вам нужно знать о команде git reset . Мы рассмотрим в деталях что именно делает reset и как с её помощью делать действительно интересные вещи в разделе Раскрытие тайн reset главы 7.

Отмена изменений в файле

Что делать, если вы поняли, что не хотите сохранять свои изменения файла CONTRIBUTING.md ? Как можно просто отменить изменения в нём — вернуть к тому состоянию, которое было в последнем коммите (или к начальному после клонирования, или ещё как-то полученному)? Нам повезло, что git status подсказывает и это тоже.

В выводе команды из последнего примера список изменений выглядит примерно так:

Changes not staged for commit: (use "git add . " to update what will be committed) (use "git checkout -- . " to discard changes in working directory) modified: CONTRIBUTING.md

Здесь явно сказано как отменить существующие изменения. Давайте так и сделаем:

$ git checkout -- CONTRIBUTING.md $ git status On branch master Changes to be committed: (use "git reset HEAD . " to unstage) renamed: README.md -> README

Как видите, откат изменений выполнен.

Важно понимать, что git checkout — — опасная команда. Все локальные изменения в файле пропадут — Git просто заменит его версией из последнего коммита. Ни в коем случае не используйте эту команду, если вы не уверены, что изменения в файле вам не нужны.

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

Помните, всё что попало в коммит почти всегда Git может восстановить. Можно восстановить даже коммиты из веток, которые были удалены, или коммиты, перезаписанные параметром —amend (см. Восстановление данных). Но всё, что не было включено в коммит и потеряно — скорее всего, потеряно навсегда.

Отмена действий с помощью git restore

Git версии 2.23.0 представил новую команду: git restore . По сути, это альтернатива git reset, которую мы только что рассмотрели. Начиная с версии 2.23.0, Git будет использовать git restore вместо git reset для многих операций отмены.

Давайте проследим наши шаги и отменим действия с помощью git restore вместо git reset .

Отмена индексации файла с помощью git restore

В следующих двух разделах показано, как работать с индексом и изменениями рабочей копии с помощью git restore . Приятно то, что команда, которую вы используете для определения состояния этих двух областей, также напоминает вам, как отменить изменения в них. Например, предположим, что вы изменили два файла и хотите зафиксировать их как два отдельных изменения, но случайно набираете git add * и индексируете их оба. Как вы можете убрать из индекса один из двух? Команда git status напоминает вам:

$ git add * $ git status On branch master Changes to be committed: (use "git restore --staged . " to unstage) modified: CONTRIBUTING.md renamed: README.md -> README

Прямо под текстом «Changes to be committed», написано использовать git restore —staged …​ для отмены индексации файла. Итак, давайте воспользуемся этим советом, чтобы убрать из индекса файл CONTRIBUTING.md :

$ git restore --staged CONTRIBUTING.md $ git status On branch master Changes to be committed: (use "git restore --staged . " to unstage) renamed: README.md -> README Changes not staged for commit: (use "git add . " to update what will be committed) (use "git restore . " to discard changes in working directory) modified: CONTRIBUTING.md

Файл CONTRIBUTING.md изменен, но снова не индексирован.

Откат изменённого файла с помощью git restore

Что, если вы поймете, что не хотите сохранять изменения в файле CONTRIBUTING.md ? Как легко его откатить — вернуть обратно к тому, как он выглядел при последнем коммите (или изначально клонирован, или каким-либо образом помещён в рабочий каталог)? К счастью, git status тоже говорит, как это сделать. В выводе последнего примера, неиндексированная область выглядит следующим образом:

Changes not staged for commit: (use "git add . " to update what will be committed) (use "git restore . " to discard changes in working directory) modified: CONTRIBUTING.md

Он довольно недвусмысленно говорит, как отменить сделанные вами изменения. Давайте сделаем то, что написано:

$ git restore CONTRIBUTING.md $ git status On branch master Changes to be committed: (use "git restore --staged . " to unstage) renamed: README.md -> README

Важно понимать, что git restore — опасная команда. Любые локальные изменения, внесённые в этот файл, исчезнут — Git просто заменит файл последней зафиксированной версией. Никогда не используйте эту команду, если точно не знаете, нужны ли вам эти несохранённые локальные изменения.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *