【Git】revertとresetの違いと使い分け完全ガイド|3層モデル・reset 5モード・reflog緊急復旧・revert-revert問題まで

Git

git revertgit reset——どちらも「取り消し」に使われますが、Git初心者が最も混乱し、ベテランも--hard連打で変更を吹き飛ばしてしまうGit最大の危険ゾーンです。

多くの記事は「revertは安全、resetは危険」という表面的な結論で終わっています。しかし実務では「なぜそうなるのか」「どの層(HEAD/Index/Working Tree)に何が起きるのか」を理解していないと、--soft--mixedの違いで変更を紛失したり、--hardでコミット前の作業を数時間分ロストしたりします。

この記事では、Gitの3層モデルを土台に、revertreset--soft--mixed--hard--keep--mergeの5モード)がそれぞれの層に何をするのかを可視化し、8軸比較、判断フローチャート、range revert、revertしたコミットをrevertする難問、reset --hardで消した変更をreflogで復活させる緊急手順、チーム運用ポリシーまで、2026年の現場で詰まらないための完全ガイドとしてまとめます。

この記事で学べること

  • 30秒で分かる結論:どちらを使うべきかの黄金律
  • Gitの3層モデル(HEAD/Index/Working Tree)と取り消しコマンドの関係
  • resetの5モード(--soft--mixed--hard--keep--merge)を層単位で完全解剖
  • revertの挙動と連続revert・範囲revert・merge revertの扱い
  • 8軸比較:履歴・安全性・復元性・merge対応・範囲指定など
  • 判断フローチャート:今すぐどちらを使うか一発判定
  • revertされたコミットをrevertする(revert-revert問題)の正しい解法
  • reset --hardで消えた変更をreflogで復旧する緊急手順
  • チーム運用ポリシーとGitHub Branch protectionとの連動
スポンサーリンク
  1. 30秒で分かる結論
  2. Gitの3層モデル:取り消しコマンドの土台
  3. revertの正体:取り消しを「新しいコミット」として追加
    1. revert前後のコミットグラフ
    2. 3層への影響
  4. resetの5モード完全解剖:–soft/–mixed/–hard/–keep/–merge
    1. 5モードの層影響マトリクス
    2. –softの使いどころ
    3. –mixedの使いどころ
    4. –hardの使いどころ(要注意)
    5. –keepの使いどころ
    6. –mergeの使いどころ
    7. pathspec付きreset(ファイル単位)
  5. revertとresetを8軸で比較
  6. 判断フローチャート:今すぐどちらを使うか
  7. 実務シナリオ別の使い分け
    1. シナリオ①:直前のコミットメッセージを書き直したい
    2. シナリオ②:PRに含めてはいけないファイルを除外
    3. シナリオ③:mergeコミットを取り消したい(push済み)
    4. シナリオ④:リモートと完全同期したい
    5. シナリオ⑤:複数の過去コミットをまとめてrevert
  8. 上級テクニック:revertのrevert・ORIG_HEAD・部分取り消し
    1. revertしたコミットをrevertする(revert-revert)
    2. ORIG_HEADでresetを取り消す
    3. reflogで完全復旧する緊急手順
    4. ファイル単位の精密な取り消し
  9. やらかした時の緊急復旧フロー
    1. レベル1:resetしてしまったコミットを取り戻す
    2. レベル2:–hardで消えた未commit変更を取り戻す
    3. レベル3:push後に気づいたforce pushされたresetを取り戻す
    4. レベル4:revertしすぎて元に戻したい
  10. チーム運用:revert/resetルールの明文化
  11. よくある質問
  12. 関連記事
  13. まとめ

30秒で分かる結論

使い分けは「公開済みかどうか」「何を残したいか」で決まります。理由は後半で解説します。

シーン 推奨コマンド 理由
push済みコミットを取り消す git revert <コミット> 履歴を壊さず追加のみ、共有ブランチで安全
未pushの直前コミットをやり直し git reset --soft HEAD~1 変更はIndexに残してcommitのみ戻す
addを取り消す git reset HEAD <file>またはgit restore --staged IndexをHEADと一致、作業内容は保持
ローカル作業を完全破棄 git reset --hard HEAD 3層全てをクリーンに、ただし戻せない
mergeコミットを取り消す git revert -m 1 <merge> 親指定必須、resetは非推奨
複数コミットをまとめて取り消す git revert OLD..HEADまたはreset <ハッシュ> 公開済みならrevertレンジ、未公開ならreset
直前のresetを取り消したい git reset ORIG_HEADまたはreflog resetの直前位置はORIG_HEADに保存されている

黄金律:push後=revert一択push前=reset(soft/mixedを優先)--hard事前にcommitかstashをしてから使うのが鉄則。

Gitの3層モデル:取り消しコマンドの土台

revertとresetの挙動を正確に理解するには、Gitが扱う3つの層を把握する必要があります。「どのコマンドがどの層を変えるか」が分かれば、変更の紛失を防げます。

Gitの3層構造
+----------------------------------------+
| Working Tree (作業ツリー)              |  ← 実際のファイル
|   あなたがエディタで編集している内容    |
+----------------------------------------+
                 ↑↓ git add / git restore
+----------------------------------------+
| Index (ステージング/インデックス)       |  ← 次のコミット候補
|   git add で積み上げた変更             |
+----------------------------------------+
                 ↑↓ git commit
+----------------------------------------+
| HEAD (最新コミット)                    |  ← ブランチ先端
|   リポジトリに記録された最新状態        |
+----------------------------------------+

3層の役割

  • Working Tree:エディタで開いている実ファイル。git statusで”modified”として表示
  • Indexgit addで貯めた”次commitする候補”。staging areaとも呼ぶ
  • HEAD:現在のブランチ先端コミット。リポジトリ上の”記録された過去”

revertとresetは、この3層に対してまったく異なる操作をします。この違いを可視化するのが本記事の核心です。

revertの正体:取り消しを「新しいコミット」として追加

git revertは、指定したコミットの変更を反転した内容で新しいコミットを追加します。既存の履歴は変更されず、「取り消し行為そのもの」が履歴に刻まれる点が最大の特徴です。

revertの基本動作
# 特定のコミットを打ち消す
git revert a1b2c3d

# 実行後
#   a1b2c3d の変更を反転する新コミットが作られる
#   エディタが開いてコミットメッセージを編集できる
#   → "Revert \"元のメッセージ\"" が自動入力

# エディタを開かず即時コミット
git revert a1b2c3d --no-edit

# コミットを作らず変更だけ適用(手動でcommit)
git revert --no-commit a1b2c3d

# revert中断
git revert --abort

# 複数コミットをまとめてrevert(レンジ指定)
git revert OLDER_SHA..NEWER_SHA
# → それぞれ別のrevertコミットが順に作られる

# レンジを1コミットにまとめてrevert
git revert --no-commit OLDER_SHA..NEWER_SHA
git commit -m "Revert feature X (multiple commits)"

revert前後のコミットグラフ

revert前
main  A---B---C---D---E

# Cにバグがあったとする
revert後(C’がCを打ち消す新コミット)
main  A---B---C---D---E---C'

# 履歴は一切削除されていない
# C' は「Cを取り消す」内容を持つ新しいコミット

3層への影響

変化
HEAD 新コミットが追加されて前進(元のコミットも残る)
Index 新コミットの内容に更新
Working Tree 新コミットの内容に更新

revertの「安全性」の正体

既存コミットのハッシュは変わらず、履歴は追加のみ。これはpush済みブランチ・他メンバーのローカル・PRやIssueのコミット参照・CIキャッシュなど既存の参照をすべて保ったまま変更を取り消せる、という意味です。共有ブランチで使える唯一の実用的な取り消し手段。

resetの5モード完全解剖:–soft/–mixed/–hard/–keep/–merge

git resetHEADを指定位置に移動するコマンドで、5つのモードで「Index」「Working Tree」に対する影響度が変わります。多くの入門記事は--soft--mixed--hardの3つしか扱いませんが、trouble shootingでは--keep--mergeの理解が必須です。

5モードの層影響マトリクス

モード HEAD Index Working Tree 主な用途
--soft ✓ 移動 そのまま そのまま commit単位でやり直し、変更は全保持
--mixed(既定) ✓ 移動 ✓ HEADに合わせる そのまま commit取消+unstage、作業は保持
--hard ✓ 移動 ✓ HEADに合わせる ✓ HEADに合わせる(破棄) 完全破棄、戻せない恐れ
--keep ✓ 移動 ✓ HEADに合わせる 未コミット変更を守る 作業を残したまま安全にブランチ移動
--merge ✓ 移動 ✓ HEADに合わせる マージのように統合 merge失敗時の復帰、未pushの変更保持

--mixedデフォルトgit reset HEAD~1はmixed扱い)。明示しないと意図せずunstageが行われるので、必ずモードを明示するのが熟練者のマナー。

–softの使いどころ

直前のcommit内容を変えずにやり直す
# 状況:コミット済みだが、ファイル追加漏れがあった
git reset --soft HEAD~1
# HEADが1つ戻り、直前コミットの変更はすべてIndexに残る

# 追加ファイルを入れて再commit
git add forgotten_file.txt
git commit -m "feat: 新機能(ファイル追加漏れ修正込み)"

# 類似用途:複数コミットを1つにまとめたい
git reset --soft HEAD~3
git commit -m "feat: 機能Xをまとめて実装"

–mixedの使いどころ

addを取り消し、作業内容は保持
# 誤ってaddしたファイルをunstage
git reset HEAD secret.env
# ファイル自体は消えない(staging areaから外れるだけ)

# コミット自体をやり直したいが変更はそのまま
git reset HEAD~1
# HEADが戻り、変更がWorking Treeに残る

–hardの使いどころ(要注意)

作業を完全破棄して綺麗にする
# ローカル作業を丸ごと捨てる
git reset --hard HEAD
# 未コミットの変更はすべて消える

# 過去の状態に完全に戻る
git reset --hard HEAD~3

# リモートと完全同期(ローカル変更全消し)
git fetch origin
git reset --hard origin/main

--hard未コミットの変更を問答無用で消します。実行前にgit statusで未コミット変更の有無を確認し、必要ならgit stashで退避しておくこと。消してしまってもgit reflogでHEAD移動履歴から復元できる可能性がありますが、未コミット変更は復元できないのが最大の落とし穴。

–keepの使いどころ

作業を失わずに安全にブランチ移動
# 今いる位置に未コミット変更がある
# 移動先で同じファイルが変わっていたら失敗する(安全側)
git reset --keep main

# エラー例
# error: Entry 'foo.js' not uptodate. Cannot update.
#   → 衝突するファイルがあるので移動を拒否

# この挙動により --hard のような事故を防げる

–mergeの使いどころ

merge途中で中断したい
# merge中にコンフリクトが出て「もう全部やめたい」
git reset --merge
# Working Treeの未コミット変更を保ちつつmergeを中止

# --abort との違い
# - git merge --abort : merge開始前の状態に戻る(標準)
# - git reset --merge : mergeを中断しつつ、未コミット変更は保護

pathspec付きreset(ファイル単位)

ファイル単位でreset
# 特定ファイルだけHEADに戻す(--mixed相当)
git reset HEAD file.txt

# 特定ファイルだけ過去版に戻す
git reset a1b2c3 -- file.txt

# 注意:pathspec付きresetは --soft/--hard を受け付けない
# → --hard でファイル単位にしたいなら git checkout や git restore を使う
git restore --source=HEAD file.txt  # 推奨

revertとresetを8軸で比較

機能の違いを8つの軸で整理します。実務ではこの表を見るだけで判断できます。

比較軸 revert reset
履歴の残し方 残す(新コミット追加) 消す(HEADを巻き戻す)
ハッシュ 既存は不変、新ハッシュ追加 既存コミットが孤児化(参照から外れる)
共有ブランチ安全性 ◎ そのまま使える ✗ force push必須・事故必至
取り消し範囲 1コミット単位/レンジ指定可 HEADからの連続範囲
マージコミット対応 -m 1指定で可能 可能(HEADを移すだけ)
誤操作からの復旧 revertコミットをrevert reflogreset ORIG_HEAD
未コミット変更への影響 競合しなければ影響なし モード依存(--hardは破棄)
部分取り消し(ファイル単位) 困難(checkout推奨) pathspec指定で可

一言で:revertは”履歴にrevertした事実を残す”/resetは”ブランチが指す場所を変える”。目的が異なる別物で、どちらが優れているではなく使い分けの問題。

判断フローチャート:今すぐどちらを使うか

4秒判定フロー
Q1: 取り消したいコミットはpush済みですか?
   YES → revert 一択(reset禁止)
   NO  → Q2へ

Q2: 残したい要素は何ですか?
   コミットそのもの以外を残したい(変更・add状態) → reset --soft
   コミットだけ消し、変更はファイルに残したい     → reset --mixed(既定)
   すべて吹き飛ばしたい(完全に綺麗に)           → reset --hard(要stash確認)

Q3: 取り消したいのはファイル単位ですか?
   YES → git restore / git reset HEAD <file> を使う
   NO  → そのままresetまたはrevert

Q4: 取り消しを再確認・検証する必要がありますか?
   YES → revert --no-commit で変更だけ適用→テスト→commit
   NO  → そのままrevert/reset

シナリオ早見表

  • main/masterにpush済みの誤コミットgit revert HEAD → push
  • PRで指摘されたaddファイルを戻すgit reset HEAD file.txt(pushしてない場合)
  • 数コミット分をまとめ直してきれいにgit reset --soft HEAD~3 + commit(未push時)
  • mergeが間違いだった(push後)git revert -m 1 <merge commit>
  • reset –hardで作業を消したgit refloggit reset --hard HEAD@{1}

実務シナリオ別の使い分け

シナリオ①:直前のコミットメッセージを書き直したい

amend / –softの選択
# 一番簡単なのは amend(直前コミットそのものを編集)
git commit --amend -m "正しいメッセージ"

# 内容も変えたい場合
git add additional_file.txt
git commit --amend --no-edit

# 履歴を前のコミットに含めて再構築したい
git reset --soft HEAD~1
# 変更はIndexにまとめて残り、好きなようにcommit可能

シナリオ②:PRに含めてはいけないファイルを除外

.envを誤ってaddしてしまった
# まだcommit前
git reset HEAD .env
# または
git restore --staged .env

# commit済みならまず履歴整形(pushしていない前提)
git reset --mixed HEAD~1
git restore --staged .env
echo ".env" >> .gitignore
git add .gitignore
git commit -m "Add .env to gitignore"

# push済みで.envが流出した場合は history rewrite が必要
# → git filter-repo か BFG Repo-Cleaner

機密ファイルをpushしてしまった場合、revertでは過去の履歴に残り続けるため【Git】履歴に含まれる機密情報を完全に削除する方法filter-repoによる履歴書き換え+シークレットローテーションが必要です。

シナリオ③:mergeコミットを取り消したい(push済み)

revert -m 1 で親を指定
# push済みmergeコミットを取り消す
git revert -m 1 <マージコミット>

# -m 1 = "一番目の親 (mainline)" を基準に差分を取る
# これをつけないとGitが「どっちの親を基準にすべきか分からない」とエラー
# fatal: commit <sha> is a merge but no -m option was given.

この操作には重要な副作用があります——revertしたfeatureブランチを再度mergeしても変更が入らない現象が起きます。詳細は【Git】mergeコミットを取り消す方法を参照。

シナリオ④:リモートと完全同期したい

ローカルを強制的にリモートに合わせる
# ローカル変更を全部捨て、リモートと完全一致させる
git fetch origin
git reset --hard origin/main

# 対象ブランチを明示的に
git fetch origin feature
git reset --hard origin/feature

# 直後に未追跡ファイルも消してクリーンに
git clean -fd

reset --hard origin/<branch>は強力ですが、ローカルの作業中ファイルも含めて問答無用で上書き。実行前にgit stash -uで未追跡含めて退避することをおすすめします。

シナリオ⑤:複数の過去コミットをまとめてrevert

レンジ指定のrevert
# OLDER_SHAより新しくNEWER_SHAまでの全コミットをrevert
git revert OLDER_SHA..NEWER_SHA
# → コミットごとにrevertコミットが個別に作られる

# 1コミットにまとめたい場合
git revert --no-commit OLDER_SHA..NEWER_SHA
git commit -m "Revert feature X (rolled back 5 commits)"

# 逆順に適用されることに注意
# 順番次第でコンフリクトしやすいので --no-commit で最後にまとめるのが安全

上級テクニック:revertのrevert・ORIG_HEAD・部分取り消し

revertしたコミットをrevertする(revert-revert)

「revertしたけど、やっぱりrevertを取り消したい」状況はよくあります。解法はrevertコミットをさらにrevertすること。

revert-revertの正しい手順
# もとの流れ
# C (機能追加) → C' (C をrevert、機能削除)

# C' を revert すれば機能が戻る
git revert C'
# → C'' が作られ、再び機能が戻った状態になる

# 履歴
# ... → C → C' → C'' ...
#       +       +
#       機能     復活

revertしたfeatureブランチを再度mergeしても内容は戻りません。Gitはそのコミットが既に履歴にあると見なすためです。解決には「①revert-revertで機能を復活させる」「②ブランチを新規に切り直す」のどちらかが必要。詳しくは【Git】mergeコミットを取り消す方法参照。

ORIG_HEADでresetを取り消す

Gitは危険な操作(resetmergerebasepull)の直前位置を自動的にORIG_HEADに保存します。やり直しが1コマンドで可能です。

ORIG_HEADで即座に戻る
# 誤って reset --hard してしまった直後
git reset --hard ORIG_HEAD
# → resetする前の位置に戻る

# ORIG_HEADの中身を確認
git rev-parse ORIG_HEAD
git log ORIG_HEAD -1 --oneline

ORIG_HEADは1回分の保険。次に危険操作をすると上書きされるので、複数回遡りたい場合はgit reflogで時系列から任意の位置を選ぶのが確実。

reflogで完全復旧する緊急手順

reset –hardで消えたコミットを復活
# HEADの移動履歴を確認
git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~3
# f4e5d6c HEAD@{1}: commit: feat: 機能Y         ← これが欲しい
# 9a8b7c6 HEAD@{2}: commit: feat: 機能X

# HEAD@{1}に戻す
git reset --hard HEAD@{1}

# または直接ハッシュ指定
git reset --hard f4e5d6c

# もしすでにgc済みで消えていたら git fsck --lost-found で探す
git fsck --lost-found
ls .git/lost-found/commit/

reflogの寿命

reflogエントリはデフォルトで90日保持されます(gc.reflogExpire)。その期間内ならどんなreset --hardからも復旧可能。ただし未コミットの変更はreflogに記録されないため、--hard前に必ずgit stashするのが鉄則。

ファイル単位の精密な取り消し

3つの精密取り消しコマンド
# ファイル単位で過去版に戻す(Working Treeのみ)
git restore --source=HEAD~2 file.txt

# ファイル単位でIndexだけ戻す(unstage)
git restore --staged file.txt

# ファイル単位で両方戻す
git restore --source=HEAD --staged --worktree file.txt

# ハンク単位(行の一部)だけ取り消す
git restore -p file.txt
# → "y"/"n"/"s"でハンクごとに選択

最新のGit(2.23+)ではgit restoreが推奨。git checkout -- fileの代わりにgit restore filegit reset HEAD fileの代わりにgit restore --staged fileを使うと意図が明確になります。

やらかした時の緊急復旧フロー

レベル1:resetしてしまったコミットを取り戻す

ORIG_HEADまたはreflog
# 直前のresetだけ取り消したい
git reset --hard ORIG_HEAD

# 数回前のresetを取り消したい
git reflog
git reset --hard HEAD@{5}

レベル2:–hardで消えた未commit変更を取り戻す

未コミットの変更は原則として復元できません。ただしエディタ(VS Code等)が自動保存したバックアップ、OSのゴミ箱、IDE内のローカル履歴機能などが残っている可能性があります。VS CodeならFile → Revert FileLocal History(Timeline)で数時間分の編集履歴が復元できることも。

レベル3:push後に気づいたforce pushされたresetを取り戻す

他メンバーのローカルから救出
# 自分のローカルが上書きされた場合でも、
# 他メンバーがまだfetchしていなければ彼らのローカルにコミットが残っている

# 他メンバーから該当ブランチをforce pushしてもらう
# もしくはremote側のreflogを確認(GitHub APIでは参照できない)

# GitHubの場合
# - Events APIで過去のpushイベントを確認
# - Security Adminに連絡して削除前のSHAから復元依頼

レベル4:revertしすぎて元に戻したい

revert-revertチェーン
# revertを取り消す
git revert <revertコミット>

# 複数のrevertを一気に取り消す
git revert OLDER_REVERT..NEWER_REVERT

revertを連打してしまった場合、reflogreset(未push前提)で一気に元に戻すのも選択肢。push済みならrevert-revert戦略が唯一の正攻法

チーム運用:revert/resetルールの明文化

resetの誤用は個人の事故にとどまらず、force pushで他メンバーの作業を消すことがあります。チームとしての明確なルールが必要です。

CONTRIBUTING.md のサンプル
## 取り消し操作のルール

### push済みブランチ
- 取り消しは **revert のみ**
- mainブランチでの `reset` / `push --force` は禁止(Branch protectionで物理強制)
- mergeコミットの取り消しは `revert -m 1` を必ず使用

### 未push ブランチ(個人作業)
- `reset --soft` / `reset --mixed` は自由に使用可
- `reset --hard` は直前に `git status` 確認+必要なら `stash` 退避
- 共有featureブランチでは force-with-lease 必須(他メンバーに事前連絡)

### 事故対応
- `reset --hard` で消した場合、まず `git reflog` 確認→`ORIG_HEAD` か `HEAD@{N}` で復旧
- 90日以内なら `git fsck --lost-found` で孤児コミットも復旧可能
- 未コミット変更のロストは IDE の Local History を確認

### GitHub設定
- main/release 系は Branch protection で force push と削除を禁止
- Require pull request reviews:最低1名以上レビュー
- Require status checks:CIのgreen必須

Branch protectionで物理強制が最強

「main/masterではresetを禁止」を口約束にせず、GitHub/GitLabのBranch protection rulesで設定するとgit push --force自体が物理的に拒否されます。リポジトリ新設時の初期タスクとして組み込むのが鉄則。

よくある質問

Qrevertとresetはどちらを覚えるべき?
A両方です。push後の取り消しはrevert、push前の整形はresetと役割が違います。どちらか一方しか使わないと、もう片方が必要な場面で危険な代替手段(force push等)を使わざるを得なくなります。両者の3層モデル上の挙動を押さえれば、混乱することはありません。
Qreset –soft/–mixed/–hardの違いが覚えられない
A層単位で覚えると楽です。–soft=HEADのみ移動/–mixed=HEAD+Index移動/–hard=HEAD+Index+WorkingTreeの全移動。下の層に行くほど「消される範囲が広がる」と考えれば、「Indexまで戻すか?」「ファイル本体まで戻すか?」で選択できます。本記事の5モードマトリクス表をブックマークしておくのがおすすめ。
Qreset –hardしてしまいました、復元できる?
Aコミット済みの変更ならgit reflogで90%復元可能。git reflogHEAD@{N}を探し、git reset --hard HEAD@{N}で戻します。ただし未コミットのWorking Tree変更は復元不能です。VS CodeのTimeline機能やエディタの自動保存バックアップを確認するのが最終手段。詳細は本記事「やらかした時の緊急復旧フロー」参照。
Qgit revertでエディタが開かないのはなぜ?
A--no-editがついているか、環境変数GIT_EDITOREDITORが未設定の可能性があります。git config --global core.editor vim(または好きなエディタ)を設定しておきましょう。CI環境で実行する場合は--no-editで自動メッセージのまま進めるのが一般的。
Qrevertしたのに変更が消えません
A以下のいずれかが原因です。①revert対象のコミット範囲が違う(git log --onelineで正しいSHAを確認)。②revertが未commit状態で止まっている(git statusでrevertが完了しているか確認→必要ならgit commit)。③同じ内容が別のコミットにも分散している(複数コミットをrevertする必要あり)。
Qreset HEAD~1とreset –soft HEAD~1は同じ?
A違います。reset HEAD~1はデフォルトで--mixed扱い。HEADが戻りIndexもリセットされます。--softを明示するとIndexはそのまま残るため、「add済み状態を保ったままcommitだけやり直したい」場合に必要。意図せず--mixedになって驚かないよう、モードは常に明示が安全。
Qmergeコミットをrevertした後、同じブランチを再mergeしても内容が反映されない
Aこれは有名な罠で、revertでブランチの変更そのものを取り消した履歴がGitに残るため、同じブランチを再mergeしてもGitは「既に適用済み」と判断します。解決は①revertコミット自体をrevertする(revert-revert)、または②ブランチを新規に切り直して作業を作り直す、のどちらか。詳しくは【Git】mergeコミットを取り消す方法参照。
Qrebaseとresetは何が違う?
Aどちらも履歴を書き換えますが目的が違います。rebase=他ブランチの上に自分のコミットを付け替えるreset=HEADが指す場所を移動する。rebaseは「複数コミットを別の根に移植」、resetは「現在のブランチの先端を動かす」イメージ。詳細は【Git】rebaseとmergeの違いと使い分け完全ガイド参照。

関連記事

まとめ

  • revert=「取り消しコミット」を追加、履歴は改変しない(push後の唯一の安全策)
  • reset=HEADを別コミットに移動、–soft/–mixed/–hard/–keep/–mergeの5モード
  • 3層モデル(HEAD/Index/Working Tree)で各モードの影響範囲を理解するのが近道
  • 黄金律:push後=revert一択push前=reset(主にsoft/mixed)
  • --hard前には必ずgit statusgit stashで保険
  • 事故時はORIG_HEADまたはreflogreset --hard HEAD@{N}で復活
  • mergeコミット取り消しはrevert -m 1必須、再mergeの罠に注意(revert-revert)
  • チーム運用:main/masterはBranch protectionでforce pushを物理禁止、CONTRIBUTING.mdでルール明文化

revertとresetは「どちらが安全か」ではなく「目的が違う別物」として理解するのが正解。3層モデルとreset 5モード、判断フローを押さえれば、取り消し操作で迷うことはなくなります。最強の防御はreflogの存在を知っていること、最強の予防はBranch protectionで物理強制すること——この2つを実装しておけば、Gitの取り消しは怖くなくなります。