間違ったコミットをpushしてしまった、パスワードを含むファイルを公開してしまった、テストコードを本番にpushしてしまった…
「もうpushしちゃったけど、取り消せる?」 「git reset –hard は危険って聞いたけど…」 「チームに迷惑かけずに修正したい」
実は、push後のコミット取り消しには4つの方法があり、それぞれリスクと適用場面が異なります。間違った方法を選ぶと、チームメンバーの作業を壊したり、履歴が壊れたりする危険があります。
今回は、最も安全な方法から、緊急時の強制的な方法まで、状況に応じた正しい取り消し方を完全解説します!
⚠️ 重要:push後の取り消しのリスクを理解する

なぜpush後の取り消しは危険なのか
ローカルとリモートの違い:
状況 | 影響範囲 | リスク | 修正の自由度 |
---|---|---|---|
push前(ローカルのみ) | 自分だけ | なし | 自由に変更可能 |
push後(リモート) | チーム全員 | 高い | 慎重な対応必要 |
絶対に理解すべき原則
Git の黄金律:
🔴 公開された履歴は書き換えない
🟡 どうしても必要な場合は、チームに通知
🟢 可能な限り revert を使う
方法1:git revert(最も安全・推奨)
revertとは?
取り消しコミットを新規作成する安全な方法:
履歴を書き換えずに、逆の変更を加える新しいコミットを作成
A → B → C → D → Revert C(Cの逆操作)
基本的な使い方
単一コミットの取り消し:
# 最新のコミットを取り消し
git revert HEAD
git push origin main
# 特定のコミットを取り消し
git revert <commit-hash>
git push origin main
# コミットメッセージを編集せずに取り消し
git revert HEAD --no-edit
git push origin main
複数コミットの取り消し
範囲指定でrevert:
# 最新3つのコミットを取り消し(個別にrevertコミット作成)
git revert HEAD~3..HEAD
# 複数のコミットを1つのrevertコミットにまとめる
git revert HEAD~3..HEAD --no-commit
git commit -m "Revert: 最新3つのコミットを取り消し"
git push origin main
# 特定の範囲を取り消し
git revert <oldest-commit>^..<newest-commit>
マージコミットのrevert
マージを取り消す特殊な方法:
# マージコミットをrevert(親を指定)
git revert -m 1 <merge-commit-hash>
# -m 1: 最初の親(通常はmainブランチ)を維持
# 確認方法
git show <merge-commit-hash>
# Merge: の行で親コミットを確認
revertのメリット・デメリット
メリット | デメリット |
---|---|
✅ 履歴が保持される | ❌ 履歴が長くなる |
✅ 安全(他者への影響なし) | ❌ コンフリクトの可能性 |
✅ 後で再適用可能 | ❌ 複雑な変更は面倒 |
✅ 監査証跡が残る | ❌ 完全な削除ではない |
方法2:git reset + force push(危険・要注意)
resetとは?
履歴を巻き戻す強制的な方法:
履歴自体を削除して、過去の状態に戻す
A → B → C → D => A → B(C,Dが消える)
⚠️ 使用前の確認事項
必ずチェック:
- [ ] 自分だけが使うブランチか?
- [ ] 他の人がpullしていないか?
- [ ] バックアップを取ったか?
- [ ] チームに通知したか?
基本的な使い方
ローカルで取り消してforce push:
# 最新のコミットを取り消し(ファイルは維持)
git reset --soft HEAD~1
git push --force-with-lease origin main
# 最新のコミットを完全に取り消し(ファイルも戻す)
git reset --hard HEAD~1
git push --force-with-lease origin main
# 特定のコミットまで戻す
git reset --hard <commit-hash>
git push --force-with-lease origin main
resetのオプション比較
オプション | コミット | インデックス | 作業ツリー | 用途 |
---|---|---|---|---|
–soft | 削除 | 維持 | 維持 | コミットやり直し |
–mixed | 削除 | 削除 | 維持 | add からやり直し |
–hard | 削除 | 削除 | 削除 | 完全に消去 |
force pushの種類
# 通常のforce push(危険)
git push --force origin main
# より安全なforce push(推奨)
git push --force-with-lease origin main
# リモートが期待する状態と異なる場合は失敗する
# dry-run で確認
git push --dry-run --force-with-lease origin main
方法3:新しいコミットで上書き(実践的)

修正コミットを追加
最もシンプルな方法:
# ファイルを修正
vim problematic-file.txt
# 修正をコミット
git add .
git commit -m "Fix: 先ほどの間違いを修正"
git push origin main
commit –amend は使わない
push後にamendは危険:
# ❌ これはやってはいけない
git commit --amend
git push --force # 履歴の書き換えになる
# ✅ 代わりに新しいコミット
git commit -m "Fix: typo修正"
git push
方法4:インタラクティブrebase(上級者向け)
複数コミットの整理
履歴を美しく整理:
# 最新5つのコミットを編集
git rebase -i HEAD~5
# エディタが開く
pick abc1234 Add feature A
pick def5678 Fix typo # これを消したい
pick ghi9012 Add feature B
pick jkl3456 Update docs
pick mno7890 Fix bug
# 変更:defの行を削除またはdropに変更
pick abc1234 Add feature A
drop def5678 Fix typo # または行ごと削除
pick ghi9012 Add feature B
pick jkl3456 Update docs
pick mno7890 Fix bug
# 保存して終了
:wq
# force pushが必要
git push --force-with-lease origin main
rebaseのコマンド一覧
コマンド | 動作 | 用途 |
---|---|---|
pick | そのまま使用 | 変更なし |
reword | コミットメッセージ変更 | メッセージ修正 |
edit | コミットを編集 | 内容変更 |
squash | 前のコミットと統合 | コミットまとめ |
fixup | squashと同じ(メッセージ破棄) | 細かい修正を統合 |
drop | コミット削除 | 不要なコミット削除 |
状況別:どの方法を選ぶべきか
判断フローチャート
push後のコミットを取り消したい
↓
他の人と共有している?
├─ Yes → git revert を使用(方法1)
└─ No
↓
機密情報の削除が必要?
├─ Yes → reset + force push(方法2)+ BFG
└─ No
↓
履歴をきれいに保ちたい?
├─ Yes → interactive rebase(方法4)
└─ No → 新しいコミットで修正(方法3)
ケース別の推奨方法
状況 | 推奨方法 | 理由 |
---|---|---|
本番環境 | revert | 安全性最優先 |
共有ブランチ | revert | 他者への影響なし |
個人ブランチ | reset + force | 自由に変更可能 |
機密情報漏洩 | reset + BFG | 完全削除必要 |
typo修正 | 新規コミット | シンプル |
PR前の整理 | interactive rebase | 履歴の美化 |
緊急対応:機密情報を公開してしまった場合
即座に行うべきこと
1分1秒を争う対応:
# 1. 即座にコミットを取り消し
git reset --hard HEAD~1
git push --force-with-lease origin main
# 2. 機密情報を変更
# - パスワードを変更
# - APIキーを無効化
# - アクセストークンを再生成
# 3. BFG Repo-Cleanerで完全削除
java -jar bfg.jar --delete-files passwords.txt
git reflog expire --expire=now --all
git gc --prune=now --aggressive
git push --force-with-lease origin main
# 4. GitHubのキャッシュもクリア
# Settings → Options → Danger Zone → "Delete this repository"
# ※最終手段:リポジトリ削除→再作成
GitHub固有の対応
# GitHubサポートに連絡
# https://support.github.com/contact
# "Accidentally pushed sensitive data" を選択
# プルリクエストやフォークの確認
gh api graphql -f query='
{
repository(owner:"owner", name:"repo") {
forks(first: 100) {
nodes {
owner { login }
name
}
}
}
}'
チーム開発での注意事項

force push前の通知テンプレート
## ⚠️ Force Push 予告
**対象ブランチ**: main
**実施時刻**: 2024/01/20 15:00
**理由**: 機密情報の誤コミット削除
**影響**: 直近3コミットが書き換わります
### 対応方法
実施前:作業中の変更をコミットまたはstash
実施後:
`git fetch origin`
`git reset --hard origin/main`
質問があれば連絡ください。
force push後の対応
チームメンバーがすべきこと:
# 方法1: 完全にリモートに合わせる(推奨)
git fetch origin
git reset --hard origin/main
# 方法2: 作業を維持しながら更新
git fetch origin
git rebase origin/main
# 方法3: 退避してから更新
git stash
git fetch origin
git reset --hard origin/main
git stash pop
トラブルシューティング
よくあるエラーと対処法
エラー1:rejected(non-fast-forward)
# エラー
! [rejected] main -> main (non-fast-forward)
# 解決方法
git push --force-with-lease origin main
# または
git pull --rebase origin main
git push origin main
エラー2:コンフリクト発生
# revert時のコンフリクト
git revert HEAD
# コンフリクト発生
# 解決手順
# 1. コンフリクトを手動解決
vim conflicted-file.txt
# 2. 解決後にadd
git add conflicted-file.txt
# 3. revert続行
git revert --continue
エラー3:force pushが拒否される
# GitHubの保護設定
# Settings → Branches → Branch protection rules
# 一時的に保護を解除(管理者権限必要)
# または管理者にforce pushを依頼
ベストプラクティス
予防策
ミスを防ぐ設定:
# push前の確認を強制
git config --global push.default simple
git config --global push.confirm always
# force pushに警告
git config --global alias.force-push '!echo "⚠️ Force pushしますか? (y/n)" && read confirm && [ "$confirm" = "y" ] && git push --force-with-lease'
# コミット前のフック
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
# パスワードファイルのチェック
if git diff --cached --name-only | grep -E "(password|secret|key)"; then
echo "⚠️ 機密情報が含まれている可能性があります"
exit 1
fi
EOF
chmod +x .git/hooks/pre-commit
履歴管理のルール
# .gitmessage
# コミットメッセージテンプレート
# Type: feat/fix/docs/style/refactor/test/chore
#
# Subject: 50文字以内で要約
#
# Body: 詳細な説明(なぜ変更したか)
#
# Issue: #123
よくある質問(FAQ)
Q1:revertとresetの使い分けは?
A:共有状況で判断
- 共有ブランチ → 必ずrevert
- 個人ブランチ → reset可能
- 本番環境 → revert一択
Q2:force pushしたら他の人の作業が消えた
A:復旧方法
# reflogから復旧
git reflog
git reset --hard <消えた作業のhash>
git push --force-with-lease
Q3:GitHubでforce pushを禁止したい
A:Branch protection設定
- Settings → Branches
- Add rule → Branch name pattern: main
- Restrict force pushes and deletions にチェック
Q4:間違えてmainにpushしてしまった
A:即座にrevert
git revert HEAD
git push origin main
# その後、正しいブランチで作業
Q5:履歴から完全に削除したい
A:BFG Repo-Cleaner使用
# https://rtyley.github.io/bfg-repo-cleaner/
java -jar bfg.jar --delete-files <file-name>
git push --force
まとめ:状況に応じた正しい選択を
push後のコミット取り消し方法:
優先度 | 方法 | 安全性 | 使用場面 |
---|---|---|---|
1 | git revert | ★★★★★ | 通常はこれ |
2 | 新規コミット | ★★★★☆ | 軽微な修正 |
3 | interactive rebase | ★★☆☆☆ | PR前の整理 |
4 | reset + force | ★☆☆☆☆ | 緊急時のみ |
鉄則:
- 🟢 迷ったらrevert
- 🟡 force pushは最終手段
- 🔴 チームへの通知を忘れない
今すぐできる対策:
- git revert の使い方をマスター
- pre-commitフックの設定
- branch protection の有効化
- チーム内でのルール策定
間違いは誰にでもあります。重要なのは、適切な方法で迅速に対処することです。この記事を参考に、安全で確実な取り消し方法を選択してください!
コメント