「git rmを実行したら、必要なファイルまで一緒に消えてしまった……」「コミット前になんとか元に戻したいけれど、どうすればいいかわからない」と焦った経験はないでしょうか。
開発現場では、ファイル管理や不要なファイルの掃除の際にgit rmコマンドを誤って実行し、作業中のコードを消失させてしまうトラブルがよく発生します。
この記事を読むと、git rmによって削除されたファイルやステージング状態を安全に取り消し、元の状態に復元する具体的な手順がわかるようになります。
確認した環境
本記事の手順は以下の環境で動作を確認しています。
- OSOS [オーエス]Operating System。基本ソフトウェア: UbuntuUbuntu [ウブントゥ]人気のLinuxディストリビューション 24.04 LTS
- GitGit [ギット]ソースコードの変更履歴を管理する分散型バージョン管理システム バージョン: 2.43.0
※本記事の手順は、すでに1回以上コミットが行われており、ファイルがGitのバージョン管理下に置かれているリポジトリを前提としています(初回コミット前で HEAD が存在しない状態では動作が異なります)。
git rmとは?ファイル削除とステージングの仕組み
git rmを実行するとどうなる?
git rmは、Gitの管理下にあるファイルを作業ツリー(ワークツリー)とインデックス(ステージングエリア)の両方から削除し、その削除を次回のコミットの対象として登録するコマンドです。
OSのコマンド(LinuxLinux [リナックス / ライナックス]オープンソースのOSカーネルのrmやWindowsのdel)でファイルを削除した場合、ファイルは作業ツリーから削除されますが、インデックスには削除前の情報が残ります。そのため、Gitは作業ツリーとインデックスの差分からファイルの削除を検出します(未ステージングの変更状態)。
一方、git rmを実行すると、作業ツリーからファイルを削除するとともに、インデックスにも削除が登録されます。そのため、通常は次回のコミットでファイルの削除が記録される状態(ステージングされた状態)になります。
git rm は、作業ツリーやインデックスに未コミットの変更があり、その内容が失われる可能性がある場合、通常は削除を拒否します。ただし、拒否される条件は変更の状態によって異なります。-f オプションを指定すると安全確認を強制的に無効化できるため、必要な変更を失わないよう注意してください。
コマンドの基本的な構文は以下の通りです。
git rm <ファイル名>オプションを指定せずに実行すると、作業ツリー上のファイル自体が物理的に削除され、その削除がインデックスに登録されます。
git rm —cachedとの違い(追跡のみ解除する場合)
「Gitの管理からは外したい(追跡をやめたい)けれど、手元のファイルやディレクトリは手元に残しておきたい」という場面では、--cachedオプションを使用します。
git rm --cached <ファイル名>このオプションを指定すると、インデックス(ステージングエリア)からファイルが削除され、作業ツリー上の実ファイルはそのまま残ります。コミットすると、そのファイルはリポジトリの管理対象から外れます。
例えば、ローカルの設定ファイルやログファイルなど、リポジトリに含めたくないファイルを誤ってバージョン管理に追加してしまった場合に役立ちます。なお、今後もGitの管理対象に含めたくないファイルは、必要に応じて .gitignore に記載してください。.gitignore に記載しない場合、次回以降に再び未追跡ファイル(Untracked files)として追加対象に検出されることがあります。
| コマンド | 作業ツリー(実ファイル) | インデックス(ステージング) | 主な用途 |
|---|---|---|---|
git rm <ファイル> | 削除される | 削除が記録される | ファイル自体を完全に不要として削除したい場合 |
git rm --cached <ファイル> | 残る | 削除が記録される(追跡解除) | 設定ファイル等を手元に残し、Git管理からのみ外したい場合 |
git rmをコミット前に取り消してファイルを復元する方法
作業ツリーからファイルを削除し、まだコミットしていない段階であれば、Gitの機能を使って安全に元の状態へ復元できます。ここでは状況に応じた2つの手順を解説します。
ステージングを解除してからファイルを復元する手順
いきなりファイルを復元するのではなく、まずは削除のステージング(インデックスへの登録)を取り消してから段階的にファイルを復元したい場合や、git rm --cached によるステージングのみを取り消したい場合は、git restore コマンドを使用します。
ステップ1:現在のGitの状態を確認する
git status実行例:
On branch mainChanges to be committed: (use "git restore --staged <file>..." to unstage) deleted: src/app.jsステップ2:ステージングを解除し、作業ツリーへファイルを復元する
削除のステージングを取り消した上で、作業ツリーへファイルを復元するには以下の2つのステップで実行します。
# 1. 削除のステージングを解除する(インデックスをHEADの状態に戻す)git restore --staged src/app.js
# 2. 作業ツリーにファイルを復元するgit restore -- src/app.jsgit restore --staged を実行すると、インデックスが HEAD の状態に戻り、ステージングされた削除が解除されます。ただし、作業ツリー上のファイルは変更されないため、git rm で削除されたファイルは自動的には復元されません。
そのため、続いて git restore -- src/app.js を実行し、インデックスに復元されたファイルの内容を作業ツリーへ反映します。
削除されたファイル自体を完全に元の状態に戻す手順(1コマンドで一括復旧)
git rmを実行すると、ファイルは作業ツリーだけでなくインデックスからも削除されます。そのため、インデックスに復元元となるファイルが存在しない状態では、単に git restore src/app.js を実行しても復元できません(通常の git restore はインデックスの内容を作業ツリーに反映するコマンドのため)。
この場合は、復元元として直前のコミット(HEAD)を指定し、インデックスと作業ツリーの両方を復元する方法が便利です。
ステップ1:作業ツリーとインデックスを直前のコミット状態に復元する
git restore --source=HEAD --staged --worktree -- src/app.js各オプションの意味は以下の通りです。
| オプション | 説明 |
|---|---|
--source=HEAD | 復元元として直前のコミット(HEAD)を指定する |
--staged | インデックス(ステージングエリア)の削除を解除する |
--worktree | 作業ツリーのファイルを復元する |
-- | これ以降をファイルパスとして扱う |
このコマンドにより、HEADに記録されているファイル内容が作業ツリーに復元され、同時にインデックスの削除指示も解除されます。
もしリポジトリ全体で誤って複数のファイルを削除してしまった場合は、パスに .(カレントディレクトリ)を指定することで一括復旧できます。
git restore --source=HEAD --staged --worktree -- .[!WARNING] このコマンドは、指定したパスのインデックスと作業ツリーを
HEADの状態に復元します。そのため、対象ファイルに加えた未コミットの変更や、ステージング済みの変更も失われる可能性があります。 特に.を指定するとカレントディレクトリ以下の広い範囲が対象になります。実行前にgit statusやgit diff、git diff --cachedで変更内容を確認し、必要な変更があれば別途退避(git stashなど)してください。
git restore が導入されたGit 2.23より前のバージョンでは、ファイルの復元に git checkout を使用できます。
以下のコマンドは、HEAD のファイル内容を作業ツリーとインデックスの両方に反映します。対象ファイルに未コミットの変更がある場合は、その変更が失われる可能性があるため注意してください。
git checkout HEAD -- src/app.jsすでにコミットしてしまった場合の対処法
git rmを実行した後に誤ってそのままgit commitまで完了させてしまった場合でも、履歴をたどることでファイルを復旧できます。
直前のコミットであればリセットで対応する
削除をコミットしたのが直前の1回だけであり、まだリモートリポジトリにプッシュしていない場合は、git resetを使用してコミットを取り消すことができます。
ステップ1:直前のコミット内容を確認する
git reset は直前のコミット全体を取り消します。対象のコミットに削除以外の変更も含まれていた場合、それらの変更もコミット履歴から外れてしまうため、事前にコミット内容を確認します。
git show HEADステップ2:コミットを取り消してインデックスを直前の状態に戻す
git reset --mixed HEAD^--mixed オプション(省略時のデフォルト動作)は、HEAD を1つ前のコミットに移動し、インデックスもそのコミットの状態に戻します。作業ツリーのファイルは変更されないため、削除されたファイルは自動的には復元されません。
※なお、git reset --soft HEAD^ を実行した場合は HEAD の位置だけが戻り、インデックスと作業ツリーは変更されないため、インデックスに削除のステージングが残ったままになります。そのため、ファイルを復元する目的では --mixed を使用するのが適切です。
ステップ3:インデックスから作業ツリーにファイルを復元する
インデックスが削除前の状態に戻っているため、以下のコマンドで作業ツリーにファイルを復元し、状態を確認します。
# 1. 作業ツリーにファイルを復元するgit restore -- src/app.js
# 2. 復元後の状態を確認するgit statusなお、git reset はローカルのコミット履歴を変更する操作です。共有ブランチで作業している場合は、実行前にブランチの状況も確認してください。
[!NOTE] すでにリモートリポジトリへプッシュしてしまったコミットを取り消す場合は、共有履歴を書き換えずに変更を打ち消す
git revertが利用できます。直前のコミットが対象であればgit revert HEADを実行します。過去のコミットを取り消したい場合は、対象のコミットハッシュを指定してください。Terminal window # 直前のコミットを取り消す場合git revert HEAD# 特定の過去コミット(例: abc1234)を取り消す場合git revert abc1234ただし、
git revertはコミット全体の変更を打ち消します。削除以外の変更も含まれている場合は、その影響を確認してから実行してください。
過去のコミットから特定のファイルを復元する
すでに何世代も前のコミットで削除を確定させてしまっている場合や、特定のファイルだけを過去のバージョンから現在の作業ツリーに持ってくるには、ファイルの履歴を指定して復元します。
ステップ1:ファイルが存在していた過去のコミットハッシュを確認する
git log --oneline -- src/app.jsgit log の結果から、復元したいファイルが実際に存在していたコミットを選択してください。削除を記録したコミットを指定してもそのコミットにはファイルが存在しないため、削除前のコミットを指定するのが基本です。
ステップ2:特定のコミットからファイルを指定して復元する
例えば、ファイルが存在していたコミットが abc1234 であれば、git restore コマンドでコミットハッシュを指定して復元します。
git restore --source=abc1234 -- src/app.jsこのコマンドは、指定したコミット時点のファイル内容を作業ツリーに復元します。ただし、インデックス(ステージング)は更新されないため、復元したファイルをコミット対象にするには別途ステージングが必要です。
# 復元したファイルをステージングするgit add src/app.js
# 状態を確認するgit statusなお、復元と同時にインデックスも一緒に更新したい場合は、--staged と --worktree を併用します。
git restore --source=abc1234 --staged --worktree -- src/app.jsまた、従来の git checkout コマンドを使用することも可能です。git checkout の場合は作業ツリーとインデックスの両方が同時に更新されます。
git checkout abc1234 -- src/app.jsまとめ:誤って削除しても落ち着いてgit restoreやresetを使おう
git rmは作業ツリーとインデックスの両方からファイルを削除し、削除をステージングするコマンドである- ファイルを手元に残してGitの追跡のみを解除したい場合は、
git rm --cachedを使用する - コミット前であれば、
git restore --source=HEAD --staged --worktree -- <ファイル>で作業ツリーとインデックスを一括復旧できる - コミット直後であれば
git reset --mixed HEAD^の後にgit restoreで復旧できる(プッシュ済みの場合はgit revertを推奨) - 過去のコミットから復元する際は、
git restore --source=<コミット>後にgit addでステージングするか、--staged --worktreeを指定する
現場で予期せぬファイル削除が発生しても、Gitの仕組みを正しく理解していれば慌てずに対応できます。操作を行う前には必ず git status で現在の状態を確認する習慣をつけましょう。
以上で本記事の解説を終わります。
よいITライフを!
人気記事
- 1
- 2
- 3
- 4
- 5
とにかく挫折しない丁寧な解説。チーム開発での基本的な流れを確実にマスターできます。