「コミットメッセージをtypoした」「Conventional Commitsのprefixを間違えた」「数件前のコミットメッセージを直したい」「push済みメッセージを修正できる?」——Gitのコミットメッセージ修正は、意外とシチュエーションが多様です。直前のコミットか過去のコミットか、push済みか未pushか、共有ブランチか個人ブランチかで、使うコマンドと注意事項が変わります。
この記事では、Gitのコミットメッセージを変更する方法を状況別に整理します。定番のgit commit --amend、過去コミットを修正するgit rebase -iのreword、push済み・共有ブランチでの扱い、一括修正のgit filter-repo、そしてConventional Commitsやコミット規約との付き合い方まで、実務で迷わない形で解説します。
この記事で学べること
- 状況別の最適コマンド:直前/数件前/全履歴/push済み
git commit --amendの正しい使い方とエディタ設定git rebase -iのrewordで過去コミットのメッセージを書き換える方法- push済み個人ブランチでの
--force-with-lease運用 - 共有ブランチで履歴書き換えを避ける現実的な対処
- 全履歴の一括修正に使う
git filter-repo(filter-branchは非推奨) - Conventional Commits・末尾Signed-off-byなどメッセージ規約との付き合い方
まず確認:状況で使うコマンドが決まる
メッセージ変更はどのコミットを修正するかとpush済みかで大きく手順が変わります。
ポイント:メッセージ修正はSHAが変わる履歴書き換え操作です。push前なら気軽に、push後なら慎重に。共有ブランチ(main/develop)ではメッセージ程度のミスは放置するか、追記コミットで補足するのが運用コストに見合います。
直前のコミットメッセージ:git commit –amend
もっとも頻繁に使うのが--amendです。エディタが開いて編集、または-mで直接指定できます。
# エディタで編集(Git設定のeditor が開く) git commit --amend # メッセージを直接指定 git commit --amend -m "fix: トークン有効期限のバグを修正" # エディタは開かず、メッセージは変えずにファイル追加だけしたい git add forgotten_file.py git commit --amend --no-edit # 作者(Author)も一緒に直したい git commit --amend --author="New Name <new@example.com>" # コミット日時も現時点に更新 git commit --amend --no-edit --date=now
amend したあとの状態
- コミットのSHAが変わる(新しいコミットとして作り直される)
- 未pushならそのまま
git pushできる - push済みなら
git push --force-with-leaseが必要 - 元のコミットは
git reflogから90日間辿れる(復元可能)
エディタの設定
# VS Code(--wait でGitが待機) git config --global core.editor "code --wait" # Cursor git config --global core.editor "cursor --wait" # Vim(デフォルト環境が多い) git config --global core.editor vim # nano(初心者向け) git config --global core.editor nano # JetBrains系(IntelliJ IDEA) git config --global core.editor "idea --wait"
注意:GUI系エディタは必ず--wait(VS Code/Cursor)・-w(Sublime Text)のような「終了まで待つ」オプションが必要です。指定しないと、エディタが開いた瞬間にGitが「空のメッセージ」と判断してabortします。
過去のコミット:rebase -i で reword
直前ではなく「3コミット前のメッセージを修正したい」という場合は、git rebase -i(インタラクティブrebase)でreword(短縮r)を指定します。
# 直近5コミットを対象にインタラクティブrebaseを起動 git rebase -i HEAD~5 # 特定のコミットの親から git rebase -i a1b2c3d^ # mainから分岐後すべてを対象に git rebase -i main
エディタでの操作
# エディタに以下のようなリストが表示される pick a1b2c3d feat: ユーザー登録を追加 pick e4f5g6a fix: emailバリデーションを修正 # ← メッセージを直したい pick i7j8k9l docs: README更新 # Commands: # p, pick = コミットを使用 # r, reword = コミットを使用し、メッセージだけ編集 # e, edit = コミットを使用し、修正のために停止 # s, squash = 前のコミットに統合(メッセージ合体) # f, fixup = 前のコミットに統合(メッセージ破棄) # d, drop = コミットを削除 # 変更したいコミットの pick を reword に書き換える pick a1b2c3d feat: ユーザー登録を追加 reword e4f5g6a fix: emailバリデーションを修正 pick i7j8k9l docs: README更新
エディタを保存して閉じると、rewordの対象コミットごとにメッセージ編集用のエディタが開きます。新しいメッセージに書き換えて保存→閉じる、を繰り返し、すべて完了するとrebaseが終了します。
複数コミットのメッセージを一度に編集
# 対象コミット全部 pick を reword に書き換える reword a1b2c3d feat: ユーザー登録を追加 reword e4f5g6a fix: emailバリデーションを修正 reword i7j8k9l docs: README更新 # 保存→閉じる → エディタが順番に開くので順次編集
rebase -i は履歴の書き換え
- 対象コミット以降のSHAがすべて変わる
- 未pushなら安全、push済みなら
--force-with-leaseが必要 - 共有ブランチでは絶対に使わない——他メンバーのローカルが壊れる
- 途中で困ったら
git rebase --abortで開始前に戻れる
rebase途中でエラーになった場合の復旧はリベース途中でエラーになったときの復旧方法、rebaseとmergeの使い分けはrebaseとmergeの違いと使い分けを参照してください。
push済みコミットの扱い
既にリモートに出ているコミットのメッセージを直す場合、ブランチの性質で対応が分かれます。
個人ブランチ:–force-with-lease で安全に反映
# メッセージ修正 git commit --amend -m "新しいメッセージ" # または rebase -i で reword git rebase -i HEAD~3 # 最新リモート情報を取得してから git fetch origin # 安全な強制push git push --force-with-lease origin feature/my-branch
–force-with-lease の安全性
- リモートが自分のローカル
origin/xxxと一致していればpush - 他人が間にpushしていたら拒否されて上書き事故を防止
--forceは無条件上書きで危険、代替として--force-with-leaseを推奨- push関連の詳細はpushを取り消す方法を参照
共有ブランチ(main/develop):修正しないのが原則
禁止:共有ブランチのコミットメッセージを直すための履歴書き換えは行いません。他メンバーのgit pullでコンフリクトが起き、作業が消える事故につながります。メッセージの typo 程度なら放置が原則。どうしても伝えたい補足があれば追記コミットでPR descriptionに書くのが現実的です。
どうしても共有ブランチで修正が必要なとき
# 1. 管理者権限でブランチ保護を一時解除(GitHub設定) # 2. 全メンバーに周知:作業を退避してもらう # 3. amend または rebase -i で修正 git commit --amend -m "修正メッセージ" # 4. --force-with-lease で反映 git fetch origin main git push --force-with-lease origin main # 5. 全メンバーに周知: # 各自:git fetch origin && git reset --hard origin/main
全履歴のメッセージ一括修正:filter-repo
「リポジトリの全履歴で「fix」を「fix:」に揃えたい」といった一括置換はgit filter-repoを使います。旧来のgit filter-branchは公式にも非推奨で、filter-repoが現在の標準です。
# インストール(まだなら) pip install git-filter-repo # ミラーcloneを推奨(安全のため) git clone --mirror https://github.com/user/repo.git repo-mirror cd repo-mirror # コールバックでメッセージ置換 git filter-repo --message-callback ' import re return re.sub(rb"^fix ", b"fix: ", message, flags=re.MULTILINE) ' # 同じプロジェクトの別ディレクトリで作業するなら --force を付ける git filter-repo --force --replace-message ../replacements.txt
警告:filter-repoは全コミットのSHAが変わる破壊的操作です。実行前にミラーcloneでバックアップを取り、チーム全員に通知し、作業を退避してもらってから実行してください。push後は全メンバーが再cloneする必要があります。
filter-branchは非推奨
# 旧 filter-branch の例(使わないでください) # git filter-branch --msg-filter 'sed "s/old/new/g"' HEAD # 新 filter-repo での同等処理 git filter-repo --replace-message expressions.txt # expressions.txt の中身例: # old==>new
filter-branch が非推奨な理由
- 処理速度が数倍〜数十倍遅い
- デフォルトで安全装置が緩く、壊しやすい
- Git公式ドキュメントに非推奨と明記されている
- 機密情報削除も含めて
filter-repoに一本化するのが現代的 - 機密情報削除は履歴に含まれる機密情報を完全に削除する方法も参照
コミット規約との付き合い方
メッセージ修正のよくある理由が「規約違反の修正」です。代表的な規約を押さえておくと、そもそも修正が必要なくなります。
Conventional Commits の基本
feat:(機能追加)/fix:(バグ修正)/docs:(ドキュメント)style:/refactor:/test:/chore:- breaking change は
feat!:やBREAKING CHANGE:フッタで明示 - semantic-release等の自動バージョニングで活躍
- 1行目は50字以内、本文は72字折り返しが慣習
コミットメッセージテンプレート
# リポジトリ/全体のテンプレート作成 cat > ~/.gitmessage.txt << "EOF" # <type>(<scope>): <subject> # # type: feat / fix / docs / style / refactor / test / chore # scope: auth / api / ui など(省略可) # # <body: なぜ変更したかの説明> # # <footer: BREAKING CHANGE / refs #issue など> EOF # グローバル設定 git config --global commit.template ~/.gitmessage.txt # リポジトリ個別 git config commit.template .gitmessage.txt
commit-msg hookで自動検証
# .git/hooks/commit-msg #!/bin/sh pattern="^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .+" msg=$(head -1 "$1") if ! echo "$msg" | grep -qE "$pattern"; then echo "エラー: Conventional Commits形式で書いてください" >&2 echo "例: feat(auth): Add OAuth support" >&2 exit 1 fi
ポイント:規約違反の修正はamendよりcommit前にフック等で予防するのがコストが低いです。husky+commitlint、pre-commit(Python)、simple-git-hooksといったツールでチーム全員の手元で自動チェックできます。
実践シナリオ
シナリオ① 直前のメッセージをtypo修正
# push前の典型パターン git commit --amend -m "fix: ログイン失敗時のエラーメッセージを修正" # push済みの個人ブランチなら git commit --amend -m "..." git push --force-with-lease origin feature/xxx
シナリオ② 3件前のメッセージを書き換え
git rebase -i HEAD~5 # エディタで該当コミットを pick → reword に変更 # 保存して閉じる → メッセージ編集用エディタが開くので書き換えて保存 # 個人ブランチなら強制push git push --force-with-lease origin feature/xxx
シナリオ③ 直前のコミットに Signed-off-by を追加
# 単一コミットのDCO署名を追加 git commit --amend --no-edit --signoff # 過去N件に一括追加 git rebase --exec 'git commit --amend --no-edit --signoff' -i HEAD~5 # rebase -i で全コミットを pick のままにして実行
シナリオ④ 作者情報を直す
# 直前のコミットの作者 git commit --amend --author="Name <email@example.com>" --no-edit # 過去コミットの作者を一括変更(filter-repo) git filter-repo --email-callback ' return email.replace(b"old@example.com", b"new@example.com") '
GUI・IDEでのメッセージ編集
主要ツール
- VS Code / Cursor:Source ControlのCommit欄、Git Graph拡張で過去commit右クリック→
Rebase - JetBrains:Git Log → コミット右クリック →
Edit Commit Message...(未pushのみ) - SourceTree:Log/Historyで過去commit右クリック →
Edit(interactive rebase起動) - GitHub Desktop:History → Amend Commit(最新のみ)
- GitKraken:commit右クリック →
Reword
やってはいけない落とし穴
共有ブランチで履歴書き換えしてforce push
mainやdevelopの過去コミットを--amendやrebase -iで書き換え、force pushすると他メンバーのローカルが壊れます。メッセージ程度のミスは追記コミットで補足するか放置しましょう。GitHub等のBranch protection rulesでforce push禁止を設定しておくと物理的に防止できます。
amend でエディタが開かず空メッセージabort
VS Code等のGUIエディタをGitのcore.editorに設定したのに--waitを付け忘れていると、エディタが開いた瞬間にGitが「空メッセージ」と判定してAborting commit due to empty commit message.となります。git config --global core.editor "code --wait"のように必ず--waitを。
rebase途中で困って状態を複雑にする
rebaseの途中でコンフリクトや想定外のエラーが出たとき、闇雲に追加操作をすると状態が悪化します。困ったらまずgit rebase --abortで開始前に戻れます。詳細はリベース途中でエラーになったときの復旧方法を参照。
filter-branch を使う
Git公式で非推奨とされており、処理速度も安全性もfilter-repoに劣ります。旧記事やStack Overflowの古い回答に従わず、新しく書くならfilter-repoを選びましょう。
amend 後にforce pushせずに普通のpushで失敗
push済みコミットをamendするとリモートとローカルで履歴が食い違います。普通のgit pushはnon-fast-forwardで拒否されるので、git push --force-with-leaseが必要です。詳しくはnon-fast-forwardで拒否されたときの解決方法も参考になります。
よくある質問
--amendは新しいコミットを作り直すのでSHAは必ず変わります。同じブランチで作業中なら問題ありませんが、push済みブランチの場合は--force-with-leaseで反映が必要です。pickをreword(またはr)に書き換えるのが操作の要です。画面下部にコマンド一覧が表示されるのでそれを参照してください。メッセージ変更だけならreword、コミットの内容も直すならedit。rewordだけならコンフリクトは発生しません(メッセージのみ変更)。editやsquashで内容も触るとコンフリクトが起き得ます。衝突ファイルを直してgit add → git rebase --continueで再開、中止したいならgit rebase --abortで元に戻せます。--amend/rebase -i reword+--force-with-leaseで安全に可能。共有ブランチ(main等)では原則修正せず、追記コミットでPR descriptionに補足する運用が無難です。git commit -m "一行目" -m "本文"で-m複数指定、または引数なしのgit commitでエディタを開いて1行目・空行・本文と書くのが基本です。commit.template設定で毎回テンプレートから編集開始もできます。git filter-repo --replace-message <file>で正規表現置換が可能です。全コミットのSHAが変わる破壊的操作なので、必ずミラーcloneで作業し、チームに再clone依頼をセットにしてください。commit.templateでフォーマットを固定、commit-msgフックで検証、commitlint + huskyで自動チェック、が王道です。Conventional Commits準拠にしておくと、セマンティックリリースやCHANGELOG生成に繋がります。関連記事
- 【Git】コミットの取り消し方 — amend含むコミット全般の取り消し
- 【Git】pushを取り消す方法 — push済みへの対処と
--force-with-lease - 【Git】rebaseとmergeの違いと使い分け — rebase運用の基礎
- 【Git】リベース途中でエラーになったときの復旧方法 — rebase -i中のトラブル対処
- 【Git】pushしようとしたら”non-fast-forward”で拒否されたときの解決方法 — amend後のpushエラー対処
- 【Git】履歴に含まれる機密情報を完全に削除する方法 — filter-repoの応用
- 【Git】特定のコミットまで戻す方法 — コミット単位の戻し方
- 【Git】よく使うgitコマンドまとめ — 日常コマンドの早見表
まとめ
- 直前のメッセージ修正は
git commit --amend、過去はgit rebase -i+reword - どちらもSHAが変わる履歴書き換え——未pushなら気軽、push済みは
--force-with-lease - 共有ブランチは原則修正しない。追記コミットやPR descriptionで補足
- 一括置換は
git filter-repo(filter-branchは非推奨) - GUIエディタ設定は
--wait必須 - そもそも間違えないよう
commit.template+commit-msgフックで予防 - Conventional Commits準拠にするとツール連携(semantic-release等)が便利
コミットメッセージ修正は、Gitの履歴書き換え操作の中では比較的軽微ですが、「SHAが変わる=push済みなら--force-with-lease必要」という原則は必ず意識してください。修正よりもむしろcommit前の予防(テンプレート・フック・Conventional Commits)に投資する方が、長期的にはチーム全体のコストを下げます。それでも修正が必要になったら、この記事のコマンドを状況別に使い分けて、きれいな履歴を保ちましょう。

