コンテンツにスキップ

1.2 履歴の操作と修正

前のセクションで addcommitpush の基本フローを学びました。
でも実際の開発では「やっぱり取り消したい」「あのコミットだけ持ってきたい」といった場面がたくさんあります。

この章では、そんなときに使う 履歴の操作・修正コマンド をひとつずつ見ていきましょう 🛠️


restore ─ 作業ディレクトリの変更を取り消す

Section titled “restore ─ 作業ディレクトリの変更を取り消す”

「ファイルを編集したけど、やっぱり元に戻したい」
そんなときに使うのが git restore です。

flowchart LR
    subgraph "取り消したい場所はどこ?"
        A["🖥️ 作業ディレクトリの変更
まだ add していない"] -- "git restore" --> A2["元に戻る"] B["📋 ステージングの変更
add したけど取り消したい"] -- "git restore --staged" --> B2["ステージングから外れる
(編集内容は残る)"] end style A fill:#FFF9C4,stroke:#F9A825,color:#F57F17 style B fill:#E3F2FD,stroke:#1E88E5,color:#0D47A1 style A2 fill:#E8F5E9,stroke:#43A047,color:#1B5E20 style B2 fill:#E8F5E9,stroke:#43A047,color:#1B5E20
Terminal window
# 作業ディレクトリの変更を取り消す(add前)
git restore style.css
# ステージングから外す(add後、編集内容は作業ディレクトリに残る)
git restore --staged style.css
# 両方を一度に戻す(ステージングも作業ディレクトリも元に戻す)
git restore --staged --worktree style.css

「コミットしちゃったけど、やっぱりやり直したい」
そんなときは git reset の出番です。

reset には 3 つのモードがあり、どこまで巻き戻すか が異なります。

flowchart TD
    C["コミット済みの状態"]

    C -- "git reset --soft HEAD~1" --> S1["コミットだけ取り消し"]
    C -- "git reset --mixed HEAD~1" --> S2["コミット+ステージングを取り消し"]
    C -- "git reset --hard HEAD~1" --> S3["すべて取り消し"]

    style C fill:#FFF3E0,stroke:#FB8C00,color:#E65100
    style S1 fill:#E8F5E9,stroke:#43A047,color:#1B5E20
    style S2 fill:#E3F2FD,stroke:#1E88E5,color:#0D47A1
    style S3 fill:#FFEBEE,stroke:#E53935,color:#B71C1C
モードコミットステージング作業ディレクトリ使いどころ
--soft取り消す残る残るコミットメッセージだけ直したい
--mixed(デフォルト)取り消す戻る残るadd からやり直したい
--hard取り消す戻る戻るすべてなかったことにしたい
Terminal window
# 直前のコミットを取り消す(変更は残る)
git reset --soft HEAD~1
# 直前の2つのコミットを取り消す(変更は残る)
git reset --soft HEAD~2
# 直前のコミットを完全に取り消す(変更も消える)
git reset --hard HEAD~1

cherry-pick ─ 特定のコミットだけ取り込む

Section titled “cherry-pick ─ 特定のコミットだけ取り込む”

「別のブランチにある あのコミットだけ 欲しい」
そんなときに使うのが git cherry-pick です。

gitGraph
    commit id: "A"
    commit id: "B"
    branch feature-x
    checkout feature-x
    commit id: "C (これが欲しい)" type: HIGHLIGHT
    commit id: "D"
    checkout main
    commit id: "E"
    commit id: "C' (cherry-pick)" type: HIGHLIGHT
Terminal window
# 特定のコミットを今のブランチに取り込む
git cherry-pick a1b2c3d
# 複数のコミットを取り込む
git cherry-pick a1b2c3d e4f5g6h
# 取り込むが、コミットせずステージングに留める
git cherry-pick --no-commit a1b2c3d
Terminal window
# 取り込みたいコミットがあるブランチの履歴を確認
git log --oneline feature-x
e4f5g6h (feature-x) バリデーション追加
a1b2c3d ログインAPI連携 ← このコミットが欲しい!

commit —amend ─ 直前のコミットを修正する

Section titled “commit —amend ─ 直前のコミットを修正する”

「コミットメッセージを間違えた」「ファイルを1つ入れ忘れた」
そんなときは --amend で直前のコミットを修正できます。

Terminal window
git commit --amend -m "fix: 正しいコミットメッセージに修正"

ファイルを追加してコミットし直す

Section titled “ファイルを追加してコミットし直す”
Terminal window
# 忘れていたファイルをステージング
git add forgotten-file.js
# 直前のコミットに含める(メッセージはそのまま)
git commit --amend --no-edit
flowchart LR
    A["コミット A
(間違いあり)"] -- "git commit --amend" --> B["コミット A'
(修正済み)"] style A fill:#FFEBEE,stroke:#E53935,color:#B71C1C style B fill:#E8F5E9,stroke:#43A047,color:#1B5E20

「今の作業を中断して、別のブランチで急ぎの対応をしたい」
でもコミットするほどではない…。
そんなときに git stash が活躍します。

flowchart LR
    A["✏️ 作業中の変更"] -- "git stash" --> B["📦 一時退避
(stash)"] B -- "git stash pop" --> C["✏️ 変更が復元される"] style A fill:#FFF9C4,stroke:#F9A825,color:#F57F17 style B fill:#E3F2FD,stroke:#1E88E5,color:#0D47A1 style C fill:#E8F5E9,stroke:#43A047,color:#1B5E20
Terminal window
# 今の変更を一時退避
git stash
# メッセージ付きで退避(あとで見分けやすい)
git stash -m "ログインページの途中"
# 退避した一覧を確認
git stash list
stash@{0}: On feature/login: ログインページの途中
stash@{1}: WIP on develop: ヘッダー修正中
Terminal window
# 最新の stash を復元して削除
git stash pop
# 最新の stash を復元(削除しない)
git stash apply
# 特定の stash を復元
git stash pop stash@{1}
# stash を削除
git stash drop stash@{0}
# すべての stash を削除
git stash clear

merge —squash ─ 複数コミットをまとめて取り込む

Section titled “merge —squash ─ 複数コミットをまとめて取り込む”

「他のブランチの変更を取り込みたいけど、コミット履歴はまとめたい」
そんなときに merge --squash を使います。

gitGraph
    commit id: "A"
    commit id: "B"
    branch feature
    checkout feature
    commit id: "C: ログイン画面"
    commit id: "D: バリデーション"
    commit id: "E: スタイル修正"
    checkout main
    commit id: "F: squash merge" type: HIGHLIGHT

通常の merge ではすべてのコミットがそのまま取り込まれますが、
--squash を使うと 1つのコミットにまとめて 取り込めます。

Terminal window
# feature ブランチの変更をまとめて取り込む
git merge --squash feature/add-login-page
# まとめた変更をコミット(自分でメッセージを書く)
git commit -m "feat: ログインページ機能を追加"
項目git mergegit merge --squash
コミット履歴すべて残る1つにまとまる
マージコミット作られる作られない
元ブランチとの関連保持される切れる
使いどころ履歴を残したいとき履歴をきれいにしたいとき

rebase は Git の中でも強力なコマンドです。
コミットの「土台(ベース)」を付け替える ことで、履歴をきれいに整理できます。

rebase の基本:ブランチの起点を移動する

Section titled “rebase の基本:ブランチの起点を移動する”
%%{init: { 'gitGraph': { 'mainBranchName': 'develop' } } }%%
gitGraph
    commit id: "A"
    commit id: "B"
    branch feature
    checkout feature
    commit id: "C"
    commit id: "D"
    checkout develop
    commit id: "E (新しいコミット)"
    commit id: "F"

この状態で feature ブランチから git rebase develop を実行すると…

%%{init: { 'gitGraph': { 'mainBranchName': 'develop' } } }%%
gitGraph
    commit id: "A"
    commit id: "B"
    commit id: "E"
    commit id: "F"
    branch feature
    checkout feature
    commit id: "C' (rebase後)"
    commit id: "D' (rebase後)"

feature ブランチのコミットが、develop の最新の後ろに 付け替えられます

Terminal window
# feature ブランチにいる状態で
git rebase develop

rebase -i(インタラクティブ)で履歴を編集

Section titled “rebase -i(インタラクティブ)で履歴を編集”

rebase -i を使うと、コミットの 並べ替え・統合・修正・削除 ができます。

Terminal window
# 直近の3つのコミットを編集
git rebase -i HEAD~3

エディタが開き、以下のような画面が表示されます。

pick a1b2c3d feat: ログインフォーム追加
pick e4f5g6h fix: バリデーションのtypo修正
pick i7j8k9l style: インデント修正
コマンド動作
pickそのまま使う
rewordコミットメッセージだけ変更
squash前のコミットとまとめる(メッセージ編集あり)
fixup前のコミットとまとめる(メッセージは破棄)
dropコミットを削除

例:細かいコミットをまとめる

Section titled “例:細かいコミットをまとめる”
pick a1b2c3d feat: ログインフォーム追加
fixup e4f5g6h fix: バリデーションのtypo修正
fixup i7j8k9l style: インデント修正

これで 3 つのコミットが 1 つにまとまります


コマンド用途安全度
git restore <file>作業ディレクトリの変更を取り消す⚠️ 変更が消える
git restore --staged <file>ステージングを取り消す✅ 安全
git reset --soft HEAD~1コミットだけ取り消す✅ 安全
git reset --hard HEAD~1すべて取り消す🔴 要注意
git cherry-pick <hash>特定コミットを取り込む✅ 安全
git commit --amend直前のコミットを修正⚠️ push前のみ
git stash変更を一時退避✅ 安全
git stash pop退避した変更を復元✅ 安全
git merge --squash <branch>まとめて取り込む✅ 安全
git rebase <branch>履歴を付け替える🔴 push前のみ
git rebase -i HEAD~n履歴を対話的に編集🔴 push前のみ