1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

`git clean -fdx` で絶対クリーンされると思ってないか❓

Posted at

git clean -fdx したら、untrackなファイルは全部消えるんでしょ❓」って思っているそこのあなた。
実はリポジトリをネストしたときには、消えないことがあるのだ❗

TL;DR

git clean -ffdx を使え。
事前確認(ドライラン)は git clean -nffdx を使え。

入れ子になったGitリポジトリ(nested repository)は -fdx ではクリーンされない

例えば、空っぽの repo フォルダから始めて、
git init した後、適当にテキストファイル( akane.md )を作ってみる。
ディレクトリ構成は↓のようになる。

repo
├── .git
└── akane.md

この状態で git clean -nfdx すると、クリーンされるファイルとフォルダが事前確認できる。

$ git clean -nfdx
Would remove akane.md

akane.md がクリーン対象になってることがわかる。
これは新規追加したuntrackなファイルなので、クリーン対象になっているのは期待動作だね。

ここから、 untracked-nested-repo ディレクトリを作成し、
git init してみる。リポジトリが入れ子になるね。
ついでに、適当なテキストファイル( aoi.md )を配置すると、↓の構成になる。

repo
├── .git
├── akane.md
└── untracked-nested-repo
    ├── .git
    └── aoi.md

同じように、 git clean -nfdx を実行してみると...

$ git clean -nfdx
Would remove akane.md

あれ❓変わってなくね❓

そう、実はuntrackでnestedなrepositoryは git clean -fdx の対象にならないのである❗
git clean -fdx に絶対の信頼を寄せていた自分はここで膝から崩れ落ちた。

あわやパニック状態になる自分。
Google先生に聞いても、「 git clean には -f をつけないと消えないぜ❗」的な素人アドバイスしかくれない。ソウジャネーヨ。

Docをよく読んで見る

こういうときは落ち着いて、 公式Doc を読む。

-f

--force

If the Git configuration variable clean.requireForce is not set to false, git clean will refuse to delete files or directories unless given -f or -i. Git will refuse to modify untracked nested git repositories (directories with a .git subdirectory) unless a second -f is given.

ん❓

Git will refuse to modify untracked nested git repositories (directories with a .git subdirectory) unless a second -f is given .

意訳: 「untracked nested repositoryは f2個 ないと無視しちゃうんだよね。」

なんじゃそりゃ〜〜〜〜❗
何年もGit使ってるけど初めて知ったぞそんなの...。
っていうかコマンドサンプルもなしかよ。非英語ネイティブにはつらいぜ❗

-ff にしてみる

おそるおそる git clean -nffdx を叩いてみると...

$ git clean -nffdx
Would remove akane.md
Would remove untracked-nested-repo/

おぉ❗untrackでnestedなrepoもクリーン対象になってる❗

そこで、 -n をやめて git clean -ffdx してみると...

$ git clean -ffdx
Removing akane.md
Removing untracked-nested-repo/

消えた❗消えた❗これが期待動作だよ❗

というわけで、ようやく真にクリーンな状態になりましたとさ。

余談: 「どこでハマるんだこんなケース❓」

Stable Diffusion web UI でハマったんだなこれが。
こいつはStable Diffusionをブラウザから使えるようにする界隈じゃ定番のツール。

問題になるのは拡張機能を保存しておくディレクトリで、↓のようになってる。

stable-diffusion-webui
├── .git
├── ...
└── extensions
    ├── kakucho1
    │   ├── .git
    │   └── ...
    ├── kakucho2
    │   ├── .git
    │   └── ...
    └── ...

つまり、拡張機能は、各拡張機能のGitリポジトリをそのまま /extensions の直下に clone するような構造になってる。

ここで、ルートリポジトリの .gitignore には /extensions が指定されている。

以上により『untrackでnestedなリポジトリ』がユースケースとして存在することになる。

で、「web UIのバージョンあげたいけど、せっかくだからクリーンな状態からあげるか〜」と思って、 git clean -fdx したら、拡張機能が消えないもんだから、慌てだしたってことね。

まぁ、ぶっちゃけ、web UIの場合は拡張機能が残ってても実害はないので、本記事の罠は問題にはならないけど。

しかし、例えば『フォルダの中身を自動で認識して動くシステム』みたいなものを評価する場合を考えると、やばいかも。
テンポラリデータを使って開発していて、いざ本番用に評価しようとしたとき、 git clean -fdx しても、データが残ったままで評価することになりうる。
そうなると、本来はNGになるべき評価がOKになったりするので、影響がでかい。

余談: 「そもそも -n-f がそれぞれ反対の意味を持つ1セットじゃないの❓ -nfdx ってなんだよ...。」

そう思ったそこのあなた❗私も全く同じ意見だった。
確か、どのwebサイトも -ndx が『実際には消さない』、 -fdx を『実際に消す』、として紹介していた気がする。

ただ、公式Docには -n は『実際には消さない』と書いてあって、 -f は『これがないと実際に消すのはやめる』って書いてあるので、微妙にニュアンスが違う。
ぴったり正反対のオプションではないらしい...多分。英語力に自信がない❗
-nf にしたときの挙動は書いてないんだよね...。分かりづらいなぁ。

ともかく、 -nf を指定すると -n の『実際には消さない』を優先するのが実動作のようだ。

また、 -n-f を正反対の意味を持つ1セットとして考えると、
-ff の対になるものが存在しないので矛盾が生じる。
そういう意味もあって、 -f-ff がベースで、そこに -n をつけるって考え方のほうが良いようだ。
ちなみに、「 -f の反対が -n なら、 -ff の反対は -nn じゃろ❗」って思って試したけど、 -n-nn の結果は変わらなかった😭

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?