Gitでcommit(コミット)を取り消す方法

Gitでcommit(コミット)を取り消す方法

公開: 更新:
CodeCampが提供するDX人材育成が可能なプログラミングやITが学べる公開講座

Gitでcommitを実行した後に、間違いに気づいてコミットを取り消したい場面は、日常的な開発作業で頻繁に発生します。コミットメッセージの誤りや、意図しないファイルの含有、コミットのタイミングミスなど、原因はさまざまですが、Gitには状況に応じた複数の取り消し方法が用意されています。

ただし、commitの取り消し方法は「push前かpush後か」「変更内容を残すか消すか」によって使うべきコマンドが異なります。誤った方法を選ぶと、作業中のコードが消えてしまったり、チームメンバーのリポジトリに影響を与えてしまう可能性もあります。

この記事では、git resetの3つのモードによるcommitの取り消し方法と、push済みのcommitを安全に取り消すgit revertの使い方を、実行例付きで詳しく解説していきます。



git resetでcommitを取り消す方法

git resetとは、現在のブランチの先端(HEAD)を指定したコミットまで移動させることによって、コミットを取り消すGitコマンドです。HEADとは、現在の作業位置を示すポインタで、通常はチェックアウトしているブランチの最新コミットを指します。

git resetにはコミット取り消し後の変更の扱いが異なる3つのモードがあり、以下の表にまとめました。

モード コミット ステージング 作業ディレクトリ
--soft 取り消す 残る 残る
--mixed 取り消す 取り消す 残る
--hard 取り消す 取り消す 取り消す

git resetはローカルのコミット履歴を書き換えるため、基本的にはまだリモートにpushしていないcommitの取り消しに使用してください。push済みのcommitにgit resetを使うと、リモートとローカルの履歴に不整合が生じ、チームメンバーに影響を与える可能性があります。

ただし、自分だけが使用しているトピックブランチであれば、git push --forceで強制的に上書きする運用も実務では一般的です。

それぞれのモードは、取り消し後にどの状態まで戻したいかによって使い分けます。コミットし直したい場合は--soft、ステージングからやり直したい場合は--mixed、変更自体を破棄したい場合は--hardが適しています。

それでは各モードについて、詳しく解説していきます。

--softでコミットだけを取り消す

git reset --softは、コミットのみを取り消し、ステージングエリア(インデックス)と作業ディレクトリの変更はそのまま残すモードです。ステージングエリアとは、次のコミットに含めるファイルを登録する領域のことで、git addで追加した変更が保持されます。

git reset --soft HEAD~1

上記のコマンドでは、HEAD~1によって直前の1つのコミットを取り消しています。HEAD~1とは「現在のHEADから1つ前のコミット」を意味します。

実行後、コミットは取り消されますが、変更内容はステージングエリアに残っているため、コミットメッセージを修正したい場合はすぐにgit commitを実行できます。ファイルの追加漏れに気づいた場合は、追加したいファイルをgit addしてから再度コミットしてください。

--soft: Does not touch the index file or the working tree at all (but resets the head to <commit>, just like all modes do). This leaves all your changed files "Changes to be committed", as git status would put it.

出典:Git公式ドキュメント - git-reset

--mixedでコミットとステージングを取り消す

git reset --mixedは、コミットとステージングエリアを取り消し、作業ディレクトリの変更だけを残すモードです。--mixedはgit resetのデフォルトモードであるため、オプションを省略してgit reset HEAD~1と実行した場合も同じ動作になります。

git reset --mixed HEAD~1
# または省略形
git reset HEAD~1

上記のコマンドを実行すると、直前のコミットが取り消され、変更内容はステージングされていない状態(git add前の状態)に戻ります。コミットに含めるファイルを選び直したい場合や、変更内容を確認してから再度ステージングしたい場合に適しています。

このreset操作自体は作業ディレクトリのファイルを変更しないため、編集中のコードはそのまま残ります。


Python研修一覧はこちら

目的に合うPython研修を一覧形式から探したい方は、ぜひご利用ください。

Python研修を比較する

Java研修一覧はこちら

目的に合うJava研修を一覧形式から探したい方は、ぜひご利用ください。

Java研修を比較する

PHP研修一覧はこちら

目的に合うPHP研修を一覧形式から探したい方は、ぜひご利用ください。

PHP研修を比較する

新入社員研修

目的に合う新入社員研修を一覧形式から探したい方は、ぜひご利用ください。

新入社員研修を比較する

全ての研修からも探したい方はこちら

--hardでコミットと変更を全て取り消す

git reset --hardは、コミット、ステージングエリア、作業ディレクトリの変更を指定したコミットの状態に戻すモードです。Gitが追跡しているファイルの変更内容が破棄されるため、取り消したコミットの変更を復元できなくなる危険性があります。

git reset --hard HEAD~1

上記のコマンドを実行すると、直前のコミットとその変更内容が削除され、1つ前のコミットの状態に戻ります。誤ったコードをコミットしてしまい、変更内容自体が不要な場合に使用してください。

ただし、--hardが破棄するのはGitが追跡しているファイル(tracked files)のみです。git addで一度も追加していない新規ファイル(Untracked files)は--hardを実行しても削除されません。

未追跡ファイルも含めて完全にクリーンな状態に戻したい場合は、git clean -fdを併用する必要があります。

--hard: Resets the index and working tree. Any changes to tracked files in the working tree since <commit> are discarded. Any untracked files or directories in the way of writing any tracked files are simply left alone.

出典:Git公式ドキュメント - git-reset

--hardは危険度の高い操作であるため、実行前にgit statusで作業ディレクトリの状態を確認し、git log --onelineやgit diffで取り消す内容を必ず確認することを推奨します。

万が一--hardで消してしまった変更を復元したい場合は、コミット済みの変更に限り、git reflogからコミットハッシュを特定してgit reset --hard [ハッシュ]で戻せる場合があります。ただし、reflogはデフォルトで90日間の保持期限があり、GC(ガベージコレクション)が実行されると参照できなくなるため、確実な復元手段ではありません。

コミットされていなかった変更(git add前の編集内容や未追跡ファイル)は、reflogでも復元できない点に注意してください。

git revertでpush済みのcommitを取り消す方法

git revertとは、指定したコミットの変更内容を打ち消す新しいコミットを作成するGitコマンドです。git resetがコミット履歴を書き換えるのに対して、git revertは履歴を保持したまま変更を元に戻すため、共有済みの履歴を書き換えずに安全に扱いやすいのが特徴です。

リモートリポジトリにpush済みのcommitを取り消す場合は、git revertの使用が推奨されます。

なお、git revertを実行する前に、作業ディレクトリに未コミットの変更がないことを確認してください。未コミットの変更がある状態でgit revertを実行するとエラーになります。

変更がある場合は、事前にgit stashで一時退避するか、git commitでコミットしておく必要があります。

Given one or more existing commits, revert the changes that the related patches introduce, and record some new commits that record them. This requires your working tree to be clean (no modifications from the HEAD commit).

出典:Git公式ドキュメント - git-revert

それでは、直前のコミットを取り消す方法と、特定のコミットを指定して取り消す方法について、詳しく解説していきます。

直前のコミットを取り消す

直前のコミットを取り消す場合は、git revert HEADを実行します。HEADは現在のブランチの最新コミットを指すため、コンフリクトが発生しなければ、直前のコミットの変更内容を打ち消す新しいコミットが作成されます。

git revert HEAD

上記のコマンドを実行すると、エディタが起動してコミットメッセージの編集画面が表示されます。デフォルトのメッセージは「Revert "元のコミットメッセージ"」となっており、そのまま保存して閉じれば打ち消しコミットが作成されます。

エディタを起動せずにデフォルトメッセージでそのままコミットしたい場合は、--no-editオプションを付けてgit revert --no-edit HEADと実行してください。打ち消しコミットの作成後、git pushでリモートに反映すれば、push済みのcommitの取り消しが完了します。

特定のコミットを指定して取り消す

直前以外の過去のコミットを取り消す場合は、git revertにコミットハッシュを指定します。コミットハッシュとは、各コミットを一意に識別するSHA-1形式の英数字(0〜9、a〜fの16進数)の文字列のことで、git logコマンドで確認できます。

# コミット履歴を確認する
git log --oneline
# 出力例:
# a1b2c3d 最新のコミット
# e4f5a6b 取り消したいコミット
# c7d8e9f その前のコミット

# 特定のコミットを取り消す
git revert e4f5a6b

上記のコマンドでは、git log --onelineでコミット履歴を簡潔に表示し、取り消したいコミットのハッシュ(e4f5a6b)を確認しています。git revertに該当のハッシュを指定して実行すると、そのコミットの変更内容だけを打ち消す新しいコミットが作成されます。

git revertは指定したコミットの変更を逆向きに適用する操作であるため、それ以降のコミットの履歴は削除されません。ただし、取り消し対象のコミットと後続のコミットが同じファイルを変更している場合は、コンフリクト(競合)が発生する可能性があるため、手動で解消する必要があります。

また、取り消したい対象がマージコミット(git mergeやPull Requestで作成されたコミット)の場合は、通常のgit revertではエラーになります。マージコミットを取り消すには、-m 1オプションを付けてgit revert -m 1 [コミットハッシュ]と実行し、どちらの親コミットを残すかを指定する必要があります。

-m parent-number: Usually you cannot revert a merge because you do not know which side of the merge should be considered the mainline. This option specifies the parent number (starting from 1) of the mainline and allows revert to reverse the change relative to the specified parent.

出典:Git公式ドキュメント - git-revert

Python基礎・実践(Django)

企業・法人向けのPython研修では、基礎から応用まで体系的に学べます。

Python研修の詳細

DX社員研修

企業・法人向けのDX研修では、実務に繋がるリスキリングでITレベルを向上させます。

DX研修の詳細

Javaエンジニア育成研修

企業・法人向けのJavaエンジニア育成研修では、Javaの基礎から応用まで確実に習得できます。

Java研修の詳細

新卒・新入社員向け研修

企業・法人に新入社員・新卒社員に向けたプログラミング研修を提供しています。

新入社員研修の詳細

コードキャンプのIT研修を全て見る

commitの取り消しに関するよくある質問

git resetとgit revertの違いは何ですか?

git resetはブランチの先端を移動させてコミット履歴を書き換え、git revertは履歴を保持したまま打ち消しコミットを作成します。以下の表に主な違いをまとめました。

項目 git reset git revert
履歴の扱い ブランチの先端を移動し、履歴を書き換える 新しい打ち消しコミットを追加する
適した場面 push前のローカルcommit push済みのcommit
チームへの影響 push済みの場合、履歴の不整合が発生しうる 履歴を壊さないため共有しやすい

基本的には、その履歴が他のメンバーに共有(push)済みかどうかで判断します。本質的には「公開済みの履歴を書き換えるかどうか」が判断基準であり、push前ならgit reset、push後ならgit revertが適しています。

ただし、自分だけが使用しているブランチでpush済みであっても、git resetとgit push --forceを組み合わせる運用は実務で広く行われています。

コミットメッセージだけを修正するにはどうすればよいですか?

直前のコミットメッセージを修正する場合は、git commit --amendを使用します。--amendオプションは、直前のコミットを新しいコミットで置き換えるオプションです。

メッセージの修正だけでなく、ステージングエリアに変更があればその内容も含めて直前のコミットが置き換わります。メッセージだけを変更してファイルの内容は変えたくない場合は、git addを実行せずに--amendを実行してください。

git commit --amend -m "修正後のコミットメッセージ"

上記のコマンドを実行すると、直前のコミットが「修正後のコミットメッセージ」を持つ新しいコミットに置き換えられます。-mオプションを省略した場合はエディタが起動し、既存のメッセージを編集できます。

--amendはコミットを置き換える操作であるためコミットハッシュが変わります。push済みのコミットに対して使用するとリモートとの不整合が発生するため、push前のコミットに対してのみ使用してください。

複数のコミットをまとめて取り消すことはできますか?

git resetでは、HEAD~Nの数値を変更することによって、直近のN個のコミットをまとめて取り消せます。git revertでは、コミット範囲を指定して複数のコミットを連続で取り消せます。

# resetで直近3つのコミットを取り消す(変更は作業ディレクトリに残る)
git reset --mixed HEAD~3

# revertで直近3つのコミットを取り消す(各コミットごとに打ち消しコミットを作成)
git revert HEAD~3..HEAD

上記のgit resetの例では、HEAD~3を指定して直近3つのコミットを取り消しています。git revertの例では、HEAD~3..HEADの範囲指定を使用しています。

Gitの範囲指定「A..B」はAを含まずBを含むため、HEAD~3..HEADは「HEAD~3の次のコミットからHEADまで」、つまりHEAD~2、HEAD~1、HEADの3つのコミットが対象となります。revertの処理は新しいコミット(HEAD)から順に適用されるため、連続するコミットが同じファイルを変更している場合はコンフリクトが発生しやすくなります。

git revertで打ち消しコミットを1つにまとめたい場合は、--no-commitオプションを付けてgit revert --no-commit HEAD~3..HEADと実行してください。--no-commitを使うと、個々の打ち消し結果がコミットされずにステージングエリアに蓄積されるため、全ての打ち消し内容を確認してからgit commitを1回だけ実行できます。

途中でコンフリクトが発生した場合も、都度解消しながら最終的に1つのコミットにまとめられるため、履歴を整理しやすいというメリットもあります。

※上記コンテンツの内容やソースコードはAIで確認・デバッグしておりますが、間違いやエラー、脆弱性などがある場合は、コメントよりご報告いただけますと幸いです。

ITやプログラミングに関するコラム


ITやプログラミングに関するニュース

ブログに戻る

コメントを残す

コメントは公開前に承認される必要があることにご注意ください。

企業・法人向けのIT・プログラミング・生成AI研修を探す、比較する - IT・プログラミングを知って学べるコネクトメディア CodeCampが提供するDX人材育成が可能なプログラミングやITが学べる公開講座 - IT・プログラミングを知って学べるコネクトメディア コードキャンプが提供する無料で学べるプログラミングスクール講座 - IT・プログラミングを知って学べるコネクトメディア コードキャンプDX人材育成研修 - IT・プログラミングを知って学べるコネクトメディア 配属3ヶ月で30%の生産性向上を実現するいよぎんコンピュータサービスの新人研修に迫る - IT・プログラミングを知って学べるコネクトメディア 金融業界の業務効率化を加速するニッセイアセットマネジメントの生成AI×GAS活用研修事例 - IT・プログラミングを知って学べるコネクトメディア 【製造業のDX人材育成事例】デジタル人材の即戦力化を実現する、日本ガイシ株式会社の異動者向オンボーディング研修 - ITやプログラミングを知って学べるコネクトメディア フューチャーアーキテクト株式会社が実現した新入社員向けIT研修プログラムでタスクフォース制度が主体的な学びと成長を生み出す - IT・プログラミングを知って学べるコネクトメディア コードキャンプDX人材育成研修 - IT・プログラミングを知って学べるコネクトメディア コードキャンプIT・プログラミング研修事例/【IT新入社員研修】オンラインとオフラインの最適バランスを実現したFutureOneの導入事例 - IT・プログラミングを知って学べるコネクトメディア コードキャンプIT・プログラミング研修事例/【新入社員研修】柔軟なハイブリッド型Java研修で実現した新卒20名の成長と成果|サークレイス株式会社 - ITやプログラミングを知って学べるコネクトメディア コードキャンプIT・プログラミング研修事例/現場により近いところにデジタルを根付かせるDX基礎講座研修|株式会社ブリヂストン - ITやプログラミングを知って学べるコネクトメディア コードキャンプIT・プログラミング研修事例/業務の効率化・DX推進に向けたIT人材育成への第一歩|株式会社カナエ - ITやプログラミングを知って学べるコネクトメディア 企業・法人向けのIT・プログラミング研修 - ITやプログラミングを知って学べるコネクトメディア

新着記事

対象者別で探す

子供(小学生・中学生・高校生)向け
プログラミング教室検索する

子供(小学生・中学生・高校生)がロボットやプログラミング言語を学ぶことができるオフラインからオンラインスクールを検索、比較することが可能です。

子供(小学生・中学生・高校生)
プログラミング教室検索する

ITやプログラムなどの
最新情報を検索する

日々、新しいITやプログラミング言語の情報が流れていきますが、特定の情報を時系列でニュースやコラムを確認することができます。

ITやプログラムなどの
最新情報を検索する