DEV Community

vast cow
vast cow

Posted on

How to Squash Past Commits with Git Rebase

Squashing commits with Git’s rebase command is useful when you want to clean up your commit history. Here’s a step-by-step guide.


1. Check Which Commits to Squash

First, review the commit log to decide which commits you want to combine:

git log --oneline
Enter fullscreen mode Exit fullscreen mode

Example:

a1b2c3d Fix typo
d4e5f6g Add feature X
h7i8j9k WIP: implement feature X
...
Enter fullscreen mode Exit fullscreen mode

Suppose you want to squash Add feature X and WIP: implement feature X.


2. Start an Interactive Rebase

Run git rebase -i using the commit before the ones you want to squash as the base:

git rebase -i <base_commit_id>
Enter fullscreen mode Exit fullscreen mode

In this case, if a1b2c3d is the commit before, you would run:

git rebase -i a1b2c3d
Enter fullscreen mode Exit fullscreen mode

3. Edit the Commit List

Your editor will open with something like this:

pick d4e5f6g Add feature X
pick h7i8j9k WIP: implement feature X
Enter fullscreen mode Exit fullscreen mode

Change the second pick to squash (or just s):

pick d4e5f6g Add feature X
squash h7i8j9k WIP: implement feature X
Enter fullscreen mode Exit fullscreen mode

4. Edit the Commit Message

Next, Git will prompt you to combine commit messages:

# This is a combination of 2 commits.
# The first commit’s message is:
Add feature X

# The following commit message will also be included:
WIP: implement feature X
Enter fullscreen mode Exit fullscreen mode

Clean it up so the final message is concise:

Add feature X
Enter fullscreen mode Exit fullscreen mode

5. Finish the Rebase

Save and close the editor. Git will apply the rebase and squash the commits into one.


6. Troubleshooting

  • If you hit conflicts: resolve them as usual, then run:
  git add <fixed_files>
  git rebase --continue
Enter fullscreen mode Exit fullscreen mode
  • If you want to cancel the rebase:
  git rebase --abort
Enter fullscreen mode Exit fullscreen mode
  • After rewriting history: if the branch is pushed to a remote you will need to force-push the rewritten history:
  git push --force-with-lease
Enter fullscreen mode Exit fullscreen mode

(Prefer --force-with-lease over --force when collaborating.)


7. Squashing Including the Root Commit (--root)

By default git rebase -i <base> rebases starting after the specified base commit. If you want to include the very first (root) commit in an interactive rebase — for example to edit or squash the initial commit together with later commits — use the --root option:

git rebase -i --root
Enter fullscreen mode Exit fullscreen mode

What this does

  • Lists the root (initial) commit as the first entry in the interactive todo.
  • Lets you pick, reword, edit, squash, or fixup the root commit just like any other commit.
  • Rewrites the root and all descendant commits (so every commit ID in the branch will change).

Common uses & examples

  1. Squash all commits into a single initial commit If you want a single commit that contains the whole history, keep the root as pick and mark every other commit as squash (or s):
   pick a1b2c3d Initial commit
   squash d4e5f6g Add feature X
   squash h7i8j9k WIP: implement feature X
   ...
Enter fullscreen mode Exit fullscreen mode

After saving, Git will open the combined commit-message editor so you can craft the final message.

  1. Edit or reword the root commit message Change the first line to reword (or r) to update the initial commit message during the rebase:
   reword a1b2c3d Initial commit
   pick d4e5f6g Add feature X
   ...
Enter fullscreen mode Exit fullscreen mode

The rebase will stop and prompt you to edit the root commit message.

  1. Amend the root content Use edit on the root entry if you need to change the actual tree of the root commit (add/remove files). Rebase will stop at that commit; then you can modify files, git add them, and run git commit --amend before continuing the rebase:
   # interactive todo:
   edit a1b2c3d Initial commit
   pick d4e5f6g Add feature X
   ...
   # when rebase stops:
   # make changes to the working tree
   git add <files>
   git commit --amend --no-edit   # or edit message as needed
   git rebase --continue
Enter fullscreen mode Exit fullscreen mode

Caveats

  • Rewriting the root rewrites the entire branch history. This is disruptive if the branch is shared — coordinate with collaborators or avoid rewriting published branches.
  • After a --root rebase you must force-push to update any remote branch (git push --force-with-lease).
  • git rebase -i --root behaves like a normal interactive rebase in terms of conflict resolution and aborting (git rebase --abort).

Summary

  • Use git rebase -i <base> to interactively squash commits after <base>.
  • Mark commits to squash with squash (or s).
  • Edit the commit message when prompted.
  • Complete the rebase and resolve conflicts with git rebase --continue.
  • To include the initial/root commit in your rebase (so you can squash or edit it), run git rebase -i --root. Be aware this rewrites the whole branch history and requires a force-push for published branches.

Git Rebaseで過去のコミットをSquashする方法

Gitのrebaseコマンドを使ってコミットをSquash(統合)すると、コミット履歴を整理したいときに便利です。以下に手順を説明します。


1. Squashするコミットを確認する

まず、コミットログを確認して、どのコミットをまとめるか決めます。

git log --oneline
Enter fullscreen mode Exit fullscreen mode

例:

a1b2c3d タイポを修正
d4e5f6g 機能Xを追加
h7i8j9k WIP: 機能Xを実装
...
Enter fullscreen mode Exit fullscreen mode

ここでは、機能Xを追加WIP: 機能Xを実装をSquashするとします。


2. Interactive Rebaseを開始する

Squashしたいコミットの直前のコミットをベースとして、git rebase -iを実行します。

git rebase -i <base_commit_id>
Enter fullscreen mode Exit fullscreen mode

この例で、a1b2c3dがその直前のコミットである場合は、次のように実行します。

git rebase -i a1b2c3d
Enter fullscreen mode Exit fullscreen mode

3. コミット一覧を編集する

エディタが開き、次のような内容が表示されます。

pick d4e5f6g 機能Xを追加
pick h7i8j9k WIP: 機能Xを実装
Enter fullscreen mode Exit fullscreen mode

2つ目のpicksquash(または単にs)に変更します。

pick d4e5f6g 機能Xを追加
squash h7i8j9k WIP: 機能Xを実装
Enter fullscreen mode Exit fullscreen mode

4. コミットメッセージを編集する

次に、Gitからコミットメッセージを統合するよう求められます。

# これは2個のコミットを組み合わせたものです。
# 1つ目のコミットメッセージ:
機能Xを追加

# 以下のコミットメッセージも含まれます:
WIP: 機能Xを実装
Enter fullscreen mode Exit fullscreen mode

最終的なメッセージが簡潔になるよう整理します。

機能Xを追加
Enter fullscreen mode Exit fullscreen mode

5. Rebaseを完了する

保存してエディタを閉じます。GitがRebaseを適用し、コミットを1つにSquashします。


6. トラブルシューティング

  • コンフリクトが発生した場合:通常どおりコンフリクトを解消してから、次を実行します。
  git add <fixed_files>
  git rebase --continue
Enter fullscreen mode Exit fullscreen mode
  • Rebaseをキャンセルしたい場合
  git rebase --abort
Enter fullscreen mode Exit fullscreen mode
  • 履歴を書き換えた後:ブランチをすでにリモートへPushしている場合は、書き換えた履歴をForce Pushする必要があります。
  git push --force-with-lease
Enter fullscreen mode Exit fullscreen mode

(共同作業をしている場合は、--forceより--force-with-leaseを使用することを推奨します。)


7. ルートコミットを含めてSquashする(--root

デフォルトでは、git rebase -i <base>は指定したベースコミットののコミットからRebaseを行います。最初のコミット(ルートコミット)もInteractive Rebaseの対象に含めたい場合(たとえば、初回コミットを編集したり、後続のコミットとSquashしたりする場合)は、--rootオプションを使用します。

git rebase -i --root
Enter fullscreen mode Exit fullscreen mode

このコマンドの動作

  • ルート(初回)コミットがInteractive Rebaseのtodoリストの最初の項目として表示されます。
  • 他のコミットと同様に、ルートコミットに対してpickrewordeditsquashfixupを指定できます。
  • ルートコミットと、それ以降のすべてのコミットが書き換えられます(そのため、ブランチ内のすべてのコミットIDが変更されます)。

一般的な用途と例

  1. すべてのコミットを1つの初回コミットにSquashする 履歴全体を含む1つのコミットにしたい場合は、ルートコミットをpickのままにして、それ以外のすべてのコミットをsquash(またはs)に変更します。
   pick a1b2c3d 初回コミット
   squash d4e5f6g 機能Xを追加
   squash h7i8j9k WIP: 機能Xを実装
   ...
Enter fullscreen mode Exit fullscreen mode

保存すると、Gitが統合後のコミットメッセージを編集するためのエディタを開くので、最終的なメッセージを作成できます。

  1. ルートコミットのメッセージを編集・変更する Rebase中に初回コミットのメッセージを変更するには、最初の行をreword(またはr)に変更します。
   reword a1b2c3d 初回コミット
   pick d4e5f6g 機能Xを追加
   ...
Enter fullscreen mode Exit fullscreen mode

Rebaseが一時停止し、ルートコミットのメッセージを編集するよう求められます。

  1. ルートコミットの内容を修正する ルートコミットの実際のツリー(ファイルの追加・削除)を変更する必要がある場合は、ルートのエントリにeditを指定します。Rebaseはそのコミットで一時停止します。その後、ファイルを変更してgit addし、git commit --amendを実行してからRebaseを続行できます。
   # Interactive Rebaseのtodo:
   edit a1b2c3d 初回コミット
   pick d4e5f6g 機能Xを追加
   ...
   # Rebaseが停止したら:
   # ワーキングツリーに変更を加える
   git add <files>
   git commit --amend --no-edit   # 必要に応じてメッセージも編集
   git rebase --continue
Enter fullscreen mode Exit fullscreen mode

注意点

  • ルートコミットを書き換えると、ブランチの履歴全体が書き換えられます。共有ブランチで行うと大きな影響があるため、共同作業者と調整するか、公開済みブランチの書き換えは避けてください。
  • --rootを使ってRebaseした後、リモートブランチを更新するにはForce Pushが必要です(git push --force-with-lease)。
  • git rebase -i --rootでも、コンフリクトの解消や中止(git rebase --abort)については通常のInteractive Rebaseと同様に動作します。

まとめ

  • git rebase -i <base>を使用すると、<base>より後のコミットを対話形式でSquashできます。
  • Squashするコミットをsquash(またはs)に変更します。
  • プロンプトが表示されたらコミットメッセージを編集します。
  • Rebaseを完了し、コンフリクトが発生した場合はgit rebase --continueで続行します。
  • 初回/ルートコミットをRebaseの対象に含めてSquashや編集を行うには、git rebase -i --rootを実行します。この操作ではブランチの履歴全体が書き換えられ、公開済みブランチではForce Pushが必要になる点に注意してください。

Top comments (0)