【Git】git スカッシュとは?コミット履歴を整理する方法をわかりやすく解説
はじめに
git スカッシュ は、複数のコミットをまとめて1つのコミットに統合する方法を指します。
実務の現場でコードレビューを受けるときや、プルリクエスト(Pull Request)を出す前に履歴を整える際に便利です。
ブランチを切って作業しているうちにコミットの粒度が細かくなりすぎてしまい、後から見返すと履歴がわかりにくくなることはないでしょうか。
そんなときに役立つのが、いわゆる「コミットのスカッシュ」です。
ただし、過度にコミットをまとめすぎると履歴自体の意味を失ってしまう可能性があります。
状況に応じて、必要最低限のコミット単位にまとめるのがポイントです。
ここでは、初心者が実務に入ったときに役立つスカッシュの基本的な使い方や注意点を紹介していきます。
この記事を読むとわかること
- git スカッシュの概要
- 基本的な操作方法(rebase -i など)の手順
- 実務でコミット履歴を整理するときの流れ
- 初心者が気をつけるべき注意点
git スカッシュとは何か
git スカッシュ は、Gitのバージョン管理機能を活用して複数のコミットを1つにまとめる操作です。
元々のコミットは履歴上で合体された形となり、新しいコミットとして再作成されます。
コミット履歴をすっきりさせる
作業ブランチでコミットを重ねていると、1コミットあたりの変更量が少なく断片的になりがちです。
レビューする側からすれば、コミットの塊があまりに細かいと全体像を掴むのに時間がかかるかもしれません。
スカッシュ によって主要な変更点だけをピックアップしてコミットをまとめると、あとから履歴を追いやすくなります。
同僚と共同開発するときにも「どのタイミングで何が変わったか」を把握しやすくなり、コードレビューの効率もあがるでしょう。
メリットと注意点
メリット
- 履歴がシンプルになり、コミットメッセージの読みやすさが向上する
- レビューの対象コミットが絞られ、開発チーム間のコミュニケーションがスムーズになる
- 過去の変更点を追うときに迷いにくい
注意点
- コミット履歴を「書き換える」操作なので、公共のリポジトリ(すでに他の人が取得済みのコミット)に対して行うと混乱を招く場合がある
- 過去のコミットメッセージが失われる可能性がある
- 合理的な単位でのコミットをまとめないと、変更の意図を見失う場合がある
スカッシュの目的 は「わかりやすい履歴を残すこと」です。
便利だからといって、すべてまとめてしまうとコミットの意味が消えてしまう恐れがあります。
作業時の事情を適度に残しつつ、不要なコミットを統合するのがおすすめです。
git スカッシュの基本的なやり方
git スカッシュ にはいくつかのやり方がありますが、代表的なのが インタラクティブリベース(git rebase -i) です。 ここでは、作業ブランチでいくつかコミットを重ねた後、それらをまとめる流れをみていきましょう。
インタラクティブリベースを使う
次のように HEAD~3
の部分を指定して、直近3つのコミットをまとめる例を考えてみます。
git rebase -i HEAD~3
上記コマンドを実行すると、エディタが立ち上がり、対象のコミットが一覧表示されます。
通常はコミット日時が新しいものが上にくるので、その並び順で操作するイメージです。
エディタに表示されたコミットの行頭にあるコマンドを pick
から squash
または s
に変更すると、そのコミットは直前のコミットにまとめられる形になります。
まとめたいコミットが3つあるなら、そのうち最初のコミットは pick
のままにし、残りの2つを squash
にするのが一般的です。
例として、以下のようなリストが表示されるかもしれません。
pick a1b2c3d Fix header layout pick 9a8b7c6 Update footer link pick 5e4f3d2 Remove unused variable
この場合、最初の pick a1b2c3d Fix header layout
を残して、残りのコミットを squash
に書き換えます。
pick a1b2c3d Fix header layout squash 9a8b7c6 Update footer link squash 5e4f3d2 Remove unused variable
変更を保存してエディタを閉じると、次にスカッシュしたコミットメッセージを編集する画面が出るはずです。
そこで、新しいコミットメッセージをまとめて編集して保存します。
これにより、直近3つのコミットが1つにまとめられて再コミットされます。
スカッシュ後の履歴を確認する
インタラクティブリベースが正常に完了したら、以下のようにして履歴を確認してみてください。
git log --oneline
ここで、先ほどの3つのコミットが1つのコミットにまとまっていれば成功です。
この状態で、履歴が整理されたブランチをプッシュするときは、強制プッシュ(git push -f
)が必要になるケースがあります。
なぜならばコミット履歴を書き換えたことで、リモートの履歴と食い違いが発生するためです。
ただし、強制プッシュ はチーム開発において他のメンバーの作業に影響する可能性があるため注意が必要です。
実務でのよくある利用シーン
実務の中でどんな場面で git スカッシュ
が役立つのか、いくつか具体例を挙げます。
新機能をまとめて開発したいとき
新しく機能を実装するとき、何度もコミットを重ねることが多いでしょう。
試行錯誤のコミットが大量にあると、後からレビューしても履歴が煩雑です。
仕上げの段階で不要な試行錯誤のコミットをスカッシュすると、本当に必要な変更点だけが見えやすくなります。
レビュー前の最終調整
他人にレビューを依頼する前にコミット履歴を整えておきたい場合、細かい修正コミットをまとめることがあります。
誤字修正やコメント修正のような内容まで1コミットとして残すと煩雑になるため、スカッシュで合体してからプルリクエストを作成するわけです。
過去のコミットを整理して可読性を高める
すでに開発が完了した部分で、どうしてもコミットが細かすぎる場合もあるでしょう。
この場合、履歴を再編集することで可読性が上がり、履歴に対する理解度を高められます。
ただし、既にリモートにプッシュされ、他の人がそのブランチを使っているなら要注意です。
コミット書き換え操作は慎重に行うのが大切です。 特にメンバーと共有中のリポジトリでスカッシュを行う場合は、他の人のブランチに影響が及ぶリスクがあります。
git スカッシュとマージコミットの違い
Gitには、コミットを統合する方法として「マージコミットを作る」手段もあります。
マージコミットとは、複数のブランチを統合するときに自動生成される特別なコミットです。
マージコミット
- 複数ブランチの作業結果を統合するための特別なコミット
- どのブランチとどのブランチをいつマージしたかがわかる
- ブランチを分岐した履歴を保持しやすいが、コミット履歴が増える傾向がある
スカッシュ
- 複数のコミットを1つにまとめる
- 履歴の細切れを整理できる
- 過去のコミットを書き換えるため、履歴の分岐点がわかりにくくなる側面もある
実務では、マージコミットを残すのか、それともスカッシュして1つのコミットにするのかは、プロジェクトの方針やレビューのしやすさによって異なります。
チームの中で「原則としてブランチごとにひとまとまりのコミットにしておく」というルールがあるなら、スカッシュを意図的に使うことが多いでしょう。
スカッシュ操作の手順詳細
前述の git rebase -i
で行う操作を、やや詳しくみていきましょう。
1. ブランチを最新の状態にする
スカッシュ作業を行うブランチが、リモートやメインブランチと差分が少ない状態であることが望ましいです。
なるべくコンフリクトを減らすためにも、事前にメインブランチ(master や main)を取り込んでおくケースが多いです。
git checkout feature/new-feature git fetch origin git merge origin/main # あるいは rebase で更新する方法もあります
2. インタラクティブリベースコマンドの実行
たとえば直近5件のコミットをまとめたいなら HEAD~5
と指定します。
git rebase -i HEAD~5
ここでは、最新のコミットから5個前までが対象になるイメージです。
3. エディタでコミットを操作
エディタに表示されたコミット一覧を編集します。
コミットを残したい行だけ pick
にしておき、それ以外の行を squash
(または s
) にします。
pick 1111111 Add login form squash 2222222 Fix CSS for login form squash 3333333 Refactor: rename variables pick 4444444 Implement logout feature squash 5555555 Update error handling
この例では「1111111」と「4444444」はそれぞれ独立したコミットとして残し、それ以外は直前のコミットとまとめます。
4. スカッシュ後のコミットメッセージ編集
エディタを閉じると、スカッシュしたコミットをまとめて書き込むためのメッセージ編集画面が出ます。
必要に応じてコメントアウトされている元のコミットメッセージを組み合わせながら編集すると、変更内容がわかりやすいメッセージにできます。
5. コンフリクトが発生したら解消する
スカッシュ対象のコミット同士で競合するファイルがあれば、リベースの途中でコンフリクトが起こることがあります。
その場合はファイルを修正してから git add .
して、git rebase --continue
を実行してください。
# 競合ファイルを修正してステージング git add conflicted_file.html # リベースを続行 git rebase --continue
6. スカッシュ完了後のプッシュ
リモートにまだプッシュしていないローカル作業なら、ふつうに git push
するだけでOKです。
しかし、すでにリモートにプッシュ済みのコミットをスカッシュした場合は、git push -f
で強制的に上書きする必要があります。
ここはチーム開発では特にトラブルのもとになりやすいので、必ず確認をとりましょう。
他の開発者が既にスカッシュ前のコミットを使って作業を進めている場合、強制プッシュによる履歴書き換えは大きな混乱を招きます。 作業中のブランチならばまだしも、共有されているメインブランチでのスカッシュは慎重に検討しましょう。
よくある質問と対処法
Q1. スカッシュするべきコミットが多すぎるんですが?
A1. 一度にまとめすぎるよりも、ある程度のグルーピングをして段階的にスカッシュする方がベターです。
あまりにも大量のコミットがある場合は、途中で要点ごとに分割しておくと履歴の意味を保ちやすいです。
Q2. すでにリモートにプッシュしているブランチもスカッシュしていいですか?
A2. 原則としてチームルール次第ですが、他のメンバーがリポジトリをpullしていない段階なら、そこまで大きな問題にはなりにくいです。
一方、みんながそのブランチを活用しているタイミングでスカッシュしてしまうと、全員が履歴の整合性を取り直す必要が出てくるかもしれません。
Q3. マージコミットも含めてスカッシュできますか?
A3. 可能ですが、マージコミットまでスカッシュすると履歴がさらに複雑になる場合があります。
特に大規模開発でブランチが何本もある場合は、どこで何がマージされたかが見えなくなる恐れがあるので注意しましょう。
まとめ
git スカッシュ は、開発の履歴をきれいに整理する強力な方法です。
とりわけ、試行錯誤や細かい修正を多く含むブランチをコミット1つにまとめたい場合に重宝します。
一方で、コミットの歴史を書き換える行為でもあるため、他のメンバーと協力して作業をしている現場では注意点が多いです。
特にリモートにプッシュ後のブランチをスカッシュする際は、チーム内で「なぜスカッシュが必要なのか」を共有して、トラブルを避けるようにしましょう。
どんなにスカッシュを駆使しても、すべてのコミットを1つにまとめればいいわけではありません。
最終的なコミットメッセージから変更の意図が伝わるよう、合理的な単位でまとめるのがポイントです。
コミットを丁寧にまとめていくことで、あとから自分や他のメンバーが履歴を辿りやすくなり、開発全体の見通しが良くなるでしょう。