Gitを使用したロールバック、resetとrevertの違い

.gitignoreで追跡対象外のファイルは別で対応

.gitignoreでphp.iniや.htaccessが追跡対象外になっているため、Git操作だけでは不十分で、FTPでの個別ファイル操作が必要

Git resetについて

git resetは、リポジトリの状態を以前のコミットに戻すコマンドです。主に3つの異なるモードがあります:

リポジトリ commit した状態 ステージング add した状態 ワーキングツリー 作業中の場所 –soft –mixed –hard
  1. git reset –soft
git reset --soft [コミットハッシュ]
  • 変更点: HEADの位置だけを変更します
  • ステージングエリア: 変更されません
  • ワーキングディレクトリ: 変更されません
  • 用途: コミットをやり直したい場合に使用します
  • 結果: 指定したコミットとHEAD間の変更がステージングエリアに残り、再コミットできます

HEAD はローカルの概念!

結論HEADローカルリポジトリでのみ使われる用語 で、現在チェックアウトされているコミットを指す
origin とは違うorigin はリモートリポジトリ(GitHub など)を指す。

  1. git reset –mixed (デフォルト)
git reset [コミットハッシュ]
git reset --mixed [コミットハッシュ]
  • 変更点: HEADの位置とステージングエリアを変更します
  • ステージングエリア: 指定したコミットの状態に戻ります
  • ワーキングディレクトリ: 変更されません
  • 用途: コミットとステージングをやり直したい場合
  • 結果: 変更は保持されますが、コミット前の状態(unstaged)になります
  1. git reset –hard

hardは全部なかったことにする

git reset --hard [コミットハッシュ]
  • 変更点: HEAD、ステージングエリア、ワーキングディレクトリすべてを変更します
  • ステージングエリア: 指定したコミットの状態に戻ります
  • ワーキングディレクトリ: 指定したコミットの状態に戻ります(未保存の変更はすべて失われます)
  • 用途: 完全に過去の状態に戻したい場合
  • 結果: すべての変更が失われ、指定したコミットの状態に完全に戻ります
Git Resetの種類と動作 凡例: コミット ステージング ワーキングツリー 初期状態 –soft –mixed –hard C1 C2 C3 C4 C5 HEAD ステージ ファイル C1 C2 C3 C4 C5 HEAD ステージ ファイル C1 C2 C3 C4 C5 HEAD ステージ ファイル C1 C2 C3 C4 C5 HEAD ステージ ファイル git reset –soft git reset –mixed git reset –hard

Git resetのロールバック手順:–hardオプションの推奨理由

Webサイトのロールバックを行う場合、git reset --hardオプションを使用することを強く推奨します。

  1. ロールバック対象のコミットハッシュを確認
git log

コミットの履歴が表示されるので、ロールバック先の安定していたコミットのハッシュ値を確認します。

  1. ハードリセットを実行
git reset --hard [安定していたコミットのハッシュ]

これにより、リポジトリ、ステージングエリア、ワーキングディレクトリすべてが指定したコミット時点の状態に完全に戻ります。

  1. リモートリポジトリに変更を強制的に反映
git push -f origin [現在のブランチ名]

git push -fの本質は「履歴を消して上書きする」ことにあり、これによって履歴に依存しない更新が可能になります。

git push -f の動作 ローカルリポジトリ リモートリポジトリ 開始状態: コミット: A → B → C (現在の状態) コミット: A → B → C (現在の状態) ローカルでリセット: コミット: A → D (リセット後の状態) git reset –hard git push -f origin [ブランチ名] コミット: A → D (B, Cは消去された)

強制プッシュはGitの履歴を書き換える強力なコマンドですが、適切に使用すれば問題を解決する効果的な手段になります。特にロールバックのような緊急対応時には非常に役立ちます

通常のpushと強制push (push -f) の比較 通常のpush(履歴依存) 強制push(git push -f) 初期状態 ローカル: A→B リモート: A→B→C 初期状態 ローカル: A→D リモート: A→B→C git push の試行 エラー: リモートに新しいコミットがあります 先にgit pullでリモートの変更を取り込む必要あり git push -f の試行 成功: リモートブランチを強制更新しました 注意: リモートの履歴が上書きされました 解決策: git pull & merge 1. git pull でリモートの変更を取得 2. マージまたはリベース 最終状態: ローカル & リモート: A→B→C→D 結果: 履歴の上書き 1. BとCのコミットは消去される 2. リモートの履歴がローカルに合わせられる 最終状態: ローカル & リモート: A→D git push -f: 履歴依存を無視して強制的に更新(チーム開発では注意が必要)

  1. 本番サーバーで変更を取得・適用
cd [Webサイトのディレクトリ]
git pull

–hardオプションを推奨する理由

  • リポジトリ、ステージング、ワーキングディレクトリの全てが完全にリセットされ、確実に安定状態に戻ります
  • 部分的なリセット(–soft/–mixed)では問題のある変更が残る可能性があり、トラブルシューティングには不向きです
  • 障害対応では「確実に動作していた時点」に完全に戻すことが最も安全な方法です

git resetとgit revertの主な違い

git resetgit revert
コミット履歴を実際に書き換えます既存のコミット履歴はそのまま保持します
対象のコミットまで戻り、それ以降のコミットを削除します対象コミットの変更を打ち消す新しいコミットを作成します
履歴を安全に修正できます
通常はプッシュ済みの共有ブランチには使用しません共有リポジトリでも安全に使えます
git reset と git revert の違い 元のコミット履歴 A B C D E F (HEAD→master) git reset –hard C A B C (HEAD→master) D, E, F は履歴から削除される git revert D A B C D E F G (HEAD→master) Gは「Dの逆の変更」を加えるコミット • reset: 履歴を書き換え、指定したコミット以降を削除する • revert: 履歴はそのままで、指定コミットを打ち消す新コミットを作成

Git resetとpush -fの練習方法

Git resetやforce pushの操作を安全に練習するには、以下のような方法があります。これらは実際の本番環境に影響を与えずに練習できる方法です。

1. ローカルでの練習環境を作る

# 練習用ディレクトリを作成
mkdir git-practice
cd git-practice

# 新しいGitリポジトリを初期化
git init

# いくつかファイルを作成してコミット
echo "初めてのファイル" > file1.txt
git add file1.txt
git commit -m "最初のコミット"

echo "2つ目のファイル" > file2.txt
git add file2.txt
git commit -m "2つ目のコミット"

echo "3つ目のファイル" > file3.txt
git add file3.txt
git commit -m "3つ目のコミット"

# コミット履歴を確認
git log --oneline

2. リモートリポジトリをシミュレート

# 別のディレクトリに裸のリポジトリを作成(これがリモートの役割)
cd ..
mkdir remote-repo.git
cd remote-repo.git
git init --bare

# 元のリポジトリに戻り、リモートとして追加
cd ../git-practice
git remote add origin ../remote-repo.git

# リモートにプッシュ
git push -u origin master
Git練習環境のセットアップ ステップ1: ローカル練習リポジトリの作成 mkdir git-practice && cd git-practice git init 空のローカルリポジトリ ステップ2: テストコミットの作成 echo “ファイル1” > file1.txt && git add file1.txt && git commit -m “コミット1” echo “ファイル2” > file2.txt && git add file2.txt && git commit -m “コミット2” コミット履歴: A→B ステップ3: 疑似リモートリポジトリの作成 cd .. && mkdir remote-repo.git && cd remote-repo.git git init –bare cd ../git-practice git remote add origin ../remote-repo.git 裸のリモートリポジトリ

3. git resetとforce pushの練習

# 履歴を確認
git log --oneline

# 1つ前のコミットに戻す
git reset --hard HEAD~1

# 履歴を確認(最新のコミットが消えているはず)
git log --oneline

# 強制プッシュ
git push -f origin master
Git Reset と Force Push の練習シナリオ 練習シナリオ:初期状態 A B C A: 最初のコミット B: 機能追加 C: バグ混入 ローカル: A→B→C リモート: A→B→C 練習シナリオ:ローカルでのリセット # リセット前に履歴確認 git log –oneline git reset –hard HEAD~1 # 1つ前のコミットに戻す A B C 削除済 練習シナリオ:強制プッシュ # 通常のプッシュ(失敗する) git push origin master # エラー: リモートに新しいコミットがあります # 強制プッシュで解決 git push -f origin master リモートリポジトリの状態: A→B(Cは消去)

4. チーム開発をシミュレーション

# 別のディレクトリにクローンして別のユーザーをシミュレート
cd ..
mkdir teammate
cd teammate
git clone ../remote-repo.git .

# 変更を加えてコミット
echo "チームメイトの変更" > teammate-file.txt
git add teammate-file.txt
git commit -m "チームメイトの変更"

# リモートにプッシュ
git push origin master
チーム開発シミュレーション 開発者1(あなた) 開発者2(チームメイト) ステップ1: リポジトリ作成 git init & コミット作成 ステップ1: クローン git clone ../remote-repo.git ステップ2: 機能Xを開発 git commit & git push ステップ2: プル & 機能Y開発 git pull & git commit ステップ3: バグ発見・リセット git reset –hard HEAD~1 git push -f origin master ステップ3: 機能Yを完成させる 開発を継続 (プルはまだしていない) 結果: 履歴がクリーンに 履歴: 機能Xのコミットはなし バグは除去された このまま新機能を実装 問題: プッシュできない git push でエラー発生 「リモート履歴が変更された」 開発者1に連絡が必要

そして元のディレクトリに戻って、どのように競合が発生するかを観察できます。

オンラインの練習サービス

Learn Git Branching
https://learngitbranching.js.org/?locale=ja