Gitリセットでコミットを取り消す!基本から実践テクニックまで徹底解説
個人でもチームでも、プロジェクトを進めていると「コミットを取り消したい」という場面に遭遇することがあります。そんなときに頼りになるのが git reset コマンドです。まさに命綱とも言えるツールの一つでしょう。
Gitの追跡メカニズム
git reset を理解する前に、まずGitの内部構造について押さえておきましょう。Gitは、ノードとポインタで構成されるツリー構造によってファイルを管理・追跡しています。
ローカルのGitリポジトリには、基本的に次の3つの「ツリー」が存在します。
- 作業ディレクトリ(Working Directory):ワーキングツリーとも呼ばれ、ローカルディレクトリそのものを指します。
git statusを実行すると、作業ディレクトリの状態を確認できます。 - HEAD:現在のブランチにおける最新コミットのスナップショットです。
git checkoutでブランチを切り替えると、HEADはそのブランチの最新コミットを指すように変わります。 - インデックス(Index):ステージングエリアとも呼ばれます。
git addでファイルを追加すると、このインデックスに登録されます。
Gitのワークフロー
次の例では、ファイルに変更を加え、git add でインデックス(ステージング)に追加し、git status でコミット対象の変更を確認する流れを示しています。
続いて git commit を実行すると、変更内容がより永続的なスナップショットとして保存され、masterブランチとHEADのポインタが更新されます。つまり git commit の後に git status を実行すると、3つのツリーすべてが同じ状態になっていることがわかります(コミットすべきものが何もない状態です)。
では、git reset の目的とは?
なぜこれほど前置きが必要なのか不思議に思うかもしれません。実は git reset は、これらのツリーをさまざまな方法で操作するコマンドだからです。やりたいことに応じて、複数のオプションを受け付ける仕組みになっています。
Gitリセットのモード
変更やファイルをコミットしたものの、「間違ったブランチにコミットしてしまった」「バグを含むコミットだったので巻き戻したい」と気づくことはよくあります。ここで役立つのが、git reset のモードに関する知識です。
モードを指定した git reset は、必ずHEADポインタを更新します。構文は以下の通りです。
git reset <mode> <commit-optional>
主なモード一覧
--soft:HEADポインタのみをリセットし、インデックスと作業ディレクトリには手を加えません。HEADだけがリセットされ、他のツリーには最新の変更が残ったままになります。--mixed:デフォルトのオプションです。HEADとインデックスをリセットします。すべての変更がアンステージされ、git addを実行する前の状態に戻ります。補足:オプションなしでgit resetだけを実行した場合、git reset --mixedとして解釈されます。--hard:このモードは要注意です。HEADとインデックスに加えて、作業ディレクトリまでリセットします。せっかく書いたコードを失う可能性があります!現在のHEADポインタ(最新コミット)以降の変更はすべて破棄されます。
--merge や --keep などのその他のモードについては、公式ドキュメントを参照してください。
覚えておきたい git reset の実践テクニック
コミットの巻き戻し
モードを省略した場合(git reset をオプションなしで実行した場合)、--mixed として解釈されることを思い出してください。
git reset HEAD だけを実行しても何も起こりませんが、git reset HEAD~1 を実行すると、HEADは直前のコミットを指すようになります。
次の例は前述のワークフローの続きです。サンプルファイルに新しいテキストを追加し、git add してコミットしたとしましょう。その後 git reset HEAD~1 を実行すると、すべての変更がアンステージされ、直前のコミットの状態に戻ります。
これは、コミットを素早く取り消したいときに非常に便利な方法です!
特定のファイルだけをアンステージする
git add でファイルをインデックスに追加してしまった場合、次のコマンドだけでそのファイルを除外できます。
git reset HEAD <file-name>
シナリオ:コードをめちゃくちゃにしてしまった!動いていた頃の状態に戻せる?
ローカルの変更をすべて破棄して、直前のコミットの状態に戻りたい場合、最終手段となるのが git reset --hard です。
コードを壊してしまったとき、これが唯一の選択肢になることも少なくありません。コミットハッシュがわかっていれば git reset --hard <commit> と実行できます。ただし注意点として、指定したコミットより後のコミット(存在する場合)にも影響が及ぶので慎重に!
シナリオ:このコミットは新しいブランチに入れるはずだったのに!
これはよくあるミスで、特に本番環境での開発を始めたばかりの頃に起こりがちです。もし遭遇しても、慌てる必要はありません!
対処の手順は基本的に次の通りです。まず、巻き戻したいブランチの状態を持つ新しいブランチを作成します。次に、影響を受けたブランチをリセットし、その後新しいブランチにチェックアウトして、そこで改めてコミットを行います。
git branch new-branch
git reset HEAD~1 --hard
git checkout new-branch
まさに命綱のような使い方ですね!
最後にひとこと
git reset --hard の実行時や、特定のコミットへの巻き戻し時には十分に注意してください。特に本番コードを扱う場合や、他の開発者と共同作業をしている場合には重要です。こうした変更を安全に行いたい場合は、多くの場面で git revert が推奨されます。それについてはまた別の機会に詳しく解説します。それではまた!👋🏻
-
Linuxでrootパスワードをリセットする2つの方法(GRUB・Live CD)
Linuxでは、一般ユーザーもスーパーユーザーも、パスワード認証によって各種サービスへアクセスできます。一般ユーザーが自分のパスワードを忘れてしまった場合は、スーパーユーザーがターミナルから簡単に再設定できます。しかし、スーパーユーザー(rootユーザー)自身がパスワードを失ってしまったらどうすればよいのでしょうか。その場合、ログイン画面が表示される前にパスワードを復旧する必要があります。なお、この仕組みは、物理的にアクセスできる悪意あるユーザーがLinuxホストの完全な権限を奪えてしまう点にもつながるため注意が必要です。本記事では、Linuxでrootパスワードを紛失した際の復旧方法を、2
-
Git初心者向けガイド:バージョン管理の基本をやさしく解説
Linuxユーザーなら、新しいプログラムをダウンロードするときや、CVSやSubversionといったバージョン管理システムを調べているときに、「Git」という名前を目にしたことがあるかもしれません。Gitは、Linuxカーネルの生みの親として知られるLinus Torvalds氏が、既存のソリューションに満足できなかったことをきっかけに開発したリビジョン管理システムです。設計における最大の重点は速度、より正確には効率性に置かれており、従来のシステムが抱えていた多くの欠点を解消しながら、はるかに短い時間で処理を実行します。この記事では、これからGitを学びたい初心者の方向けに、基本的な使い方