HOWTO · Git

Git で rm を取り消す方法

削除がステージ済みかコミット済みかにかかわらず、git rm で削除したファイルを復旧する方法を学びます。インデックスまたはコミットから目的のバージョンを復元するための、安全な Git コマンドを選択します。

このページの内容

git rm を取り消すには、まず削除がステージ済みかコミット済みかを確認します。コミット前であれば、HEAD からパスを復元します。コミット後であれば、目的のバージョンを含むコミットを選択し、そのコミットからパスを復元します。Git はコミット済みのバージョンは復旧できますが、一度もコミットされなかったファイルの内容を再作成することはできません。

git rm が変更する内容

git rm <path> は、追跡対象のファイルを作業ツリーから削除し、その削除をインデックスにステージします。これにより、削除は次のコミットに含まれる準備が整います。コマンド rm は git remove のエイリアスではありません。rm はシェル コマンドであり、git rm は Git のインデックスも更新します。

ファイルの追跡をやめつつ作業ツリーのコピーは残したい場合は、git rm --cached <path> を使用します。これにより、インデックスからの削除がステージされ、ファイルはディスク上に残ります。ファイルをローカルに残しながらリポジトリには属させたくない場合によく使われます。

コミット前に削除を復元する

削除がステージ済みで、最後にコミットされたバージョンが必要な場合は、git restore --source=HEAD --staged --worktree -- <path> を使って、HEAD からインデックスと作業ツリーの両方にパスを復元します。使用前に、お使いの Git インストールで git restore が提供されているか確認してください。提供されていない場合、git checkout HEAD -- <path> が HEAD からインデックスと作業ツリーにそのパスを復元します。

これらのコマンドは、作業ツリーにのみ存在した編集ではなく、コミット済みのバージョンを復旧します。そのパスに対するステージ済みまたはローカルの変更をまず確認してください。両方の場所を復元すると、そのパスは選択したバージョンに置き換わります。複数のパスを復元するには、-- の後に各パスを列挙します。

この自己完結型の例では、一時リポジトリを作成し、メモをコミットし、その削除をステージして、コミット済みバージョンを復元します。最後の行が復元されたファイルの内容です。

set -eu
repo_dir="$(mktemp -d)"
trap 'rm -rf "$repo_dir"' EXIT
cd "$repo_dir"
git init -q
git config user.name "Example User"
git config user.email "example@example.invalid"
printf 'A tracked note.\n' > notes.txt
git add notes.txt
git commit -qm "Add note"
git rm -q notes.txt
if git restore --source=HEAD --staged --worktree -- notes.txt 2>/dev/null; then
  :
else
  git checkout HEAD -- notes.txt
fi
cat notes.txt

想定される標準出力:

A tracked note.

コミット後に削除を復旧する

コミットが削除を記録した後は、目的のファイル バージョンを含むコミットを選びます。次に、git restore --source=<commit> --staged --worktree -- <path> を使ってそのパスだけを復元します。git restore が使えない場合は、git checkout <commit> -- <path> を使用します。<commit> と <path> は、選択したコミットとリポジトリ相対パスに置き換えてください。

1 つのパスを復元しても、それを削除したコミットが取り消されるわけではありません。ファイルの復元がステージされ、確認してコミットできます。HEAD~1 が正しいソースだと思い込まないでください。後のコミットが存在する場合があり、直前のコミットに必要なバージョンが含まれていないこともあります。

Git の履歴で以前のバージョンを探す

git log --all -- <path> を使用して、そのパスを変更したコミットを調べ、目的のバージョンを含むものを特定します。git reflog はブランチ先端の最近の位置を記録し、リセットなどのブランチ移動後にコミットを探すのに役立ちます。ファイルの内容を別々に保存するわけではありません。選択するコミットに、目的のファイル バージョンが含まれている必要があります。

候補を特定したら、そのパスが含まれていることを確認し、上記のコマンドを使って候補コミットからそのパスを復元します。Git の履歴が役立つのは、内容がコミットされていた場合のみです。ファイルが一度もコミットされていない場合は、代わりにエディターのバックアップ、システムのバックアップ、その他のコピーを確認してください。

安全な復旧方法を選ぶ

リポジトリの状態に応じてソースを選びます。ステージ済みで未コミットの削除には HEAD から復元し、コミット済みの削除には特定の以前のコミットから復元します。復旧したファイルをコミットする前に、ステージ済みの差分と作業ツリーの状態を確認してください。特に、同じパスに他の作業がある場合は注意してください。

1 つのファイルを復旧する常用手段として git reset --hard は避けてください。インデックスと作業ツリーをリセットし、無関係な未コミットの変更を破棄する可能性があります。選択したコミットから 1 つのパスだけを復元する方が対象が絞られます。複数のファイルについては、復元コマンドに各パスを指定し、コミット前に結果の変更を確認してください。