The site that you are currently viewing is a static version of the Software Factory documentation delivered with the

version v7.2.
For up-to-date documentation, see the latest version.

Git clean history

How to clean your Git history

Concept

This guide explains how to clean up your branch’s Git history. A clean history makes code reviews easier, reduces merge conflicts, and keeps the main branch readable.

  • Remove noisy commits like fix bug, wip, debug.
  • Group related changes into meaningful commits.
  • Make the history easier to understand for reviewers.
Warning

Be careful when rebasing shared branches.
Rebasing rewrites commit history, which can cause problems for other developers working on the same branch.
Before rebasing a shared branch, make sure you coordinate with your team and communicate clearly.
When in doubt, prefer rebasing only your local feature branches before they are pushed.

Tasks

Make sure your work is committed

Check your status and commit any uncommitted work:

git status
git add .
git commit -m "Your latest changes"

Interactive rebase on your local history

Assuming you want to clean your last 5 commits:

git rebase -i HEAD~5

Pick, reword, edit, squash, fixup

When you run git rebase -i, an editor opens showing a list of commits and their actions.
By default, all commits are marked as pick. You can change the action word at the start of each line to control how Git rewrites the history.

Here’s a summary of the most common and useful options:

  • pick → Keep the commit as-is.
    Use this when the commit is fine and doesn’t need changes.

  • reword → Keep the commit content, but edit the commit message.
    This is useful when you want to clarify or complete commit messages.

  • edit → Pause the rebase at this commit so you can change its content (and/or message).
    Git will stop, let you make changes, then you continue the rebase.

  • squash → Combine this commit with the previous one and merge both commit messages.
    Use this to group related commits into one, while keeping a record of their intent.

  • fixup → Combine this commit with the previous one but discard its commit message.
    Use this for small corrections or cleanups you want merged into the earlier commit without cluttering the final message.

You can also reorder commits by moving the lines up or down in the editor. This lets you change the sequence of commits if needed and it allows to use the action above.
Example: You can move a commit up in the list before changing its action to fixup.

For example, we start with the following situation:

gitGraph
   commit id: "Start"
   branch dev
   checkout dev
   commit id: "Initial login form"
   commit id: "Continue to add backend API"
   commit id: "Update CSS"
   commit id: "Fix typo in API"
   commit id: "Fix CSS color"
   

Next, running the command git rebase -i HEAD~5 opens an editor showing these lines:

pick a1b2c3 Initial login form
pick d4e5f6 Continue to add backend API
pick j1k2l3 Update CSS
pick f7g8h9 Fix typo in API
pick m4n5o6 Fix CSS color
Note

Remember to set your preferred editor. For example: export EDITOR=vim

To improve the commit history, we apply the following changes in the editor:

  • Rename the first commit message (reword)
  • Combine Add backend API into the first commit using fixup
  • Move Fix typo in API below Continue to add backend API and set it to fixup to include it in the same commit group
  • Combine Fix CSS color into Update CSS with fixup

This results in the following rebase plan:

reword a1b2c3 Initial login form
fixup d4e5f6 Continue to add backend API
fixup f7g8h9 Fix typo in API
pick j1k2l3 Update CSS
fixup m4n5o6 Fix CSS color

When the editor opens for the reword step, make sure to replace the default message with a meaningful one (Login form with backend API), as this will be the final commit message after the fixups are applied.

After completing the rebase, we obtain a much cleaner and more meaningful commit history:

gitGraph
   commit id: "Start"
   branch dev
   checkout dev
   commit id: "Login form with backend API"
   commit id: "Update CSS"
Tip

To facilitate editing the rebase file, you can configure an external tool like
[git-interactive-rebase-tool].
You can also use the --autosquash option of rebase to prepare the file if you have used the --fixup or --squash options during commits.
Some Git clients, like lazygit , also make the rebase operation easier.

Resolve any conflicts

If conflicts occur during rebase:

git status
# Edit conflicted files
git add <file>
git rebase --continue

Rebase onto remote source branch

If your merge strategy is Fast Forward or Merge Commit with Semi-linear History, you need to rebase your dev branch on top of the source branch.

Assuming the source branch is called main:

# Starting from dev branch, switch to main and update it
git switch main   # → on main
git pull
# back to dev branch and rebase it on main
git switch dev   # → on dev
git rebase main
Note

git switch, introduced in Git 2.23.0, instead of git checkout

Or (without updating your local main branch) :

# directly from dev branch
git pull origin main --rebase

Push your cleaned branch

If you need to update your dev branch on the remote, you need to force the push as the history has been modified.

git push --force-with-lease --force-if-includes
Software Factory Recommendations
To avoid overwriting other’s work, instead of using --force option, use the safer options --force-with-lease

with –force-if-includes

.
–force-with-lease: Force push only if I have the latest remote state.
–force-if-includes: Force push only if I’ve incorporated remote changes locally.

Reference