Esc
Navigation
Actions
๐ŸŽจ Cycle Theme t
๐Ÿ”„ Toggle Blog/Dev Mode
โฌ†๏ธ Scroll to Top gg
โฌ‡๏ธ Scroll to Bottom G
BIOS v2.1.0
Loading kernel...
Starting services...
Welcome to dev@sandikodev
NORMAL
dev@enigma
โšก 12% โ”‚ ๐Ÿ’พ 4.2G โ”‚ ๐Ÿ“ถ eth0 โ”‚ ๐Ÿ• 00:00 โ”‚ ๐Ÿ“… Mon 01
โ–ฃ nvim โ€” git-filter-branch-vs-manual-rebase.md
dev@enigma:~ โฏ cat git-filter-branch-vs-manual-rebase.md

Git Filter-Branch vs Manual Rebase: Restructuring Repository History

The Problem

Recently, while working on the RENDER project, I had a repository with this structure:

terminal-code/
โ”œโ”€โ”€ packages/
โ”‚   โ””โ”€โ”€ astro-terminal-code/
โ”‚       โ”œโ”€โ”€ package.json
โ”‚       โ”œโ”€โ”€ README.md
โ”‚       โ””โ”€โ”€ src/

But I needed it to be:

terminal-code/
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ src/

The challenge? I wanted to preserve the entire commit history while restructuring the files across all commits, not just the latest one.

Approach 1: Manual Rebase Strategy

My usual approach for this type of problem involves manually going through each commit:

# 1. Start interactive rebase from root
git rebase -i --root

# 2. Mark each commit as 'edit'
# 3. For each commit, manually:
git reset --soft HEAD~1
# Move files manually
mv packages/astro-terminal-code/* .
rm -rf packages/
git add -A
git commit --amend --no-edit

# 4. Continue to next commit
git rebase --continue

# 5. Repeat until all commits are processed

Pros of Manual Rebase:

  • โœ… Full control over each commit
  • โœ… Can make different changes per commit if needed
  • โœ… Easy to understand whatโ€™s happening
  • โœ… Can abort/fix issues at any step

Cons of Manual Rebase:

  • โŒ Time-consuming for many commits
  • โŒ Prone to human error
  • โŒ Interactive editor issues in some environments
  • โŒ Repetitive and tedious process

Approach 2: Git Filter-Branch

Then I discovered git filter-branch - a powerful command that can rewrite entire repository history in one go:

# Single command to restructure entire history
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch \
  --tree-filter 'if [ -d packages/astro-terminal-code ]; then 
    mv packages/astro-terminal-code/* . 2>/dev/null || true; 
    mv packages/astro-terminal-code/.* . 2>/dev/null || true; 
    rm -rf packages; 
  fi' HEAD

Pros of Filter-Branch:

  • โœ… One command handles entire history
  • โœ… Consistent changes across all commits
  • โœ… Fast execution
  • โœ… No interactive editor issues
  • โœ… Atomic operation - all or nothing

Cons of Filter-Branch:

  • โŒ Less granular control
  • โŒ Can be dangerous if command is wrong
  • โŒ Harder to debug if something goes wrong
  • โŒ Rewrites all commit hashes

Real-World Comparison

Let me show you the actual results from my RENDER project restructuring:

Before:

$ git log --oneline
65e77b3 ๐Ÿ”ฅ Update branding: SandikoOS โ†’ RENDER
a2219f5 ๐Ÿš€ FOUNDATION: SandikoOS Ecosystem - Phase 1

$ git show --name-only a2219f5
packages/astro-terminal-code/README.md
packages/astro-terminal-code/package.json
packages/astro-terminal-code/src/index.ts
packages/astro-terminal-code/src/processor.ts

After Filter-Branch:

$ git log --oneline
31a26da ๐Ÿ”ฅ Update branding: SandikoOS โ†’ RENDER
064115d ๐Ÿš€ FOUNDATION: SandikoOS Ecosystem - Phase 1

$ git show --name-only 064115d
README.md
package.json
src/index.ts
src/processor.ts

Time taken:

  • Manual rebase: ~10-15 minutes (with interactive editor struggles)
  • Filter-branch: ~5 seconds

When to Use Each Approach

Use Manual Rebase When:

  • You need different changes per commit
  • You want to review each commit individually
  • Youโ€™re learning Git and want to understand the process
  • You have complex merge conflicts to resolve

Use Filter-Branch When:

  • You need consistent changes across all commits
  • You have many commits to process
  • You want a fast, automated solution
  • Youโ€™re confident in your filter command

Modern Alternative: Git Filter-Repo

For new projects, consider git filter-repo (requires separate installation):

# More modern and safer alternative
git filter-repo --path-rename packages/astro-terminal-code/:

Safety Tips

Regardless of which approach you choose:

  1. Always backup your repository first
  2. Test on a clone before applying to main repo
  3. Use --force-with-lease when pushing rewritten history
  4. Coordinate with team before rewriting shared history
# Safe backup and testing workflow
git clone original-repo test-repo
cd test-repo
# Apply your changes
git push --force-with-lease origin main

Conclusion

Both approaches have their place in a developerโ€™s toolkit. For the RENDER project restructuring, git filter-branch was clearly the winner - it saved me significant time and eliminated the interactive editor issues I was facing.

However, the manual rebase approach taught me a lot about Git internals and gives me confidence to handle complex history rewriting scenarios.

My recommendation: Start with understanding the manual approach, then graduate to git filter-branch for efficiency. Your future self will thank you for learning both! ๐Ÿš€

This article is part of my journey building the RENDER ecosystem - revolutionizing desktop development with web technologies. Follow along for more Git tips and development insights!

dev@enigma:~ โฏ
โ–ฃ navigation
โ–ฃ info
type: post
mode: dev ๐Ÿ’ป