Как удалить untracked-файлы в Git: безопасный git clean
Как безопасно удалить untracked-файлы в Git: сначала git clean -nd, потом -fd для каталогов и -x для игнорируемых — и почему clean ничего не удаляет.
TL;DR: чтобы удалить untracked-файлы в git, выполните git clean -fd — но сначала всегда смотрите превью через git clean -nd, потому что clean удаляет навсегда: ни корзины, ни отката. -f — для файлов, -fd — для файлов и каталогов, -fdx — если заодно должен уйти игнорируемый build-выход. Самая частая жалоба — «git clean не удаляет мои untracked-файлы» — почти всегда означает, что файлы лежат внутри untracked-каталога (добавьте -d) или это игнорируемые файлы (добавьте -x). Untracked-мусор — нормальный побочный продукт экспериментов, сборок и скриптов рядом с клоном; этот гайд показывает, как посмотреть превью каждого удаления, вычистить одну директорию и какие комбинации никогда не запускать в репозитории, который вам дорог.
Что такое untracked-файлы в git status?
Untracked значит, что git видит файл на диске, но его никто не просил отслеживать — файла нет в индексе и нет в истории коммитов. git status раскладывает всё по трём корзинам:
$ git status --short
M src/app.ts # изменён: отслеживаемый, есть правки
?? notes.txt # untracked: новый файл, git о нём не знает
?? build/ # untracked-каталог: для git совершенно новый
Это различие важно, потому что каждой корзине нужен свой инструмент удаления. Отслеживаемые, но изменённые файлы откатываются через git restore или просто коммитятся — git clean их не тронет. Территория git clean — только строки с ??. Игнорируемые файлы (всё, что матчится с .gitignore) — скрытая четвёртая корзина: они даже не показываются как ??, и git clean их пропускает, пока вы явно не включите -x.
Если ваша реальная проблема — отслеживаемый файл, который вообще не следовало коммитить, чистка тут не поможет: это работа для git rm --cached или отката последнего коммита, как разобрано в git undo last commit: keep the changes.
Как удалить все untracked-файлы и папки в git?
Базовая команда — git clean -f. Без -f git откажется что-либо удалять и просто напечатает предупреждение — это сознательная страховка. Полный ритуал выглядит так:
# 1. Посмотрите, что именно будет удалено (dry run — ничего не удаляет)
git clean -nd
# Будет удалено:
# notes.txt
# build/
# scratch/
# 2. Убедитесь, что в списке нет ценного, и удаляйте по-настоящему
git clean -fd
Разбираем флаги:
-f/--force— обязателен. Реально удаляет untracked-файлы.-d— рекурсивно спускается в untracked-каталоги. Голый-fубирает только untracked-файлы верхнего уровня и честно сообщает про каталоги, которые отказался трогать.-n/--dry-run— показывает, что было бы удалено. Всегда запускайте первым.-x— заодно удаляет игнорируемые файлы (node_modules, build-выход,.env).-X— удаляет только игнорируемые файлы, оставляя untracked, но не игнорируемые.-i— интерактивный режим; выручает, когда список из dry-run длинный.
Привычка, которую стоит скопировать: относитесь к git clean -nd как к git diff — перед коммитом вы смотрите diff, перед чисткой смотрите список.
Почему git clean не удаляет мои untracked-файлы?
Три реальные причины, по убыванию частоты:
1. Файлы лежат внутри untracked-каталога. С одним лишь -f git удаляет одиночные untracked-файлы, но останавливается перед каталогами — даже печатает Would remove build/, не удаляя его по-настоящему. Добавьте -d:
git clean -fd
2. Файлы в gitignore. node_modules/, dist/, .venv/ — игнорируемые пути для обычного clean невидимы. Их нет в dry-run, и clean их не удалит. Включайте явно:
git clean -fdx # untracked + игнорируемые файлы и каталоги
3. На пути вложенный git-репозиторий или сабмодуль. Git никогда не удаляет содержимое чужого репозитория снаружи. Правильно удалите сабмодуль или передайте --force дважды (git clean -ffd) — но первый вариант лучше.
Если dry-run не показывает ничего, а git status всё ещё содержит ??, вы, скорее всего, не в том рабочем дереве — выполните git rev-parse --show-toplevel и проверьте, что находитесь внутри того репозитория, который собирались чистить.
Как удалить untracked-файлы только из одной директории?
Ограничьте чистку путём — всё остальное останется нетронутым:
git clean -fd build/ # только внутри build/
git clean -fd src/generated # одно конкретное дерево
Это ответ на «хочу вычистить untracked-файлы и папки в build/, но сохранить свои черновые заметки в корне репозитория». Путь относительный: запустили из корня — чистится весь репозиторий, из подкаталога — это поддерево.
Как убрать untracked-файлы, не удаляя их?
Когда dry-run показывает файлы, которые могут пригодиться позже, не играйте в рулетку — сначала сохраните, потом чистите:
# Убираем untracked-файлы в stash (игнорируемые тоже — с -a) без удаления
git stash push --include-untracked
git clean -fd # дерево чистое
git stash pop # вернуть, когда понадобятся
git stash -u выносит untracked-файлы из дерева, но оставляет их восстановимыми — это те самые «удалить, не удаляя», которые люди на самом деле ищут. А для превью, которое останется под рукой, git clean -nd > clean-plan.txt даёт точный список до всяких необратимых шагов. Отмены после git clean -f не существует: удалённое — удалено.
git clean vs git rm vs git restore: что и когда?
| Команда | Затрагивает | Удаляет с диска | Когда использовать |
|---|---|---|---|
git clean -fd |
Untracked-файлы/каталоги | Да | Удалить файлы, которые git никогда не отслеживал |
git clean -fdx |
Untracked + игнорируемые | Да | Полный сброс: включая node_modules, build-выход |
git rm <file> |
Отслеживаемые файлы | Да (stage + диск) | Удалить файл и записать удаление в git |
git rm --cached <file> |
Отслеживаемые файлы | Нет | Перестать отслеживать файл, оставив его на диске |
git restore <file> |
Отслеживаемые файлы | Нет | Отменить локальные правки, файл оставить |
Правило в одну строку: clean управляет тем, о чём git не знает; rm и restore — тем, о чём знает. Путаница между ними и стоит людям работы: достаточно запустить git clean -fdx, будучи уверенным, что это ведёт себя как git restore.
Что никогда не стоит чистить через git clean?
Две привычки, которые надо вычеркнуть сразу:
- Никогда не запускайте
git clean -fdxвслепую в монорепозитории или воркспейсе. Он удаляет каждый игнорируемый каталог — это всеnode_modules, все виртуальные окружения, все локальные.envв дереве. Восстановление может обойтись в час переустановок, а удалённый.envможет не восстановиться вообще. - Никогда не делайте алиас для clean с вшитым force.
git config alias.wipe "clean -fd"ощущается эффективным, пока вы не опечатаетесь в пути. Держите dry-run в одном нажатии (git clean -nd) и превратите чистку в ритуал из двух команд: сначала превью, потом удаление.
Кстати: чистка untracked-файлов прямо перед пуллом уменьшает поверхность слияния — а аккуратное дерево, самая дешёвая страховка от конфликтов, делается по шагам за один вечер.
Безопасный workflow git clean: кратко
git status --short # что лежит в дереве?
git clean -nd # превью: что БЫЛО бы удалено?
git clean -fd # удалить untracked-файлы + каталоги
git clean -fdX # (опционально) снести только игнорируемый build-выход
git status --short # проверка: рабочее дерево чистое
Превью, удаление, проверка — тридцать секунд, ноль сожалений, и git status наконец снова читается как «чисто».