git rm コマンド
git追跡fileの削除はシェルのrmコマンドではなく、git rm
コマンドを使う。
最初に現在の編集状況を解説し、次に丸数字の順に説明する。
想定する現在の編集状況(ある開発中の状態)
- 社内業務用のシェルプログラムのプロジェクトとする
- 10回前のcommitでfileはa.shとb.shがあり、b.sh内の変数名はhoge
- 1回前のcommitでb.shの変数名をfugaに修正
- 最新commitでc.sh fileを追加
- 編集を再開しb.shの変数名をpiyoに変えてstaging(index)した。d.sh fileも追加&staging
- さらにb.shの変数名をfugafugaに変えて、e.sh fileを追加した(e.shはまだgitで追跡されていない)
- この状態を基本として、git rmコマンドを実行する
- 変化が発生した部分を朱書きで表示
① git rm file名
gitが追跡しているfileを削除する。staging、作業ディレクトリーからファイルを削除する。削除した行為をgitが認識しているので次回のgit commit実行時にfile削除をリポジトリに記録出来る。シェルのrmコマンドを使うとstagingには削除したfileが残ったままとなるためgit rmを使用すること
② git rm file名(内容変更時)
gitの追跡対象fileで、内容が変更されたfileをgit rmで削除しようとするとエラーになる。これは変更内容が保存されていないfileの損失を防ぐためのもの
③ git rm -f file名(内容変更時)
しかし上記の様な場合でも「-f」オプションを付けると、file内容が変更されていても削除する(変更内容を失う)
④ git rm --cached file名
対象fileをgitの追跡対象から外すコマンド。stagingからは削除されるが、作業ディレクトリ内にはgitの追跡対象外fileとして残る。残したfileは .gitignore
に追記しないと常にstaging候補のfileとして表示される点に注意
(このd.shはcommitで保存されていないため①の様にgit rm d.shで削除しようとするとエラーになる)
git addとgit resetとgit rmの関係
git rmコマンドの話の延長として、git addコマンド、git resetコマンドの機能と比較しながら着目してみる。
- git addは、fileをgit追跡対象fileにして、そのfileをstagingに上げる
- git resetは、git追跡対象fileをstagingから下ろす
- git rmは、git追跡対象fileを追跡対象から外す(or 削除)
つまり新規fileに対してgit addを行うと、①fileをgit追跡対象にして②stagingの2つの動作を行う。これは③git resetのunstagingと④git rmのgit追跡対象から外す( or 削除する)という二つのコマンドの逆動作を一気に行っている事になる。となると、git rmの機能だけの逆動作、つまり新規fileをgit追跡対象fileにするだけのコマンドが有っても良い理屈になり、実際に存在する。
git add -N コマンド
それがgit add -N file名
コマンドで、対象fileをgit追跡対象にするがstagingはしない動作になる。コマンド例を示す。
- a.shファイルは、
git add a.sh
でgit追跡対象fileにしてstagingに上げる - b.shファイルは、
git add -N b.sh
でgit追跡対象fileにするがstagingしない - c.shファイルは、何もしない(git追跡対象外のまま)
$ touch a.sh b.sh c.sh # - a.sh , b.sh , c.sh を作成 $ git add a.sh # - a.shをstaging $ git add -N b.sh # -b.shを add -Nオプションで実行 $ git status # - 現在の状態を見る On branch main Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: a.sh # - a.shはstagingされている Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) new file: b.sh # - b.shは非stagingだがgit追跡対象になった Untracked files: (use "git add <file>..." to include in what will be committed) c.sh # - c.shはgit追跡対象外のまま $ git rm -f a.sh # - git追跡対象fileなのでgit rm -f で強制削除出来る rm 'a.sh' $ git rm -f b.sh # - git追跡対象fileなのでgit rm -f で強制削除出来る rm 'b.sh' $ git rm -f c.sh # - git追跡対象外fileなのでgit rm -f では削除出来ない fatal: pathspec 'c.sh' did not match any files $
上記の様にgit status
を実行すると、git add -N
を用いたb.shファイルには Changes not staged for commit: のメッセージが現れる。そしてgit追跡対象fileになっているのでgit rm -f
の強制コマンドで削除出来る(修正保存されていないのでgit rm
コマンドはエラーになる)。
fileの動き
作業ディレクトリに新規file追加してからの各コマンドによる動きを表にした。
説明は下記の別記事を参照して欲しい。
programmingforever.hatenablog.com
どう使うのか
このgit add -N
コマンドを使えば、stagingはしたくないが、新規作成したfileをgitの配下に置いて差分をgit diffでいつでも見られる運用が実現する。例えばgit add -N .
と打つと、作業ディレクトリ内の全fileをすべてgitの追跡対象に出来るので、差分を確認しながら編集を行い、整ったものからstaging出来る。