GitLabのrevertとは?コミットの取り消し方を基本から徹底解説【5000字】
はじめに
ソフトウェア開発の世界では、バージョン管理システム(VCS)が不可欠なツールとなっています。その中でも、Gitは事実上の標準となり、GitLabはGitリポジトリをホスティングし、CI/CDや課題管理など、開発プロセス全体をサポートする強力なプラットフォームとして広く利用されています。
日々の開発業務において、私たちはコードを書き、テストし、そして「コミット」という形で変更を記録していきます。しかし、人間である以上、ミスは避けられません。
- 「新機能を追加したら、なぜか既存の重要な機能が動かなくなった…」
- 「クライアントからの急な仕様変更で、昨日まで書いていたコードが丸ごと不要になった…」
- 「やってしまった!設定ファイルに本番環境のAPIキーを含めたままコミットしてしまった…」
このような状況に直面したとき、頭が真っ白になるかもしれません。しかし、GitとGitLabには、こうした過ちを安全に修正するための強力な機能が備わっています。その代表格が、本記事の主役である「revert」です。
この記事では、GitLabにおけるコミットの取り消し操作、特に「revert」に焦点を当て、その基本概念から具体的な操作方法、そして他の取り消し方法との違いまでを、約5000語のボリュームで徹底的に解説します。
この記事を読めば、以下のことがわかります。
- なぜコミットの取り消しが必要になるのか、具体的なシナリオ
revert
の核心的な概念である「打ち消しコミット」とは何か- GitLabのWeb UIを使って、誰でも安全にコミットをrevertする方法
- コマンドライン(CLI)を使った、より柔軟なrevert操作
revert
,reset
,rebase
という3つの強力なツールの違いと、適切な使い分け- チーム開発で安全にrevertを運用するためのベストプラクティス
この記事は、GitやGitLabを使い始めたばかりの初心者から、チームでの開発効率をさらに高めたい中級者まで、幅広い開発者の方々を対象としています。もう「間違ったコミット」を恐れる必要はありません。この機会にrevert
をマスターし、自信を持って開発を進められるようになりましょう。
第1章: なぜコミットの取り消しが必要なのか?
コミットを取り消す方法を学ぶ前に、まずは「なぜ」そのような操作が必要になるのか、開発の現場で実際に起こりうるシナリオを具体的に見ていきましょう。これにより、revert
の価値と必要性をより深く理解することができます。
開発現場で起こりがちなシナリオ
-
バグの混入(リグレッション)
最も一般的なシナリオです。新しい機能を追加したり、既存のコードをリファクタリングしたりした結果、意図せず別の箇所でバグ(デグレード、リグレッション)を発生させてしまうことがあります。問題のコミットを特定できた場合、迅速にその変更を無かったことにし、安定した状態に一旦戻す必要があります。リリース直後に重大なバグが発覚した場合などは、一刻も早い対応が求められます。 -
急な仕様変更
開発は常に計画通りに進むとは限りません。ビジネス上の都合やユーザーフィードバックにより、急な仕様変更が発生することは日常茶飯事です。昨日まで全力で実装していた機能が、今日の会議で「やはり不要」と判断されることもあります。このような場合、不要になったコードをプロジェクトから綺麗に取り除く必要があります。 -
機密情報の誤コミット
これは最も注意すべきミスの一つです。データベースのパスワード、APIキー、プライベートな証明書といった機密情報を、誤ってソースコードに含めたままリモートリポジトリにpush
してしまうケースです。たとえプライベートリポジトリであっても、このような情報がバージョン管理履歴に残ることは深刻なセキュリティリスクとなります。この場合、単に変更を打ち消すだけでなく、履歴から完全に情報を消去する特別な対応が必要になりますが、その第一歩として変更を取り消すことが考えられます。 -
不完全な実装のプッシュ
作業の途中で、まだ不完全でコンパイルも通らないようなコードを、誤って共有ブランチ(main
やdevelop
など)にpush
してしまうことがあります。これにより、他のチームメンバーの作業がブロックされたり、CI/CDパイプラインが失敗し続けたりと、チーム全体に混乱を招いてしまいます。
コミット取り消しの重要性
これらのシナリオからわかるように、コミットを取り消す能力は、プロジェクトを健全に保つために不可欠です。
- コードベースの健全性維持: バグや不要なコードを迅速に取り除くことで、コードベースをクリーンで安定した状態に保ちます。
- 影響範囲の最小化: 問題が発生した際に、その原因となった変更を素早く取り消すことで、ユーザーや他の開発者への影響を最小限に食い止めます。
- セキュリティリスクの低減: 誤ってコミットされた機密情報へのアクセス経路を(履歴上は残るものの)コード上からは断ちます。
- チーム開発の円滑化: 誤ったプッシュによる混乱を速やかに収拾し、チームのスムーズな開発フローを維持します。
取り消し方法の選択肢
Gitにはコミットを取り消すためのいくつかの方法がありますが、主に以下の3つが挙げられます。
git revert
: 安全な取り消し。過去のコミットを打ち消す「新しいコミット」を作成します。本記事の主役です。git reset
: 強力な履歴改変。コミットの歴史そのものを指定した地点まで巻き戻します。git rebase
: 柔軟な履歴編集。コミットを並べ替えたり、まとめたり、削除したりできます。
この中で、特にチームで開発を進めている共有リポジトリにおいて、最も安全で推奨される方法がgit revert
です。なぜなら、revert
は歴史を「書き換える」のではなく、歴史に「追記する」ことで修正を行うからです。この違いが、チーム開発の安全性を左右する極めて重要なポイントとなります。次の章で、その仕組みを詳しく見ていきましょう。
第2章: git revert
の基本概念を理解する
revert
を効果的に使うためには、その裏側で何が起きているのか、その基本概念をしっかりと理解することが重要です。この章では、revert
の核心である「打ち消しコミット」という考え方と、なぜそれが安全なのかを解説します。
revert
とは何か? — 「打ち消しコミット」の作成
git revert
を一言で説明するならば、「特定のコミットが行った変更を、すべて元に戻すための新しいコミットを作成する操作」です。
これは非常に重要なポイントです。revert
は、過去のコミットを削除したり、変更したりするわけではありません。そうではなく、対象のコミットと正反対の変更を持つ、いわば「打ち消しコミット」または「逆コミット」を新たに生成し、歴史の最後に追加するのです。
会計帳簿で例えてみましょう。
ある帳簿に「支出: 1000円」と誤って記載してしまったとします。
reset
やrebase
のアプローチ(危険): 消しゴムや修正液で「支出: 1000円」の行を消し去り、無かったことにします。一見綺麗に見えますが、後から見返したときに「なぜこの記録が消えたのか」という経緯が一切わかりません。revert
のアプローチ(安全): 間違った記載はそのまま残しておき、新しい行に「収入: 1000円(誤記訂正のため)」と追記します。これで、差し引きゼロとなり、帳簿の残高は正しくなります。そして何より、「間違いがあったこと」と「それを訂正したこと」の両方が記録として明確に残ります。
git revert
は、この会計帳簿の例えの後者のアプローチを取ります。
revert
の最大の特徴: 履歴を改変しない
前述の通り、revert
はGitのコミット履歴を改変しません(Non-destructive)。過去は過去としてそのまま保存し、未来に向かって修正を加えます。
これがなぜそれほど重要なのでしょうか?
共有リポジトリでの絶大な安全性
ソフトウェア開発、特にチームでの開発では、main
やdevelop
といったブランチを全員で共有します。あなたがgit push
でリモートリポジトリ(GitLab)に送信したコミットは、すぐに他のチームメンバーがgit pull
で自分のローカル環境に取り込みます。
ここで、もしあなたがgit reset
やgit rebase
を使って、一度push
したコミットを書き換えてしまったらどうなるでしょうか?
あなたのローカルリポジトリでは歴史が変わっていますが、他のメンバーのローカルリポジトリは古い歴史のままです。次にあなたが変更をpush
しようとすると(この場合、歴史を書き換えているため強制的なgit push --force
が必要になります)、GitLab上のリポジトリはあなたの新しい歴史で上書きされます。
しかし、古い歴史を基に作業していた他のメンバーがgit pull
しようとすると、歴史の分岐点が食い違っているため、Gitは自動でマージすることができず、深刻なコンフリクトが発生します。最悪の場合、他のメンバーの作業内容が失われたり、リポジトリが混乱状態に陥ったりする可能性があります。これは「コンフリクト地獄」の始まりです。
一方、git revert
ならどうでしょう。
revert
は新しいコミットを追加するだけです。これは、新しい機能を追加する際のコミットと何ら変わりありません。他のメンバーは、いつも通りgit pull
を実行するだけで、あなたの「打ち消しコミット」を安全に取り込むことができます。歴史の整合性が崩れることはなく、誰の作業も妨げません。
追跡可能性と透明性
revert
は「なぜこの変更が取り消されたのか」という経緯を、コミット履歴という形で明確に残します。git log
コマンドやGitLabのコミット履歴画面を見れば、誰でも一目瞭然です。
commit XXXXXX...
– Revert “Add new feature Y”commit YYYYYY...
– Add new feature Ycommit ZZZZZZ...
– (以前のコミット)
このように、コミットYがコミットXによって打ち消されたことが記録として残ります。これは、コードレビューや将来の監査、バグの原因調査などにおいて非常に価値のある情報となります。
revert
の仕組みを図解
revert
の動きを、簡単なコミット履歴の図で見てみましょう。
-
通常の状態
main
ブランチにA、Bというコミットがあるとします。
A -> B
-
間違ったコミットCを追加
ここで、バグを含んだコミットCをpush
してしまいました。
A -> B -> C (バグあり)
現在のコードの状態は、Cの変更が適用された状態です。 -
コミットCをrevert
git revert C
を実行します。すると、Cの変更内容(例: 3行目に追加したコード)を打ち消す変更(例: 3行目からそのコードを削除)を持つ、新しいコミットC’が作成されます。
A -> B -> C -> C' (Cの変更を打ち消す)
-
結果
最終的なコードの状態は、Cの変更がC’によって打ち消された結果、コミットB時点の状態と全く同じになります。しかし、歴史上には「Cという変更を一度加えたが、C’でそれを取り消した」という事実が明確に残ります。
この「歴史を書き換えずに、追記によって修正する」という哲学こそが、git revert
をチーム開発における安全な標準たらしめている理由なのです。
第3章: GitLab UIでrevertを実行する
git revert
の概念を理解したところで、次はいよいよ実践です。GitLabの優れたWebインターフェース(UI)を使えば、コマンドラインに不慣れな方でも、マウス操作だけで直感的かつ安全にrevertを実行できます。
特に、GitLab UIのrevert機能は、チーム開発のワークフローに沿った便利なオプションを提供しており、単にコマンドを代行する以上の価値があります。
ステップ・バイ・ステップ・ガイド
ここでは、具体的な手順を追いながら、GitLab UIでのrevert方法を解説します。
1. 対象コミットの特定
まず、取り消したいコミットを見つける必要があります。
- GitLabで対象のプロジェクトページを開きます。
- 左側のサイドバーから
Repository > Commits
をクリックします。 - コミット履歴の一覧が表示されます。ここから、取り消したいコミットを探します。
- コミットメッセージ、作者、日時などを手掛かりに探しましょう。
- 特定のブランチのコミットだけを見たい場合は、画面上部のブランチ選択ドロップダウンで絞り込めます。
- 目的のコミットが見つかったら、そのコミットのタイトル(コミットメッセージの1行目)をクリックして、コミット詳細ページに移動します。
この詳細ページでは、そのコミットでどのようなファイルが、どのように変更されたか(差分)を確認できます。revertを実行する前に、本当に対象がこのコミットで間違いないか、最終確認をしましょう。
2. Revert操作の開始
コミット詳細ページで、内容に間違いがないことを確認したら、revert操作を開始します。
- 画面の右上にある
Options
というドロップダウンボタンをクリックします。 - メニューの中から
Revert
を選択します。
3. Revertコミットの設定
Revert
をクリックすると、「Revert Commit」というモーダルダイアログが表示されます。ここで、これから作成する「打ち消しコミット」に関するいくつかの重要な設定を行います。
-
Commit message:
- デフォルトで
Revert "[元のコミットメッセージ]"
という形式のコミットメッセージが自動生成されます。 - 非常に重要: このデフォルトメッセージのままにせず、なぜこのコミットをrevertするのか、その理由を具体的に追記することを強く推奨します。
- 良い例:
Revert "Add user login cache"
の下に、「本番環境でセッションが意図せず共有される致命的なバグ(#123)が発見されたため、一時的にこの機能を無効化します。」のように、背景や関連するIssue番号を記載します。 - これにより、未来の自分や他のチームメンバーが履歴を見たときに、文脈を即座に理解できます。
- 良い例:
- デフォルトで
-
Target branch:
- このrevertコミットを、どのブランチに作成するかを選択します。
- 通常は、元のコミットが存在するブランチ(例えば
main
やdevelop
)を選択します。
-
Start a new merge request with these changes:
- これがGitLab UIの最も強力な機能の一つです。このチェックボックスをオンにするかオフにするかで、その後のワークフローが大きく変わります。
- チェックを入れた場合(強く推奨):
- GitLabは
revert-xxxxxxxx
のような名前で新しいブランチを自動的に作成します。 - その新しいブランチに、revertコミットを作成します。
- そして、その新ブランチからターゲットブランチ(例:
main
)へのマージリクエスト(MR)を自動で開始します。
- GitLabは
- チェックを外した場合:
- 指定したターゲットブランチに、直接revertコミットが作成・プッシュされます。
なぜマージリクエスト経由のRevertを推奨するのか?
緊急時を除き、常に「Start a new merge request」のオプションを有効にすることをお勧めします。その理由は以下の通りです。
- チームでのレビュー: 「この変更を取り消す」という判断が本当に正しいか、他のメンバーにレビューしてもらう機会が生まれます。もしかしたら、もっと良い解決策があるかもしれません。revertの理由をMRのDescriptionに記述し、チームで合意形成を図ることができます。
- CI/CDパイプラインの実行: MRが作成されると、通常はCI/CDパイプラインが自動的にトリガーされます。これにより、revertした結果、ビルドが失敗したり、新たなテストが失敗したりしないかを事前に確認できます。安全性の二重チェックになります。
- 透明性と議論の場の提供: なぜrevertが必要になったのか、その背景や影響について、MR上で議論し、記録を残すことができます。これにより、同じ過ちを繰り返さないための学びにも繋がります。
4. Revertの実行と完了
設定が完了したら、Revert
ボタンをクリックします。
-
MRを作成するオプションを選んだ場合:
- 自動的にMRの作成ページに遷移します。
- MRのタイトル、説明(Description)、担当者(Assignee)、レビュアー(Reviewer)などを適切に設定します。
Create merge request
ボタンをクリックしてMRを作成します。- その後は、通常のMRと同じフローです。レビュー、CI/CDの確認を経て、問題がなければMRをマージします。MRがマージされた時点で、ターゲットブランチにrevertが適用され、操作は完了です。
-
MRを作成しないオプションを選んだ場合:
Revert
ボタンをクリックすると、即座にターゲットブランチにrevertコミットが作成されます。- コミットリストを再読み込みすると、新しいrevertコミットが追加されているのが確認できます。
マージコミットのRevert
機能開発は通常、フィーチャーブランチで行われ、マージリクエスト(MR)経由でmain
ブランチなどにマージされます。このとき、マージの証として「マージコミット」が作成されます。
もし、あるMRで取り込まれた機能全体を丸ごと取り消したくなった場合、このマージコミット自体をrevertすることができます。
操作は、通常のコミットをrevertする手順とほとんど同じです。
コミットリストで Merge branch 'feature-xxx' into 'main'
のようなマージコミットを探し、その詳細ページからRevert
を選択します。GitLab UIは、マージコミットのrevertに必要な複雑なオプション(後述する-m
オプション)を内部で自動的に処理してくれるため、ユーザーは意識することなく簡単に操作できます。
このように、GitLab UIは、Gitの複雑な操作をラップし、安全でわかりやすい開発ワークフローを提供してくれる強力な味方なのです。
第4章: コマンドラインでgit revert
を実行する
GitLab UIは非常に便利ですが、CUI(コマンドラインインターフェース)に慣れている開発者にとっては、ターミナルから直接git
コマンドを叩く方が素早く、より柔軟な操作が可能です。また、Gitの仕組みを深く理解するためにも、コマンドラインでの操作を学ぶことは有益です。
この章では、git revert
コマンドの基本的な使い方から、便利なオプションまでを解説します。
基本的なワークフロー
コマンドラインでrevert
を行う際の基本的な流れは以下の通りです。
-
ローカルリポジトリの準備
まず、リモートリポジトリの最新の状態をローカルに反映させるため、作業ブランチでpull
を実行します。
bash
# mainブランチで作業する場合
git checkout main
git pull origin main -
対象コミットのハッシュ値を確認
git log
コマンドを使って、コミット履歴を表示し、revertしたいコミットのハッシュ値(一意なID)を特定します。
bash
git log --oneline
# 出力例:
# f1a2b3c (HEAD -> main, origin/main) Add documentation for new API
# c4d5e6f Implement new API endpoint <-- これをrevertしたい
# a7b8c9d Refactor database connection
この例では、c4d5e6f
がrevertしたいコミットのハッシュ値です。 -
git revert
コマンドの実行
特定したハッシュ値を使い、git revert
コマンドを実行します。
bash
git revert c4d5e6f -
コミットメッセージの編集
コマンドを実行すると、デフォルトのテキストエディタ(VimやNanoなど)が起動し、コミットメッセージの編集画面が表示されます。
“`
Revert “Implement new API endpoint”This reverts commit c4d5e6f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7.
Please enter the commit message for your changes. Lines starting
with ‘#’ will be ignored, and an empty message aborts the commit.
“`
ここでもGitLab UIの時と同様に、なぜrevertするのか具体的な理由を追記することが非常に重要です。編集後、エディタを保存して終了すると、revertコミットがローカルリポジトリに作成されます。 -
リモートリポジトリへのプッシュ
最後に、ローカルで作成したrevertコミットをgit push
でGitLab上のリモートリポジトリに反映させます。
bash
git push origin main
これで、他のチームメンバーも変更内容をpull
できるようになります。
git revert
の便利なオプション
git revert
には、より高度な操作を可能にするいくつかのオプションがあります。
-
-e
/--edit
これはデフォルトの動作です。revertコミットを作成する前に、コミットメッセージを編集するためのエディタを起動します。理由を明記するために、基本的にはこのまま使うのが良いでしょう。 -
--no-edit
エディタを起動せず、自動生成されたデフォルトのコミットメッセージ(Revert "..."
)でrevertコミットを即座に作成します。急いでいる場合や、理由が自明な場合に便利ですが、多用は推奨されません。 -
-n
/--no-commit
これが非常に強力なオプションです。git revert -n <commit-hash>
を実行すると、revertによる変更がワーキングツリーとステージングエリアに適用されますが、自動でコミットはされません。-n
オプションの主なユースケース:-
複数のコミットを1つのrevertコミットにまとめる:
複数のコミット(A, B, C)をまとめて取り消したい場合、一つずつrevertすると3つのrevertコミットができてしまい、履歴が煩雑になります。-n
を使えば、これを1つにまとめられます。
bash
git revert -n <commit-A-hash>
git revert -n <commit-B-hash>
git revert -n <commit-C-hash>
# 全ての変更がステージングされている状態になる
git commit -m "Revert features from A, B, and C due to major spec change" -
Revert内容をさらに手動で修正する:
コミットの変更を完全に取り消すのではなく、「一部だけ取り消して、少し修正を加えたい」という場合があります。-n
を使えば、revertによる変更を一旦ワーキングツリーに展開し、コードエディタで自由に修正してから、自分の好きなようにコミットすることができます。
-
-
-m <parent-number>
/--mainline <parent-number>
このオプションはマージコミットをrevertする場合に必須となります。マージコミットは、通常のコミットと異なり、2つ以上の親コミットを持ちます(マージ先のブランチと、マージ元のブランチ)。そのため、
git revert
を実行する際に、「どちらの親から来た変更を打ち消したいのか」をGitに教えてあげる必要があります。この「どちらの親」を指定するのが-m
オプションです。<parent-number>
は通常1
か2
です。
*1
: 1番目の親。通常はマージ先のブランチ(例:main
)。
*2
: 2番目の親。通常はマージ元のブランチ(例:feature/xxx
)。マージリクエストによって取り込まれた変更(つまり、フィーチャーブランチで行われた変更)をすべて打ち消したい場合は、マージ先のブランチ(
main
)を主線(mainline)として残し、フィーチャーブランチからの変更を取り消すことになります。したがって、通常は-m 1
を指定します。マージコミットのrevert手順:
1.git log
でマージコミットのハッシュ値を確認します。マージコミットはMerge:
という行を持っています。
bash
git log --oneline -1 <merge-commit-hash>
# 出力例:
# 3a4b5c6 (HEAD -> main) Merge branch 'feature-login' into 'main'
2.git revert
に-m 1
オプションを付けて実行します。
bash
git revert -m 1 3a4b5c6
3. あとは通常通り、コミットメッセージを編集し、push
します。
コマンドラインでの操作は、最初は少し難しく感じるかもしれませんが、これらのオプションを使いこなすことで、GitLab UIだけでは難しい、よりきめ細やかなバージョン管理が可能になります。
第5章: revert
vs reset
vs rebase
: 適切な使い分け
Gitには、コミットを取り消したり修正したりするための強力なコマンドが他にもあります。特にgit reset
とgit rebase
は、revert
としばしば比較されます。しかし、これらのコマンドはrevert
とは根本的に異なる思想と影響範囲を持っており、誤った使い方をするとリポジトリに深刻なダメージを与えかねません。
この章では、これら3つのコマンドの違いを明確にし、どのような状況でどれを使うべきかの判断基準を解説します。
特徴比較の早見表
まずは、3つのコマンドの核心的な違いを一覧で見てみましょう。
特徴 | git revert |
git reset |
git rebase -i |
---|---|---|---|
操作内容 | 打ち消しコミットを作成 | 履歴を指定した地点まで巻き戻す | コミットの編集、削除、統合など |
履歴の変更 | 変更しない(追記型) | 変更する(削除・巻き戻し) | 変更する(改変・再構築) |
共有リポジトリでの安全性 | 安全 | 極めて危険 (force push 必須) |
極めて危険 (force push 必須) |
主な用途 | push 済みのコミットの安全な取り消し |
push 前のローカルコミットの整理・取り消し |
push 前のローカルコミットの整形・編集 |
例え話 | 帳簿に訂正仕訳を追記 | 帳簿のページを破り捨てる | 帳簿の記述を書き換える |
この表からわかるように、最も大きな違いは「履歴を変更するかどうか」です。revert
だけが履歴を変更せず、reset
とrebase
は履歴を破壊的に変更します。これが、共有リポジトリでの安全性を決定づける要因です。
git reset
— 歴史を巻き戻すタイムマシン
git reset
は、ブランチの先端(HEAD)を、過去の特定のコミットまで強制的に移動させるコマンドです。これにより、指定したコミット以降のコミットは、そのブランチの歴史から消え去ります。
git reset
には、主に3つのモードがあります。
-
git reset --soft <commit-hash>
コミット履歴だけを巻き戻します。行った変更内容はステージングエリア(git add
された状態)に保持されます。コミットだけやり直したい場合に便利です。 -
git reset --mixed <commit-hash>
(デフォルト)
コミット履歴とステージングエリアを巻き戻します。行った変更内容はワーキングツリー(ファイル自体)には残ります。変更内容を見直して、別のコミットに分割したい場合などに使います。 -
git reset --hard <commit-hash>
最も強力で危険なモードです。コミット履歴、ステージングエリア、ワーキングツリーのすべてを、指定したコミットの状態まで完全に巻き戻します。指定したコミット以降に行ったすべての変更は、跡形もなく消え去ります。失われた変更を元に戻すのは非常に困難なため、使用には細心の注意が必要です。
reset
を使うべき時:
push
する前の、完全にローカルなブランチで作業している時。「直前のコミット、やっぱりやり直したい」「一連のコミットを全部捨てて、ゼロから考え直したい」といったシナリオで非常に役立ちます。
reset
を絶対に使ってはいけない時:
main
やdevelop
など、一度でもpush
してチームメンバーと共有したブランチ。歴史を書き換えてしまうため、他のメンバーのリポジトリと深刻な不整合を引き起こします。
git rebase -i
— 歴史を美しく編集する外科医
git rebase
は、あるブランチのコミットを、別のブランチの先端に付け替える(re-baseする)コマンドですが、-i
(--interactive
)オプションを付けることで、コミットの歴史を対話的に編集する強力なツールに変貌します。
git rebase -i <commit-hash>
を実行すると、指定したコミット以降のコミット一覧がエディタで開かれ、各コミットに対して以下のような操作を指示できます。
pick
: そのコミットをそのまま使用する(デフォルト)reword
: コミットメッセージを編集するedit
: コミットを修正するsquash
: 前のコミットと1つに統合する(コミットメッセージは両方残す)fixup
: 前のコミットと1つに統合する(こちらのコミットメッセージは破棄する)drop
: そのコミットを完全に削除する
rebase -i
を使うべき時:
push
する前の、ローカルなフィーチャーブランチで作業している時。マージリクエストを作成する前に、「”fix typo” のような細かいコミットをまとめたい」「コミットの順番を整理して分かりやすくしたい」といった、コミット履歴を綺麗に整える目的で使われます。drop
を使えば、不要なコミットを歴史から消すこともできます。
rebase -i
を絶対に使ってはいけない時:
reset
と同様、チームで共有しているブランチでは絶対に使ってはいけません。コミットハッシュがすべて新しく作り直されるため、歴史の改変に他なりません。
フローチャートによる判断基準
どのコマンドを使うべきか迷ったときは、以下のフローチャートを参考にしてください。
-
取り消したいコミットは、既にリモートリポジトリに
push
済みか?- Yes (push済み) ->
git revert
を使いましょう。これが唯一安全な選択肢です。 - No (ローカルのみ) -> 次の質問へ
- Yes (push済み) ->
-
目的は何か?
- A. コミットを完全に無かったことにしたい
- 変更内容も完全に消して良い ->
git reset --hard
(細心の注意を払って!) - 変更内容はファイルに残しておきたい ->
git reset --soft
またはgit reset --mixed
- 変更内容も完全に消して良い ->
- B. コミットを整理・編集したい(複数コミットをまとめる、メッセージを修正するなど)
- ->
git rebase -i
を使いましょう。
- ->
- A. コミットを完全に無かったことにしたい
この判断基準を常に念頭に置くことで、あなたはGitの強力な機能を安全かつ効果的に使いこなすことができるようになります。
第6章: GitLabにおけるRevertのベストプラクティスと注意点
最後に、GitLab環境でrevert
をより安全かつ効果的に運用するためのベストプラクティスと、特に注意すべき点についてまとめます。
1. 常にマージリクエスト経由でRevertする
第3章でも強調しましたが、これは非常に重要なプラクティスです。GitLab UIの「Start a new merge request with these changes」オプションを積極的に利用しましょう。
- 理由の再確認:
- チームレビュー: revertの妥当性をチームで検証できる。
- CI/CDの実行: revertが新たな問題を引き起こさないか自動テストで確認できる。
- 透明性の確保: なぜrevertが必要だったのか、その経緯がMRとして記録に残る。
緊急のホットフィックスで一刻を争う場合を除き、このワークフローを徹底することで、ヒューマンエラーのリスクを大幅に低減できます。
2. Revertコミットのメッセージを丁寧に書く
デフォルトのRevert "..."
というメッセージは、何がrevertされたかは教えてくれますが、「なぜ」revertされたのかは教えてくれません。
git log
は未来の開発者(未来の自分自身を含む)への手紙です。コミットメッセージには、revertの背景にある文脈を必ず記述しましょう。
- 関連するIssueやTicketの番号(例:
Fixes #456
) - 発生したバグの概要
- ビジネス上の判断(例:
仕様変更に伴い、この機能は一旦クローズ
)
丁寧なコミットメッセージは、将来のコードメンテナンスやデバッグの時間を劇的に短縮してくれます。
3. 一度Revertした変更を再度取り込む(RevertのRevert)
一度revertした変更を、後からやっぱり元に戻したくなることがあります。例えば、一時的な問題で機能を無効化するためにrevertし、その問題が解決した後に再度機能を有効化したい、といったケースです。
この場合、元のコミットを再度cherry-pickするのではなく、revertコミットをrevertするのが正しい方法です。
“`bash
C’ が C を打ち消すrevertコミットだったとする
A -> B -> C -> C’
C’ をrevertする
git revert
“`
これにより、C’の変更(=Cの変更を打ち消す変更)を打ち消す、新しいコミットC”が作成されます。結果として、コードの状態はCの変更が適用された状態に戻ります。
A -> B -> C -> C' -> C''
この方法により、歴史の整合性を保ちながら、一度取り消した変更を安全に復活させることができます。
4. 機密情報をコミットした場合の対処法
これは最も重要な注意点です。
もしAPIキーやパスワードなどの機密情報を誤ってコミットしてしまった場合、git revert
だけでは全く不十分です。
revert
は、あくまでコード上の変更を打ち消すだけで、Gitの歴史の中には機密情報を含んだコミットが永久に残り続けます。悪意のある者がリポジトリの履歴を遡れば、その情報を閲覧できてしまいます。
このような場合の正しい対処手順は以下の通りです。
-
直ちに漏洩した認証情報を無効化する:
これが最優先事項です。AWSのキーならIAMコンソールから、データベースのパスワードならDBを管理するツールから、直ちにキーを失効させ、パスワードを変更してください。被害を未然に防ぐことが最も重要です。 -
リポジトリの履歴から情報を完全に削除する:
revert
ではなく、git filter-repo
やBFG Repo-Cleaner
といった専門のツールを使用し、リポジトリの全履歴をスキャンして該当の情報を完全に消去する必要があります。
これは非常に高度で破壊的な操作であり、全メンバーとの連携が必須となります。実行後は、全員がローカルリポジトリを再クローンする必要があるかもしれません。 -
revert
を実行する(任意):
履歴のクリーンアップ後、現在のコードベースから機密情報を削除するためのrevert
コミット(または通常の修正コミット)を作成し、push
します。
機密情報のコミットは、単なるコードの間違いではなく、セキュリティインシデントです。revert
だけで安心しないよう、くれぐれもご注意ください。
まとめ
本記事では、GitLabにおけるコミットの取り消し操作、特にgit revert
について、その基本概念から具体的な操作方法、応用的な使い方までを包括的に解説しました。
最後に、重要なポイントを振り返りましょう。
git revert
は、特定のコミットの変更を打ち消す「新しいコミット」を作成する操作です。revert
の最大の利点は、コミット履歴を改変しないこと。これにより、チームで共有しているリポジトリでも安全に利用できます。- GitLabのUIを使えば、マージリクエストと連携した安全なrevertワークフローを簡単に実践できます。
- コマンドラインを使えば、複数のコミットをまとめるなど、より柔軟なrevert操作が可能です。
reset
やrebase
は、コミット履歴を破壊的に変更するため、push
済みの共有ブランチでの使用は絶対に避けるべきです。これらはpush
前のローカル作業でのみ使用します。- 状況に応じて適切な取り消し方法を選択し、revertコミットのメッセージを丁寧に書くことが、健全なバージョン管理の鍵となります。
「間違ったコミット」は、開発プロセスにおいて誰にでも起こりうることです。大切なのは、その間違いに気づき、適切かつ安全な方法で修正する知識とスキルを身につけておくことです。
git revert
は、あなたの強力なセーフティネットです。この機能を正しく理解し、使いこなすことで、あなたはより自信を持って、そしてチームと円滑に協調しながら、日々の開発業務に取り組むことができるようになるでしょう。