【Git】マージを取り消す方法を初心者向けにわかりやすく解説

Web開発

はじめに

git では、ブランチを統合するために マージ を行うことがあります。
しかし、誤ってマージをしてしまい、取り消したいという状況も珍しくないのではないでしょうか。

たとえば、開発の途中で機能を統合したものの実装が不十分だったり、想定外の不具合を引き起こしたりすることがあります。
こうしたトラブルを解決するために、マージ結果を取り消す操作が必要になる場合があります。

この記事では、git マージを取り消す 代表的な方法として revertreset を取り上げます。
それぞれの仕組みや具体的な操作手順を実務での活用をイメージしながら解説します。
初心者の方にも分かりやすいよう、技術用語はできるだけ丁寧に補足していきます。

この記事を読むとわかること

  • マージを取り消すための代表的な方法と、それぞれの特徴
  • revert と reset の違い、使い分けの考え方
  • 実務でよくある取り消しの場面と手順
  • コミット履歴を管理する際の注意点

これらを理解すると、万一マージを誤ってしまっても落ち着いて対処できるようになります。
チーム開発で余計な混乱を招くリスクを下げることにもつながるため、ぜひ覚えておいてください。

マージ取り消しの概要

git で行ったマージは、通常コミット履歴に反映されます。
他のコミットと同様に、マージコミットは履歴として記録されるため、そのままでは簡単に消えません。

しかし 実務上 は、いったんマージを行った後に「やっぱり取り消したい」というケースがしばしば発生します。
その際には、いくつかの方法で取り消しを行い、履歴を整合性のある状態に保つ必要があります。

ここで注意したいのは、単にローカルリポジトリで履歴を戻すだけではなく、チームが共有するリポジトリ(例えばリモートリポジトリ)と整合をとる点です。
一度プッシュしてしまったコミットを取り消す操作は、チームメンバーの作業にも影響を与える可能性があります。
このあたりはあとで詳しく解説していきます。

マージを取り消す主な理由

初心者の方は、なぜマージを取り消す操作が必要になるのか想像がつきにくいかもしれません。
実際のプロジェクトでは、次のような理由でマージした変更を後から撤回することがあるのです。

  1. 機能開発が不完全のままマージしてしまった
  2. 別のブランチと競合が発生し、意図しない箇所が上書きされた
  3. コードレビューで大きな修正が必要になり、マージをいったん白紙に戻したい
  4. マージ先のブランチを間違えた

こうした理由がある場合、マージコミットを取り消すことで、本来のブランチ状態に戻し、新しい方針で開発を続けることができます。

マージを取り消すための代表的な方法

git にはいくつかの方法がありますが、代表的なのは revertreset です。
単語の意味も含め、ざっと見てみましょう。

revert

過去のコミットで行った変更を「打ち消す」コミットを新たに作る操作。
取り消したいコミットを完全に無かったことにするわけではなく、反対の内容を適用する ことで最終的な状態を取り消します。
履歴を改変しないため、プッシュ済みの作業を安全に取り消すことができるのがポイントです。

reset

特定のコミットを指して、その時点の状態に 履歴自体を巻き戻す 操作。
取り消したいコミットを含む以降の履歴そのものを無かったことにします。
プッシュ済みコミットに対して行うと、リモート上との整合が崩れる恐れがあるため、チーム開発では注意が必要です。

どちらの方法を選ぶかは、状況や運用ルールによって異なります。
リモートリポジトリにプッシュ済みの場合には、まず revert から検討するとよいでしょう。

revert によるマージ取り消し

revert は マージコミットを打ち消すコミット を新たに作成することで、取り消したい変更を取り消す方法です。
何らかの理由で「変更点を『反対の操作』で元に戻したい」時に役立ちます。

revert の基本的な仕組み

たとえば過去のコミットが下記のようになっていたとします。
A - B - C - (merge commit) - D - E
このうち、(merge commit) の内容を取り消したいとしましょう。

git revert コマンドは以下の形式で実行します(<commit_hash> は取り消したいマージコミットのハッシュ値):

git revert -m 1 <commit_hash>

-m 1 : これはマージコミットを revert する際に必要となる指定です。

マージコミットには複数の親コミットが存在するため、どの親をメインとみなすかを指定します。
通常は -m 1 で問題ありません。

この操作を実行すると、マージによって追加された変更点を打ち消す 新しいコミットが作成されます。
結果的には最新の履歴に打ち消しのコミットが加わり、ソースコードはマージ前の状態に近いものになります。

revert はコミット履歴を壊さないので、チーム開発でリモートに既にプッシュしている場合によく使われます。

revert の実務での活用シーン

revert は以下のようなシーンで頻繁に使われるでしょう。

  • すでにリモートにプッシュされ、他のメンバーが更新を取得している
  • コミット履歴を改変せずに変更点だけを打ち消したい
  • 将来的に、どのような形で取り消しが行われたか、履歴を追跡できるようにしておきたい

例えば、マージした後に「実は動作に問題があった」「仕様変更の要望が出た」などの状況が起きた場合、revert で一時的にマージ結果を打ち消しておき、後で改めて修正済みのブランチをマージし直すといった使い方がされます。
このように、履歴を残したまま安全に戻せる のが revert の強みです。

reset によるマージ取り消し

reset は コミット履歴そのものを巻き戻す ため、revert と比べると操作の影響が大きいです。
とはいえ、まだローカルでプッシュ前ならばとても便利で手軽な方法でもあります。

reset の基本的な仕組み

git reset は以下のコマンドで使うことが多いです。
下記の例では、HEAD^ は「現在のコミットのひとつ前」を意味します。

git reset --hard HEAD^

この操作は、現在のコミットを含む以降の履歴を削除し、ローカルリポジトリの状態を「ひとつ前のコミット」に戻すことになります。
マージ直後であれば、マージコミットそのものを無かったことにする 形になります。

--hard, --soft, --mixed の違い

git reset にはいくつかのオプションが存在しますが、実務でよく使うのは以下の3つです。

  1. --hard: ワークツリーとステージ、両方の内容を指定したコミットに巻き戻す
  2. --soft: コミットは巻き戻すが、ワークツリー上のファイルは残したまま(ステージングも継続)
  3. --mixed: コミットは巻き戻すが、ワークツリーのファイルは残す(ステージングは解除)

マージコミットを完全に取り消したい場合は --hard が分かりやすいでしょう。
ただし、作業中の変更も一緒に破棄されるので、取り消しの前に必要なファイルがあるかどうか確認しておくべきです。

プッシュ後に reset を実行して履歴を改変すると、リモートリポジトリとの差異が大きくなる場合があります。 他のメンバーの作業にも影響が及ぶ可能性があるため、実務でリモートにプッシュしたあとに reset を使う際は慎重に検討してください。

reset の実務での活用シーン

reset は以下のようなシーンで特に有用です。

  • 間違ったブランチにマージしたが、まだプッシュしていない状態
  • マージ後に気づいた問題が小さく、履歴ごと無かったことにした方が手っ取り早い場合
  • 個人開発で、リモートで履歴共有する必要がない場合

このような状況ならば、reset による取り消しはシンプルで直感的かもしれません。
実務では、プッシュ前 かつ 他のメンバーが使っていないブランチ なら reset で巻き戻す方法がよく使われるでしょう。

実務でありがちな手順例

ここでは、マージを取り消す典型的な手順を、シーン別に簡単に紹介します。

シーン1:まだプッシュしていないマージを取り消したい

  1. git log などで現在のコミット状況を確認する。
  2. git reset --hard HEAD^ でマージコミットを取り消す。
  3. 必要に応じて別ブランチで作業をやり直す。

このケースでは、チームメンバーがまだ変更を取り込んでいないため、reset で履歴を巻き戻しても問題になりにくいでしょう。

シーン2:すでにプッシュしてしまったマージを取り消したい

  1. リモートリポジトリのブランチを確認し、取り消したいマージコミットのハッシュを調べる。
  2. git revert -m 1 <commit_hash> を実行し、新しいコミットを作成する。
  3. git push でリモートに打ち消しのコミットを共有する。

この場合、reset でリモートの履歴を改変すると衝突が起きる可能性が高いため、revert の方法が一般的です。

revert と reset の比較まとめ

操作の選択に迷う方も多いと思いますので、改めて revert と reset の違いをまとめておきます。

項目revertreset
履歴の扱い履歴は改変せず、打ち消しのコミットを新たに追加する取り消したいコミット以降の履歴を巻き戻し、改変する
リモートへの影響リモートにプッシュ済みでも問題ないリモートプッシュ後に行うと履歴が不整合になる恐れ
コミットの追跡性コミットは残るので変更の経緯を追いやすいコミットが消えるので経緯追跡は難しくなる
よくある使用シーンすでにプッシュしたけど変更を取り消したいプッシュ前、またはリモートでの履歴共有がない場合
メリット手戻りが少なく、チームでの混乱を防げるコマンドがシンプルで、状態を一気に戻せる
デメリット取り消しのためのコミットが増えるリモートとの不整合が起きるとトラブルになりやすい

初心者の方は、この表を参考に「チームで作業しているかどうか」「すでにプッシュしているかどうか」で判断すると分かりやすいのではないでしょうか。

取り消し操作における注意点

最後に、マージ取り消しを実務で活用する際に、初心者の方がつまずきやすいポイントをいくつか挙げます。

コミットハッシュの取り扱い

マージコミットは通常のコミットとは異なり、複数の親コミット を持っています。
このため revert で取り消す場合には -m オプションが必要です。
コミットハッシュを間違えないように、git loggit log --graph --oneline などでしっかり確認しましょう。

リモートリポジトリの更新時期

プッシュ前に取り消すか、プッシュ後に取り消すかによって適切な方法は変わります。
リモートに影響が及ぶかどうか、チームの運用ルールと照らし合わせて慎重に判断する必要があります。

コミットメッセージの書き方

revert を行う際には、新たに追加されるコミットメッセージが自動生成されます。
そのままでも差し支えありませんが、わかりやすいメッセージを残しておくと、後で履歴を追うときに役立ちます。

コンフリクトが発生するケース

revert や reset を行った後、新たに別のブランチをマージする際には、コンフリクト(衝突)が起こる可能性があります。
これは、マージされた履歴を消したにもかかわらず、同じファイルを別ブランチでも変更している ような場合に起きやすいでしょう。
コンフリクトの修正は落ち着いてやれば難しくはありませんが、初心者の方にとっては少しハードルが高いと感じるかもしれません。
必要であればチームメンバーと連携しながら解消すると安心です。

まとめ

この記事では、git マージを取り消す方法 として revertreset を中心に解説しました。
revert はマージコミットを打ち消すコミットを作ることで、履歴を残したまま変更を取り消せます。
一方で reset は履歴そのものを巻き戻すため、取り消したいコミットを丸ごと無かったことにする操作となります。

  • すでにリモートにプッシュした場合は、混乱を招かないよう revert で対応する方法が安心
  • プッシュ前であれば、reset で一気に履歴ごと巻き戻すのも良い手段

実務では、チームメンバーとのコミュニケーション がとても大切です。
マージ取り消しによって他の作業に影響が出る場合もあるため、誰がどのブランチを作業しているのか、リモートリポジトリにプッシュしたタイミングはいつかなどを把握しておきましょう。

慣れないうちは緊張する操作かもしれませんが、焦らずに手順とコミット履歴を確認しつつ実行してみてください。
しっかりとしくみを理解すれば、万が一の時も落ち着いて対処できるでしょう。

Gitをマスターしよう

この記事で学んだGitの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。