- Git
git cleanの使い方|未追跡ファイル削除と変更を全部取り消す手順
git cleanとは、Gitがまだ追跡していないファイル(未追跡ファイル)を作業ツリーから削除するコマンドです。 まず git clean -nd で消える対象を確認し、問題がなければ git clean -fd で削除する、という2手が基本の流れです。
この記事では、同じ作業ツリーに対してオプションの組み合わせを1つずつかけ、表示された「Would remove ...」をそのまま並べて比較しています。さらに「変更を全部取り消したい」という場面を、追跡済みファイル(git restore . / git reset --hard)と未追跡ファイル(git clean -fd)の2段に分けて整理しました。git cleanで消したファイルはreflogからも戻せないため、消す前に git stash -u で退避しておく手順も載せています。出力はすべて Git 2.43.0 で実行したものです。
git cleanの早見表
やりたいこと別のコマンド
| やりたいこと | コマンド | 補足 |
|---|---|---|
| 消える対象を確認する(何も消さない) | git clean -n |
未追跡ファイルだけを表示 |
| フォルダも含めて確認する | git clean -nd |
最初に打つのはこれ |
| 未追跡ファイルを削除する | git clean -f |
未追跡フォルダは残る |
| 未追跡ファイルとフォルダを削除する | git clean -fd |
最もよく使う形 |
| .gitignore の対象も含めて全部削除する | git clean -fdx |
node_modules や .env も消える |
| .gitignore の対象だけを削除する | git clean -fdX |
ビルド成果物だけ消したいとき |
| 一部を残して削除する | git clean -fd -e memo.txt |
-e は何回でも書ける |
| 特定のフォルダの中だけ削除する | git clean -fd src |
パスを最後に付ける |
| 選びながら削除する | git clean -id |
対話モード |
| 中に .git を持つフォルダも削除する | git clean -ffd |
-f を2回 |
| 変更を全部取り消す(コミット直後の状態へ) | git reset --hard → git clean -fd |
2段で行う |
| 消す前に退避する | git stash push -u |
後から git stash pop で戻せる |
オプション一覧
| オプション | 意味 | 単独で使ったとき |
|---|---|---|
-n(--dry-run) |
削除せず、対象だけ表示する | 動く(-f 不要) |
-f(--force) |
実際に削除する | 動く |
-d |
未追跡フォルダの中まで対象にする | -f か -n が必要 |
-x |
.gitignore などの無視ルールを使わず、無視ファイルも対象にする | -f か -n が必要 |
-X(大文字) |
無視されているファイルだけを対象にする | -f か -n が必要 |
-i(--interactive) |
対話モードで選んで削除する | 動く(-f 不要) |
-e <パターン>(--exclude) |
指定パターンを削除対象から外す | -f か -n が必要 |
-q(--quiet) |
削除したファイル名を表示しない | -f が必要 |
-ff |
中に .git を持つ未追跡フォルダも削除する | 動く |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「git cleanの使い方|未追跡ファイル削除と変更を全部取り消す手順」
検証に使った作業ツリー
以降の出力は、すべて次の作業ツリーで実行したものです。コピーして同じ状態を作れます。
git --version
# git version 2.43.0
mkdir demo && cd demo
git init -q -b main .
git config user.name taro
git config user.email taro@example.com
# 追跡済みファイル(コミットする)
mkdir src
echo 'console.log(1)' > src/app.js
echo '# demo' > README.md
printf 'node_modules/\n*.log\n.env\ndist/\n' > .gitignore
git add . && git commit -qm init
# 未追跡ファイル・フォルダ
echo memo > memo.txt
mkdir -p tmp/sub && echo a > tmp/a.txt && echo b > tmp/sub/b.txt
echo x > src/new.js
mkdir emptydir
# .gitignore に当たるファイル(無視ファイル)
echo log > debug.log
echo KEY=1 > .env
mkdir -p node_modules/pkg dist
echo m > node_modules/pkg/index.js
echo d > dist/bundle.js
# 中に .git を持つフォルダ(ネストしたリポジトリ)
mkdir -p vendor/lib && git init -q vendor/lib && echo v > vendor/lib/v.txt
この状態で git status -s --ignored を実行すると、次のように表示されます。
$ git status -s --ignored
?? memo.txt
?? src/new.js
?? tmp/
?? vendor/
!! .env
!! debug.log
!! dist/
!! node_modules/
?? が未追跡、!! が無視ファイルです。git cleanが何もオプションを付けないときに対象にするのは ?? の側だけで、!! の側は -x か -X を付けたときに初めて対象になります。空のフォルダ(emptydir)は git status には出ませんが、-d を付けた git clean の対象には入ります。
| 記号 | 状態 | git clean の対象になる条件 |
|---|---|---|
?? のファイル |
未追跡 | -f だけで対象 |
?? のフォルダ |
未追跡フォルダ | -d が必要 |
!! |
無視ファイル | -x または -X が必要 |
M / A など |
追跡済みの変更 | git clean では対象外(restore / reset を使う) |
オプションなしで実行すると止まる理由
何も付けずに git clean を実行すると、削除は行われずに止まります。
$ git clean
fatal: clean.requireForce defaults to true and neither -i, -n, nor -f given; refusing to clean
終了コードは 128 でした。これは設定 clean.requireForce の初期値が true で、-f・-n・-i のどれかを付けない限り削除しないという仕組みになっているためです。消したファイルを戻す方法がないコマンドなので、うっかり実行を防ぐための確認が最初から組み込まれています。
| 付けたオプション | 動き |
|---|---|
| なし | fatal で止まる(何も消えない) |
-n |
対象を表示するだけ |
-i |
対話モードで確認しながら進む |
-f |
削除する |
エラー文の文言は Git の版によって少し変わることがあります(ここに載せたのは 2.43.0 の表示です)。どの版でも、-f を付けると先へ進める点は同じです。
なお git config clean.requireForce false と設定すると -f なしでも削除されるようになります。今回 git -c clean.requireForce=false clean と一時的に指定して試したところ、Removing memo.txt と表示されて実際に削除されました。確認の一手が省かれてしまうので、この設定は初期値のままにしておくことをおすすめします。
オプションの組み合わせごとの出力比較
ここからは、上の作業ツリーに -n(dry-run)付きで各組み合わせをかけた結果です。-n を付けている間は何も消えないので、同じ状態のまま何度でも試せます。
-n:未追跡ファイルだけが対象
$ git clean -n
Would remove memo.txt
Would remove src/new.js
フォルダ(tmp/ や emptydir/)は出てきません。 すでに追跡済みのフォルダ src/ の中にある new.js は、ファイル単体として対象になっています。
-nd:未追跡フォルダも対象
$ git clean -nd
Would remove emptydir/
Would remove memo.txt
Would remove src/new.js
Would remove tmp/
Would skip repository vendor/lib
-d を付けると、tmp/ と空の emptydir/ が加わりました。tmp/ の中のファイルは1行ずつではなく、フォルダごと tmp/ とまとめて表示されます。最後の行 Would skip repository vendor/lib は、中に .git を持つフォルダは対象から外したという意味です(後の節で扱います)。
-nx:無視ファイルも対象
$ git clean -nx
Would remove .env
Would remove debug.log
Would remove memo.txt
Would remove src/new.js
-x は .gitignore のルールを使わないという指定です。未追跡ファイルに加えて、.env と debug.log が対象に入りました。-d がないので、node_modules/ や dist/ といったフォルダはまだ出てきません。
-ndx:未追跡も無視ファイルも、フォルダごと全部
$ git clean -ndx
Would remove .env
Would remove debug.log
Would remove dist/
Would remove emptydir/
Would remove memo.txt
Would remove node_modules/
Would remove src/new.js
Would remove tmp/
Would skip repository vendor/lib
追跡済みファイル以外がすべて対象になります。クローン直後に近い状態へ戻したいときの組み合わせです。.env のような手元だけの設定ファイルも消えるので、-n での確認がとくに役立ちます。
-nX と -ndX:無視ファイルだけが対象
$ git clean -nX
Would remove .env
Would remove debug.log
$ git clean -ndX
Would remove .env
Would remove debug.log
Would remove dist/
Would remove node_modules/
大文字の -X は、無視されているファイルだけを対象にします。memo.txt や tmp/ のような、自分で作った未追跡ファイルは残ります。ビルド成果物やキャッシュを消してビルドし直したいときに向いています。
-e:一部を対象から外す
$ git clean -nd -e memo.txt
Would remove emptydir/
Would remove src/new.js
Would remove tmp/
Would skip repository vendor/lib
$ git clean -ndx -e .env -e node_modules/
Would remove debug.log
Would remove dist/
Would remove emptydir/
Would remove memo.txt
Would remove src/new.js
Would remove tmp/
Would skip repository vendor/lib
-e で指定したパターンは、その場限りの .gitignore のように働きます。2つ目の例のように、-x と組み合わせると「全部消すが .env と node_modules だけは残す」という指定ができます。-e は複数回書けます。
パスを付ける:範囲を絞る
$ git clean -nd src
Would remove src/new.js
$ git clean -n tmp/
Would remove tmp/
$ git clean -n -- '*.txt'
Would remove memo.txt
Would remove tmp/a.txt
Would remove tmp/sub/b.txt
最後にパスを書くと、その範囲だけが対象になります。2つ目の例では、パスを指定したときは -d がなくてもフォルダ tmp/ が対象になりました。3つ目の例のようにパターンを指定した場合も、-d なしで tmp/ の中の a.txt や sub/b.txt まで届いています。パスやパターンを付けるときは、範囲が思ったより広がることがあるので、やはり -n で先に見ておくと安心です。
また、サブフォルダに移動してから実行すると、対象はそのフォルダの中だけになります。
$ cd src
$ git clean -nd
Would remove new.js
リポジトリ全体を対象にしたいときは、ルートに戻ってから実行します。
出力の比較表
同じ作業ツリーで、各組み合わせが何を対象にしたかを1つの表にまとめます(○=対象、-=対象外)。
| 対象 | -n |
-nd |
-nx |
-ndx |
-nX |
-ndX |
-ndff |
|---|---|---|---|---|---|---|---|
| memo.txt(未追跡ファイル) | ○ | ○ | ○ | ○ | - | - | ○ |
| src/new.js(追跡済みフォルダ内の未追跡) | ○ | ○ | ○ | ○ | - | - | ○ |
| tmp/(未追跡フォルダ) | - | ○ | - | ○ | - | - | ○ |
| emptydir/(空フォルダ) | - | ○ | - | ○ | - | - | ○ |
| .env・debug.log(無視ファイル) | - | - | ○ | ○ | ○ | ○ | - |
| dist/・node_modules/(無視フォルダ) | - | - | - | ○ | - | ○ | - |
| vendor/(中に .git を持つ) | - | skip | - | skip | - | - | ○ |
| README.md など追跡済みファイル | - | - | - | - | - | - | - |
-xと-Xの違い
小文字と大文字で意味が大きく変わるので、ここだけ取り出して整理します。
-x(小文字) |
-X(大文字) |
|
|---|---|---|
未追跡ファイル(??) |
消える | 残る |
無視ファイル(!!) |
消える | 消える |
| 向いている場面 | クローン直後の状態に戻したい | ビルド成果物・キャッシュだけ消したい |
| 手元のメモや作りかけのファイル | 消える | 残る |
| .env など手元だけの設定 | 消える | 消える |
どちらを使っても .env のような無視ファイルは消える点は共通です。残したいファイルがあるときは -e .env を足します。
2つを同時に指定すると、次のように止まります。
$ git clean -nxX
fatal: -x and -X cannot be used together
実際に削除する(-f / -fd / -fdX / -fdx)
確認が済んだら、-n を -f に置き換えて実行します。dry-runで Would remove と表示されたものが、そのまま Removing に変わります。 次の出力は、同じ作業ツリーで上から順に実行したものです。
$ git clean -f
Removing memo.txt
Removing src/new.js
$ git clean -fd
Removing emptydir/
Removing tmp/
Skipping repository vendor/lib
$ git clean -fdX
Removing .env
Removing debug.log
Removing dist/
Removing node_modules/
-f だけではフォルダが残り、-fd で未追跡フォルダが消え、-fdX で無視ファイルが消える、と段階的に片付いていく様子がわかります。作業ツリーを作り直して -fdx を1回だけ実行した場合は、次のように一度にまとめて削除されました。
$ git clean -fdx
Removing .env
Removing debug.log
Removing dist/
Removing emptydir/
Removing memo.txt
Removing node_modules/
Removing src/new.js
Removing tmp/
Skipping repository vendor/lib
-q を足すと(git clean -fdq)、削除は行われますが Removing ... の行は表示されません。スクリプトの中で使うときに便利です。
手を滑らせにくい打ち方
-n と -f は1文字しか違わないので、次の順番で打つ習慣にしておくと落ち着いて作業できます。
git status -s --ignoredで、未追跡(??)と無視(!!)を把握するgit clean -nd(必要なら-x/-X/-eを足す)で対象を表示する- 表示を読んで、残したいものが混ざっていないか確かめる
- 直前のコマンドを呼び出し、
-nを-fに変えるだけで実行する - もう一度
git status -sを実行して結果を見る
ネストしたGitリポジトリは-ffが必要
未追跡フォルダの中に .git があると、Gitはそれを別のリポジトリとみなし、-f 1回では削除しません。出力に Skipping repository と表示されます。
$ git clean -fd
Removing emptydir/
Removing tmp/
Skipping repository vendor/lib
別のリポジトリには、まだどこにもpushしていないコミットが入っているかもしれません。そのため、ここだけもう一段の確認が設けられています。削除してよいと判断できたら -f を2回重ねます。
$ git clean -ndff
Would remove emptydir/
Would remove memo.txt
Would remove src/new.js
Would remove tmp/
Would remove vendor/
$ git clean -ffd
Removing vendor/
-ndff のように dry-run でも -ff の効果を確認できます。skip repository だった行が Would remove vendor/ に変わりました。
| フォルダの状態 | -fd |
-ffd |
|---|---|---|
| 普通の未追跡フォルダ | 削除 | 削除 |
| 中に .git を持つ未追跡フォルダ | Skipping repository | 削除 |
ほかのリポジトリを試しにクローンしたフォルダが残っている、という場面でよく出会います。-ff を使う前に、そのフォルダの中で git status と git log --oneline -3 を見て、残したいコミットがないか確かめておくと安心です。
-iで選びながら削除する
-i を付けると、対象の一覧が表示されたあと、番号で操作を選べます。-f は不要です。
$ git clean -id
Would remove the following items:
emptydir/ memo.txt src/new.js tmp/ vendor/
*** Commands ***
1: clean 2: filter by pattern 3: select by numbers
4: ask each 5: quit 6: help
What now>
| 入力 | 動き |
|---|---|
1 または c |
表示中の対象を削除して終了 |
2 または f |
パターンを入力し、当たるものを対象から外す |
3 または s |
番号で対象を選ぶ(1,3 や 2-4 と入力) |
4 または a |
1件ずつ y/N で確認する |
5 または q |
何もせず終了 |
6 または h |
説明を表示 |
今回は s → 1,3 → Enter → c の順に入力して、emptydir/ と src/new.js だけを削除しました。
What now> s
1: emptydir/ 2: memo.txt 3: src/new.js 4: tmp/
5: vendor/
Select items to delete>> 1,3
* 1: emptydir/ 2: memo.txt * 3: src/new.js 4: tmp/
5: vendor/
Select items to delete>>
Would remove the following items:
emptydir/ src/new.js
*** Commands ***
1: clean 2: filter by pattern 3: select by numbers
4: ask each 5: quit 6: help
What now> c
Removing emptydir/
Removing src/new.js
a(ask each)を選ぶと、Remove memo.txt [y/N]? のように1件ずつ尋ねられます。memo.txt にだけ y、残りに n と答えたところ、Removing memo.txt の1行だけが表示されました。残したいものと消したいものが混ざっているときは -i が手軽です。
変更を全部取り消す2段の手順
「作業ツリーを最後のコミットの状態に戻したい」という場面では、追跡済みファイルと未追跡ファイルで使うコマンドが分かれます。git clean は未追跡の側だけを担当します。
| 対象 | 記号(git status -s) | 取り消すコマンド |
|---|---|---|
| 追跡済みファイルの編集(ステージ前) | M |
git restore . |
| ステージした変更・ステージした新規ファイル | M / A |
git reset --hard(または git restore --staged --worktree .) |
| 未追跡ファイル・フォルダ | ?? |
git clean -fd |
| 無視ファイル | !! |
git clean -fdX(全部なら -fdx) |
flowchart TD
A[git status -s で状態を見る] --> B{残したい変更がある?}
B -- ある / 迷う --> C[git stash push -u で退避]
B -- ない --> D[1段目: git reset --hard]
C --> D
D --> E[2段目: git clean -nd で確認]
E --> F[git clean -fd で削除]
F --> G[git status -s で確認]
実行例
README.md と src/app.js を編集し、新しいファイル staged.txt を git add し、さらに未追跡ファイルがある状態から始めます。
$ git status -s
M README.md
M src/app.js
A staged.txt
?? memo.txt
?? src/new.js
?? tmp/
?? vendor/
1段目:追跡済みファイルを戻す。 まず git restore . を試すと、次のようになりました。
$ git restore .
$ git status -s
A staged.txt
?? memo.txt
?? src/new.js
?? tmp/
?? vendor/
編集(M)は元に戻りましたが、ステージした新規ファイル staged.txt は残っています。git restore . が戻すのは作業ツリーの内容だけで、ステージ(インデックス)には触れないためです。ステージも含めて戻すには git reset --hard を使います。
$ git reset --hard
HEAD is now at 77dd67a init
$ git status -s
?? memo.txt
?? src/new.js
?? tmp/
?? vendor/
追跡済みの側はきれいになり、未追跡ファイルだけが残りました。git reset --hard は未追跡ファイルには触れません。
2段目:未追跡ファイルを消す。
$ git clean -fd
Removing memo.txt
Removing src/new.js
Removing tmp/
Skipping repository vendor/lib
$ git status -s
?? vendor/
中に .git を持つ vendor/ だけが残りました。これも消す場合は git clean -ffd です。
1段目のコマンドの選び方
| コマンド | 作業ツリーの編集 | ステージ | 向いている場面 |
|---|---|---|---|
git restore . |
戻る | そのまま | ステージした分は残したい |
git restore --staged . |
そのまま | 外れる | ステージだけ外したい |
git restore --staged --worktree . |
戻る | 外れる | 今いるフォルダ以下を全部戻したい |
git reset --hard |
戻る | 外れる | リポジトリ全体を全部戻したい |
git checkout -- . |
戻る | そのまま | restore と同じ働き(以前からある書き方) |
git restore --staged --worktree . も試したところ、MM README.md(ステージ済み+さらに編集)の状態が1回で元に戻りました。git restore . と git clean は、今いるフォルダ以下が対象です。全体を戻したいときはリポジトリのルートで実行します。
コピペ用:全部取り消す手順
# 0. 状態を見る
git status -s --ignored
# 1. 迷いがあれば退避(未追跡ファイルも含める)
git stash push -u -m "before-clean"
# 2. 追跡済みファイルを最後のコミットへ戻す
git reset --hard
# 3. 未追跡ファイルを確認してから削除
git clean -nd
git clean -fd
# 4. 結果を見る
git status -s
手順1で退避した場合、手順2と3で消えるものはほとんど残っていません(退避した時点で作業ツリーがきれいになるため)。その場合は、手順1だけで「全部取り消す」と同じ見た目になり、しかも後から戻せます。
消す前に退避する(git stash -u)
git stash は通常、追跡済みファイルの変更だけを退避します。-u(--include-untracked)を付けると、未追跡ファイルも一緒に退避できます。
$ git stash push -u -m "before-clean"
Ignoring path vendor/lib/
Saved working directory and index state On main: before-clean
$ git status -s
?? vendor/
$ git stash list
stash@{0}: On main: before-clean
退避の中身は次のコマンドで確認できます。
$ git stash show --include-untracked --stat stash@{0}
README.md | 1 +
memo.txt | 1 +
src/app.js | 1 +
src/new.js | 1 +
staged.txt | 1 +
tmp/a.txt | 1 +
tmp/sub/b.txt | 1 +
7 files changed, 7 insertions(+)
編集した README.md、ステージした staged.txt、未追跡の memo.txt や tmp/ の中身まで入っています。git stash pop で戻すと、M・A・?? の状態がそのまま復元されました。
退避の範囲はオプションで変わります。今回確かめた結果は次のとおりです。
| コマンド | 追跡済みの変更 | 未追跡ファイル | 無視ファイル | 中に .git を持つフォルダ | 空のフォルダ |
|---|---|---|---|---|---|
git stash push |
退避 | 残る | 残る | 残る | 残る |
git stash push -u |
退避 | 退避 | 残る | 残る(Ignoring path と表示) | 消える(pop しても戻らない) |
git stash push -a |
退避 | 退避 | 退避 | 残る(Ignoring path と表示) | 消える(pop しても戻らない) |
空のフォルダは、-u や -a で退避すると作業ツリーから消え、git stash pop をしても戻りませんでした。Gitはファイルの中身を記録する仕組みで、中身のないフォルダは記録の対象にならないためです。空のフォルダ自体が必要なときは、pop のあとに mkdir で作り直します。
-u では無視ファイルは退避されません。 そのため、git stash push -u のあとに git clean -fdx を実行すると、.env やログファイルは戻せない形で消えます。実際に、app.log を無視ファイルにした状態で試した結果がこちらです。
$ git stash push -u -m backup
Saved working directory and index state On main: backup
$ git status -s --ignored
!! app.log
$ git clean -fdx
Removing app.log
$ git stash pop
(memo.txt は戻る。app.log は戻らない)
無視ファイルまで退避したいときは -a(--all)を使います。-a で退避して pop すると、app.log も !! の状態で戻ってきました。node_modules のような大きなフォルダがあると -a は時間がかかるので、-u で退避し、.env だけ別の場所にコピーしておく、という分け方も現実的です。
cleanで消したファイルはreflogでも戻せない
git reset --hard で消えたコミットは、reflog(HEADの移動履歴)から戻せます。一方、git clean で消した未追跡ファイルは、Gitが一度も記録していないので、reflogにも何も残りません。
未追跡ファイルを2つ用意して確かめました。memo.txt は一度も git add していないファイル、draft.txt は一度 git add してからステージを外したファイルです。
$ git status -s
?? draft.txt
?? memo.txt
$ git clean -f
Removing draft.txt
Removing memo.txt
$ git reflog
cb2e808 HEAD@{0}: commit (initial): init
reflog には clean の記録が一切ありません。続けて、どこからも参照されていないデータを探す git fsck --lost-found を実行します。
$ git fsck --lost-found
dangling blob ee96201cc9ef91b3594d7f29937288f23d139b37
$ git cat-file -p ee96201cc9ef91b3594d7f29937288f23d139b37
added once
見つかったのは draft.txt の中身(added once)だけでした。一度でも git add したファイルは、内容がGitの中に残っているので拾える可能性があります。一度も git add していない memo.txt は、Gitからは戻せません。
| 消し方 | 対象 | 戻す手がかり |
|---|---|---|
git reset --hard |
コミット済みの履歴 | git reflog で戻せる |
git reset --hard / git restore . |
コミットしていない編集 | 一度 git add していれば git fsck --lost-found で拾えることがある |
git clean -f |
一度も git add していない未追跡ファイル |
Gitには残らない(エディタの履歴やOSのバックアップを探す) |
git clean -f |
一度 git add した未追跡ファイル |
git fsck --lost-found で内容だけ拾えることがある(ファイル名は残らない) |
git stash push -u |
未追跡ファイルを含む変更 | git stash pop / git stash apply で戻せる |
git clean は Git の外にあるごみ箱にも送りません。だからこそ、-n で確認する、git stash push -u で退避する、という2つの準備が効いてきます。エディタにローカル履歴の機能がある場合は、そちらに残っていることもあります。
つまずきやすい点と対処
| 起きること | 理由 | 対処 |
|---|---|---|
fatal: clean.requireForce ... で止まる |
-f・-n・-i のどれも付けていない |
-n で確認してから -f を付ける |
| フォルダが消えない | -d を付けていない |
git clean -fd |
| node_modules や dist が消えない | 無視ファイルは初期状態では対象外 | -x(全部)か -X(無視ファイルだけ) |
Skipping repository ... と出て残る |
中に .git を持つフォルダ | 中身を確かめてから git clean -ffd |
| 編集したファイルが戻らない | git clean は追跡済みファイルを扱わない | git restore . または git reset --hard |
| ステージした新規ファイルが残る | git restore . はステージに触れない |
git reset --hard |
| 一部のフォルダしか消えない | サブフォルダの中で実行している | ルートへ移動して実行 |
| .env まで消えた | -x / -X は無視ファイルを対象にする |
-e .env を足す。事前に -n で確認 |
-x and -X cannot be used together |
2つを同時に指定した | どちらか一方にする |
追跡済みファイルを編集した状態で git clean -fdx を実行しても、編集内容はそのまま残ることも確かめました。
$ git clean -fdx
Removing app.log
Removing memo.txt
$ git status -s
M README.md
git clean が追跡済みファイルを変更することはありません。 追跡済みの側を戻したいときは、前の節の1段目のコマンドを使います。
場面別の使い分け
| 場面 | おすすめのコマンド | 理由 |
|---|---|---|
| 試しに作ったファイルを片付けたい | git clean -nd → git clean -fd |
未追跡だけを消す基本形 |
| ビルドし直したい | git clean -ndX → git clean -fdX |
成果物とキャッシュだけ消える |
| クローン直後の状態にしたい | git reset --hard → git clean -fdx -e .env |
手元の設定だけ残す |
| ブランチ切り替えで未追跡ファイルがぶつかる | git stash push -u |
消さずに退避して切り替える |
| 消してよいか自信がない | git clean -id |
1件ずつ選べる |
| 自動化スクリプトの中で使う | git clean -fdxq |
出力を抑える(対象が決まっている場合) |
よくある質問
Q. git clean -fd と git clean -fdx はどう違いますか?
A. -fd は未追跡のファイルとフォルダだけを削除し、.gitignore に当たるファイルは残します。-fdx は .gitignore に当たるファイル(node_modules、dist、.env など)も含めて削除します。今回の作業ツリーでは、-fd の対象は4件、-fdx の対象は8件でした。
Q. git clean で消したファイルを元に戻せますか?
A. 一度も git add していないファイルは、Gitからは戻せません。reflog にも記録は残りませんでした。一度 git add したことがあるファイルは、git fsck --lost-found で内容だけ見つかることがあります。消す前に git clean -n で確認し、迷うときは git stash push -u で退避しておくのが確実です。
Q. 変更を全部取り消すには、どのコマンドを打てばよいですか?
A. git reset --hard で追跡済みファイルを最後のコミットへ戻し、続けて git clean -fd で未追跡ファイルを削除します。git reset --hard は未追跡ファイルに触れず、git clean は追跡済みファイルに触れないので、2つを組み合わせます。
Q. 特定のファイルだけ残して消したいときは?
A. git clean -fd -e 残したいパターン と書きます。-e は複数回書けます。残すものが多いときは git clean -id の対話モードで番号を選ぶ方法が手軽です。
まとめ
- git clean は未追跡ファイルを削除するコマンド。追跡済みファイルの変更は
git restore ./git reset --hardが担当する - 最初に
git clean -ndで対象を表示し、-nを-fに変えて実行する -dでフォルダ、-xで無視ファイルも、-Xで無視ファイルだけが対象になる。-eで一部を残せる- オプションなしは
fatal: clean.requireForce ...で止まる。中に .git を持つフォルダは-ffが必要 - 変更を全部取り消すときは「reset --hard → clean -fd」の2段で行う
- clean で消したファイルは reflog に残らない。迷うときは
git stash push -u(無視ファイルも含めるなら-a)で退避してから消す
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「git cleanの使い方|未追跡ファイル削除と変更を全部取り消す手順」
株式会社RJCでは、git cleanをはじめとするGitの使い方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。