1.2 履歴の操作と修正
前のセクションで add → commit → push の基本フローを学びました。
でも実際の開発では「やっぱり取り消したい」「あのコミットだけ持ってきたい」といった場面がたくさんあります。
この章では、そんなときに使う 履歴の操作・修正コマンド をひとつずつ見ていきましょう 🛠️
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
基本的な使い方
Section titled “基本的な使い方”# 作業ディレクトリの変更を取り消す(add前)git restore style.css
# ステージングから外す(add後、編集内容は作業ディレクトリに残る)git restore --staged style.css
# 両方を一度に戻す(ステージングも作業ディレクトリも元に戻す)git restore --staged --worktree style.cssreset ─ コミットを取り消す
Section titled “reset ─ コミットを取り消す”「コミットしちゃったけど、やっぱりやり直したい」
そんなときは git reset の出番です。
3つのモードを理解する
Section titled “3つのモードを理解する”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 | 取り消す | 戻る | 戻る | すべてなかったことにしたい |
# 直前のコミットを取り消す(変更は残る)git reset --soft HEAD~1
# 直前の2つのコミットを取り消す(変更は残る)git reset --soft HEAD~2
# 直前のコミットを完全に取り消す(変更も消える)git reset --hard HEAD~1cherry-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
基本的な使い方
Section titled “基本的な使い方”# 特定のコミットを今のブランチに取り込むgit cherry-pick a1b2c3d
# 複数のコミットを取り込むgit cherry-pick a1b2c3d e4f5g6h
# 取り込むが、コミットせずステージングに留めるgit cherry-pick --no-commit a1b2c3dコミットハッシュの調べ方
Section titled “コミットハッシュの調べ方”# 取り込みたいコミットがあるブランチの履歴を確認git log --oneline feature-xe4f5g6h (feature-x) バリデーション追加a1b2c3d ログインAPI連携 ← このコミットが欲しい!commit —amend ─ 直前のコミットを修正する
Section titled “commit —amend ─ 直前のコミットを修正する”「コミットメッセージを間違えた」「ファイルを1つ入れ忘れた」
そんなときは --amend で直前のコミットを修正できます。
メッセージだけ修正
Section titled “メッセージだけ修正”git commit --amend -m "fix: 正しいコミットメッセージに修正"ファイルを追加してコミットし直す
Section titled “ファイルを追加してコミットし直す”# 忘れていたファイルをステージングgit add forgotten-file.js
# 直前のコミットに含める(メッセージはそのまま)git commit --amend --no-editflowchart LR
A["コミット A
(間違いあり)"] -- "git commit --amend" --> B["コミット A'
(修正済み)"]
style A fill:#FFEBEE,stroke:#E53935,color:#B71C1C
style B fill:#E8F5E9,stroke:#43A047,color:#1B5E20
stash ─ 作業を一時退避する
Section titled “stash ─ 作業を一時退避する”「今の作業を中断して、別のブランチで急ぎの対応をしたい」
でもコミットするほどではない…。
そんなときに 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
基本的な使い方
Section titled “基本的な使い方”# 今の変更を一時退避git stash
# メッセージ付きで退避(あとで見分けやすい)git stash -m "ログインページの途中"
# 退避した一覧を確認git stash liststash@{0}: On feature/login: ログインページの途中stash@{1}: WIP on develop: ヘッダー修正中# 最新の stash を復元して削除git stash pop
# 最新の stash を復元(削除しない)git stash apply
# 特定の stash を復元git stash pop stash@{1}
# stash を削除git stash drop stash@{0}
# すべての stash を削除git stash clearmerge —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つのコミットにまとめて 取り込めます。
基本的な使い方
Section titled “基本的な使い方”# feature ブランチの変更をまとめて取り込むgit merge --squash feature/add-login-page
# まとめた変更をコミット(自分でメッセージを書く)git commit -m "feat: ログインページ機能を追加"通常の merge との比較
Section titled “通常の merge との比較”| 項目 | git merge | git merge --squash |
|---|---|---|
| コミット履歴 | すべて残る | 1つにまとまる |
| マージコミット | 作られる | 作られない |
| 元ブランチとの関連 | 保持される | 切れる |
| 使いどころ | 履歴を残したいとき | 履歴をきれいにしたいとき |
rebase ─ 履歴を整理する
Section titled “rebase ─ 履歴を整理する”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 の最新の後ろに 付け替えられます。
基本的な使い方
Section titled “基本的な使い方”# feature ブランチにいる状態でgit rebase developrebase -i(インタラクティブ)で履歴を編集
Section titled “rebase -i(インタラクティブ)で履歴を編集”rebase -i を使うと、コミットの 並べ替え・統合・修正・削除 ができます。
# 直近の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 つにまとまります。
まとめ:コマンド早見表
Section titled “まとめ:コマンド早見表”| コマンド | 用途 | 安全度 |
|---|---|---|
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前のみ |