Skip to content

Bits of .NET

Daily micro-tips for C#, SQL, performance, and scalable backend engineering.

  • Asp.Net Core
  • C#
  • SQL
  • JavaScript
  • CSS
  • About
  • ErcanOPAK.com
  • No Access
  • Privacy Policy
Git

Git Rebase Magic: How to Clean Up Messy Commit History Like a Pro

- 05.02.26 - ErcanOPAK

Your git history looking like a war zone? Interactive rebase transforms chaotic commits into a clean, logical story.

The Problem: Spaghetti Commit History

# Typical messy history
$ git log --oneline
a1b2c3d Fix typo in README
e4f5g6h Update config again
h7i8j9k Another attempt
k0l1m2n Revert previous change
n3o4p5q Merge branch 'feature-x'
p6q7r8s WIP: trying something
r9s0t1u Fix broken thing
t2u3v4w Actually fix it this time

# 8 commits for one small feature!
# Commit messages don't tell a story
# Multiple "fix" commits
# WIP commits in main history
# Merge commits everywhere

Solution: Interactive Rebase

# Start interactive rebase for last 8 commits
git rebase -i HEAD~8

# This opens editor with:
pick a1b2c3d Fix typo in README
pick e4f5g6h Update config again
pick h7i8j9k Another attempt
pick k0l1m2n Revert previous change
pick n3o4p5q Merge branch 'feature-x'
pick p6q7r8s WIP: trying something
pick r9s0t1u Fix broken thing
pick t2u3v4w Actually fix it this time

# Actions available:
# p, pick = use commit
# r, reword = use commit, but edit commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like squash, but discard commit message
# d, drop = remove commit
# x, exec = run command using shell

# Transform to clean history:
reword a1b2c3d docs: update README with installation steps
fixup e4f5g6h
fixup h7i8j9k
drop k0l1m2n  # Revert shouldn't be in history
drop n3o4p5q  # Remove merge commit
squash p6q7r8s
reword r9s0t1u feat: add user profile image upload
fixup t2u3v4w

# Result: 2 clean commits!
# 1. docs: update README with installation steps
# 2. feat: add user profile image upload

Advanced: Rebase with Fixup and Autosquash

# Enable autosquash for automatic fixup/squash
git config --global rebase.autoSquash true

# Workflow:
# 1. Make initial commit
git commit -m "feat: add user authentication"

# 2. Make fixes with fixup! prefix
git commit --fixup HEAD  # Automatically marks as fixup

# Or manually:
git commit -m "fixup! feat: add user authentication"
git commit -m "fixup! feat: add user authentication"

# 3. When ready to clean up:
git rebase -i --autosquash HEAD~3

# Git automatically arranges fixup commits under original
# Just save and exit!

# Even better: Use --autosquash with --autostash
git rebase -i --autosquash --autostash origin/main
# Stashes changes, rebases, applies stash back

Rewriting Commit Messages Conventionally:

# Conventional Commits format:
# [optional scope]: 
# 
# Types:
# feat:     new feature
# fix:      bug fix  
# docs:     documentation
# style:    formatting
# refactor: code restructuring
# test:     adding tests
# chore:    maintenance

# Bad: "Fixed the thing"
# Good: "fix(auth): prevent null reference in login controller"

# Use git commit --amend for last commit
git commit --amend -m "feat(auth): add password reset functionality"

# Use rebase to rewrite older commits
git rebase -i HEAD~5
# Change 'pick' to 'reword' for commits to edit

Rescue Operation: Fixing Broken Rebase

# Scenario: Rebase conflict disaster
git rebase -i HEAD~10
# Conflicts everywhere, lost track

# Option 1: Abort and start over
git rebase --abort

# Option 2: Skip problematic commit
# During conflict:
git add .  # Stage resolved files
git rebase --skip  # Skip this commit entirely
# Use carefully - you're removing a commit!

# Option 3: Use mergetool
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd "code --wait $MERGED"

# During conflict:
git mergetool  # Opens VS Code with 3-way merge

# Option 4: Rebase with strategy
git rebase -i HEAD~10 --strategy recursive --strategy-option theirs
# Accept their changes for conflicts
# OR
git rebase -i HEAD~10 --strategy recursive --strategy-option ours
# Keep your changes

Related posts:

Git: Use git log --graph to Visualize Branch History

Search History by Content

Git Reverts Remove the Wrong Code

Post Views: 3

Post navigation

CSS Grid Magic: How to Create Responsive Layouts That Work Perfectly on Any Device
Windows 11 Power User Secret: How PowerToys Makes You 3x More Productive

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

February 2026
M T W T F S S
 1
2345678
9101112131415
16171819202122
232425262728  
« Jan    

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (935)
  • How to add default value for Entity Framework migrations for DateTime and Bool (832)
  • Get the First and Last Word from a String or Sentence in SQL (826)
  • How to select distinct rows in a datatable in C# (799)
  • How to make theater mode the default for Youtube (716)
  • Add Constraint to SQL Table to ensure email contains @ (574)
  • How to enable, disable and check if Service Broker is enabled on a database in SQL Server (553)
  • Average of all values in a column that are not zero in SQL (520)
  • How to use Map Mode for Vertical Scroll Mode in Visual Studio (474)
  • Find numbers with more than two decimal places in SQL (436)

Recent Posts

  • C#: Use MemoryPack for 10x Faster Serialization than JSON
  • C#: Use params ReadOnlySpan for Allocation-Free Variable Arguments
  • C#: Use ObjectPool for Reusing Expensive Objects
  • C#: Use Lazy for Expensive Object Initialization
  • SQL: Use STRING_AGG to Concatenate Rows into Comma-Separated List
  • SQL: Use Filtered Indexes to Index Only Subset of Rows
  • .NET Core: Use Result Pattern to Avoid Exceptions for Expected Errors
  • .NET Core: Use IOptions Pattern for Strongly-Typed Configuration
  • Git: Use .gitattributes to Handle Line Endings Across OS
  • Git: Use git notes to Add Comments to Commits Without Changing History

Most Viewed Posts

  • Get the User Name and Domain Name from an Email Address in SQL (935)
  • How to add default value for Entity Framework migrations for DateTime and Bool (832)
  • Get the First and Last Word from a String or Sentence in SQL (826)
  • How to select distinct rows in a datatable in C# (799)
  • How to make theater mode the default for Youtube (716)

Recent Posts

  • C#: Use MemoryPack for 10x Faster Serialization than JSON
  • C#: Use params ReadOnlySpan for Allocation-Free Variable Arguments
  • C#: Use ObjectPool for Reusing Expensive Objects
  • C#: Use Lazy for Expensive Object Initialization
  • SQL: Use STRING_AGG to Concatenate Rows into Comma-Separated List

Social

  • ErcanOPAK.com
  • GoodReads
  • LetterBoxD
  • Linkedin
  • The Blog
  • Twitter
© 2026 Bits of .NET | Built with Xblog Plus free WordPress theme by wpthemespace.com