This guide explores interactive rebase, amending commits, and best practices for rewriting Git history. Learn how to enhance your repository’s readability and maintain integrity while rewriting history.

What is Interactive Rebase?

Interactive rebase allows you to edit a series of commits, offering options to modify commit messages, squash commits, reorder commits, or drop unnecessary changes. It is ideal for cleaning up feature branches before merging into the main branch.

Fixing the Last Commit

If you need to fix the most recent commit (e.g., edit its message or include additional changes), use:

git commit --amend

This opens the commit message editor, where you can modify the message. If you want to add more changes, stage the files first:

git add 
git commit --amend

Interactive Rebase: Editing Multiple Commits

To edit multiple commits, use interactive rebase:

git rebase -i 

Replace <base-commit> with the commit hash before the range of commits you want to modify. For example:

git rebase -i HEAD~3

This opens an editor showing the last three commits:

pick abc123 First commit message
pick def456 Second commit message
pick ghi789 Third commit message

Interactive Rebase Options

Modify the commands next to each commit to perform actions:

  • pick: Use the commit as-is.
  • reword: Edit the commit message.
  • edit: Modify the commit content or message.
  • squash: Combine this commit with the previous one.
  • drop: Remove the commit entirely.

Example: Squashing Commits

Suppose you want to combine two commits into one. Change:

pick abc123 First commit message
pick def456 Second commit message

To:

pick abc123 First commit message
squash def456 Second commit message

Save and close the editor. Git will prompt you to combine the commit messages. After confirming, the two commits will be merged into one.

Example: Editing a Commit Message

To update a commit message, change:

pick abc123 Incorrect commit message

To:

reword abc123 Incorrect commit message

Save and edit the message when prompted.

Example: Using Interactive Rebase in a .NET Project

Suppose you’re working on a .NET project and have made the following commits:

// Commit history
pick 123abc Add Program.cs with basic functionality
pick 456def Add feature to display greeting
pick 789ghi Fix typo in greeting

To squash the typo fix into the second commit, start an interactive rebase:

git rebase -i HEAD~3

Edit the rebase file:

pick 123abc Add Program.cs with basic functionality
pick 456def Add feature to display greeting
squash 789ghi Fix typo in greeting

Combine the commit messages when prompted, and the two commits will merge into one.

Best Practices for Rewriting History

  • Rewrite history only on private branches: Avoid rewriting shared history to prevent conflicts.
  • Test thoroughly: Verify changes after rewriting history to ensure the repository remains stable.
  • Document changes: Add clear commit messages to explain edits during rebase.

Risks of Rewriting History

While rewriting history is powerful, it comes with risks:

  • Shared branches: Rewriting shared history can cause conflicts for other contributors.
  • Data loss: Dropped commits are permanently removed unless backed up.

Always create a backup branch before rewriting history:

git branch backup

Conclusion

Rewriting history in Git, whether through interactive rebase or amending commits, is a valuable skill for maintaining clean and readable repositories. Use these tools wisely to correct mistakes, simplify commit history, and create well-structured repositories. With careful use, you can enhance your development workflow and improve collaboration.