git rm и git mv: удалить и переименовать под присмотром git

Обновлено 31 июля 2026 г.

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

$ git rm draft.txt
rm 'draft.txt'
$ git status --short
D  draft.txt

Буква D в первом столбце значит, что удаление уже лежит в индексе и уйдёт в следующий коммит. Файла на диске больше нет. Переименование выглядит так:

$ git mv old.txt new.txt
$ git status --short
R  old.txt -> new.txt

Удалить или переименовать файл можно и обычными средствами системы: командой rm, командой mv, мышкой в файловом менеджере. Git это заметит, но изменение останется вне индекса:

$ mv new.txt renamed.txt
$ git status --short
 D new.txt
?? renamed.txt

Пробел в первом столбце значит «в индексе пусто», ?? - неотслеживаемый файл. Один git add с флагом -A приводит всё в порядок, и git сам сводит пару в переименование:

$ git add -A
$ git status --short
R  new.txt -> renamed.txt

Так что git rm и git mv - это сокращение на один шаг, а не отдельный механизм внутри git.

Переименований git не хранит

Записи «этот файл переименовали» в коммите нет. Коммит хранит снимок целиком, а R old.txt -> new.txt в выводе - догадка, которую git делает на лету: он сравнивает содержимое исчезнувшего и появившегося файла и, если совпадение достаточно велико, показывает их как пару. Отсюда следствие: переименуешь файл и заодно перепишешь половину строк - git покажет удаление одного файла и добавление другого. История от этого не портится, просто читается хуже. Переименование и правку содержимого лучше разносить по разным коммитам.

git rm --cached: снять с наблюдения, оставить на диске

Ради этого команду чаще всего и ищут. Флаг --cached убирает файл из индекса, не трогая его на диске:

$ git rm --cached config.env
rm 'config.env'
$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	deleted:    config.env

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	config.env

Один и тот же файл значится и удалённым (так это видит git), и неотслеживаемым (он лежит на диске). Дальше добавляешь его имя в .gitignore и коммитишь оба изменения вместе. Так поступают, когда в репозиторий случайно попал секрет или каталог зависимостей: для каталога нужен ещё -r, то есть git rm -r --cached node_modules.

Частые ошибки

git rm --cached не убирает секрет из истории. Прошлые коммиты хранят прошлые снимки целиком, и коммит, в котором ключ ещё лежал, никуда не делся: любой, у кого есть копия репозитория, достанет его командой git show <хеш>:config.env. Ключ, побывавший в истории, считается утёкшим, и правильная реакция - перевыпустить его, а не вычищать файл.

git rm на файле с несохранёнными правками откажется работать и подскажет выход:

$ git rm report.txt
error: the following file has local modifications:
    report.txt
(use --cached to keep the file, or -f to force removal)

Каталог целиком удаляется только с -r. Без флага git отвечает fatal: not removing 'docs' recursively without -r.

Где это в учебнике

Индекс и .gitignore разобраны здесь: Глава 4. Посмотреть, отменить, спрятать лишнее.

Потренироваться руками - в интерактивном уроке Отмена изменений.