Git - Rebasing Advanced

Advanced

Advanced rebasing techniques allow you to rewrite Git history, clean up commits, and create professional-quality commit sequences. Master these powerful tools to maintain pristine project history.

Interactive Rebase Fundamentals

Interactive rebase lets you modify commits during the rebase process:

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

# Interactive rebase from specific commit
git rebase -i abc1234^

# Interactive rebase onto branch
git rebase -i main

Interactive Rebase Commands

# Interactive rebase editor shows:
pick f7f3f6d Change my name a bit
pick 310154e Update README formatting
pick a5f4a0d Add support for new feature

# Available commands:
# p, pick   = use commit as-is
# 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
# x, exec   = run command (the rest of the line) using shell
# b, break  = stop here (continue rebase later with 'git rebase --continue')
# d, drop   = remove commit
# l, label  = label current HEAD with a name
# t, reset  = reset HEAD to a label
# m, merge  = create a merge commit using the original merge commit's message

Common Interactive Rebase Operations

Squashing Commits

# Original commits:
pick f7f3f6d Add user authentication
pick 310154e Fix typo in auth function
pick a5f4a0d Update auth tests
pick b8c2f1e Fix auth test failures

# Squash into single commit:
pick f7f3f6d Add user authentication
squash 310154e Fix typo in auth function
squash a5f4a0d Update auth tests
squash b8c2f1e Fix auth test failures

# Result: One clean commit with combined changes

Fixup Commits

# Create fixup commit
git commit --fixup=abc1234

# Automatically squash fixups during rebase
git rebase -i --autosquash HEAD~10

# Original sequence becomes:
pick abc1234 Original commit
fixup def5678 fixup! Original commit

Rewording Commit Messages

# Reword commit messages
pick f7f3f6d Add user authentication
reword 310154e Fix typo in auth function  
pick a5f4a0d Update auth tests

# Git will open editor for each 'reword' commit

Advanced Rebase Strategies

Onto Different Branches

# Rebase onto different branch
git rebase main feature-branch

# Rebase with specific upstream and branch
git rebase --onto main develop feature-branch

# Complex rebase: move commits from one base to another
git rebase --onto new-base old-base branch-to-move
# Example: Extract commits from feature to new branch
# Original: main---A---B---C (develop)
#                    \---D---E---F (feature)
# Goal: main---A---B---C (develop)
#           \---D---E---F (feature, rebased onto main)

git rebase --onto main develop feature

Preserving Merges

# Preserve merge commits during rebase
git rebase --preserve-merges main

# Rebase with merge commit recreation
git rebase --rebase-merges main

# Interactive rebase preserving merge structure
git rebase -i --rebase-merges HEAD~10

Commit Splitting and Editing

Splitting Large Commits

# Mark commit for editing
edit f7f3f6d Large commit with multiple changes

# During rebase, Git stops at the commit
# Reset the commit but keep changes staged
git reset HEAD^

# Selectively add and commit parts
git add file1.js
git commit -m "Add user validation"

git add file2.js  
git commit -m "Add password hashing"

git add file3.js
git commit -m "Add session management"

# Continue rebase
git rebase --continue

Editing Commit Content

# Stop at commit for editing
edit abc1234 Commit to modify

# Make changes to files
vim src/auth.js

# Amend the commit
git add src/auth.js
git commit --amend

# Continue rebase
git rebase --continue

Complex History Rewriting

Reordering Commits

# Original order:
pick f7f3f6d Add feature A
pick 310154e Add feature B  
pick a5f4a0d Fix feature A bug
pick b8c2f1e Add feature C

# Reorder to group related commits:
pick f7f3f6d Add feature A
pick a5f4a0d Fix feature A bug
pick 310154e Add feature B
pick b8c2f1e Add feature C

Removing Commits

# Drop unwanted commits
pick f7f3f6d Add user authentication
drop 310154e Temporary debug code
pick a5f4a0d Update auth tests
drop b8c2f1e More debug code

# Or delete the line entirely (same as drop)

Adding New Commits Mid-History

# Stop for adding new commit
edit f7f3f6d Add user authentication

# Create new commit at this point
echo "New file" > newfile.txt
git add newfile.txt
git commit -m "Add configuration file"

# Continue with original sequence
git rebase --continue

Automated Rebase Workflows

Autosquash Workflow

# Create commits with automatic squash markers
git commit -m "Add user authentication"
# ... later, find issue in previous commit
git add fix.js
git commit --fixup=HEAD~2

# Auto-squash during rebase
git rebase -i --autosquash HEAD~10

# Configure automatic autosquash
git config rebase.autosquash true

Exec Commands in Rebase

# Run commands during rebase
pick f7f3f6d Add user authentication
exec npm test
pick 310154e Add password validation
exec npm run lint
pick a5f4a0d Update documentation
exec npm run build

# Rebase will run each command and stop if any fail

Advanced Conflict Resolution

Handling Rebase Conflicts

# During rebase conflict
git status                # See conflicted files
git mergetool            # Use merge tool
# Or edit manually
vim conflicted-file.js

# Mark as resolved and continue
git add conflicted-file.js
git rebase --continue

# Skip problematic commit
git rebase --skip

# Abort entire rebase
git rebase --abort

Rebase with Strategy Options

# Rebase with merge strategy
git rebase -X ours main
git rebase -X theirs main

# Rebase ignoring whitespace
git rebase -X ignore-space-change main

# Use patience algorithm
git rebase -X patience main

Branch Surgery Techniques

Moving Commit Ranges

# Move commits D, E, F from develop to main
# Before: main---A---B---C
#         develop---D---E---F---G

git rebase --onto main develop~3 develop

# Result: main---A---B---C---D---E---F
#         develop---G

Cherry-Pick Range with Rebase

# Pick specific commit range and rebase
git rebase --onto target-branch start-commit end-commit

# Example: Move commits 3-7 from feature to main
git rebase --onto main feature~5 feature~1

Rebase Transplanting

# Transplant branch from old base to new base
# Before: old-base---A---B (branch)
#         new-base---C---D

git checkout branch
git rebase --onto new-base old-base

# Result: new-base---C---D---A---B (branch)

Interactive Rebase Scripting

Custom Rebase Scripts

#!/bin/bash
# auto-rebase.sh - Automated interactive rebase

# Generate rebase script
cat > /tmp/rebase-script << 'EOF'
pick HEAD~4
squash HEAD~3
reword HEAD~2
edit HEAD~1
EOF

# Set custom editor
export GIT_SEQUENCE_EDITOR="cp /tmp/rebase-script"
git rebase -i HEAD~5

Rebase with Hooks

# Pre-rebase hook (.git/hooks/pre-rebase)
#!/bin/bash
echo "Starting rebase of $1 onto $2"

# Check if rebase is safe
if [ "$1" = "main" ]; then
    echo "Cannot rebase main branch"
    exit 1
fi

# Post-rewrite hook (.git/hooks/post-rewrite)
#!/bin/bash
if [ "$1" = "rebase" ]; then
    echo "Rebase completed successfully"
    # Update documentation, run tests, etc.
fi

Performance and Large Repository Rebase

Optimizing Large Rebases

# Speed up rebase with better algorithms
git config rebase.stat false
git config rebase.autoSquash true

# Use faster merge strategy
git rebase -X histogram main

# Rebase with limited context
git rebase --committer-date-is-author-date main

Shallow Repository Rebase

# Unshallow before rebase
git fetch --unshallow

# Rebase with limited history
git rebase --root main  # Rebase from initial commit

Advanced Rebase Patterns

Feature Branch Cleanup

#!/bin/bash
# cleanup-feature.sh - Clean up feature branch before merge

FEATURE_BRANCH=$(git branch --show-current)

# Squash all commits into logical chunks
git rebase -i $(git merge-base main $FEATURE_BRANCH)

# Rebase onto latest main
git fetch origin main
git rebase origin/main

echo "Feature branch $FEATURE_BRANCH cleaned up"

Release Preparation Rebase

# Prepare clean release history
git checkout release/v2.0

# Interactive rebase to clean up commits
git rebase -i --autosquash develop

# Ensure linear history
git rebase main

# Final cleanup
git rebase -i HEAD~20  # Review last 20 commits

Collaborative Rebase Strategies

Safe Collaborative Rebase

# Check if branch has been pushed
if git merge-base --is-ancestor HEAD origin/feature-branch; then
    echo "Branch already pushed, rebase may be dangerous"
    exit 1
fi

# Safe rebase workflow
git fetch origin
git rebase origin/main
git push --force-with-lease origin feature-branch

Team Rebase Policies

# Team rebase guidelines script
#!/bin/bash
# team-rebase-policy.sh

BRANCH=$1
BASE_BRANCH=${2:-main}

# Only allow rebase on feature branches
if [[ ! $BRANCH =~ ^feature/ ]]; then
    echo "Rebase only allowed on feature branches"
    exit 1
fi

# Check if branch is up to date with base
git fetch origin $BASE_BRANCH
if ! git merge-base --is-ancestor origin/$BASE_BRANCH $BRANCH; then
    echo "Please rebase onto latest $BASE_BRANCH first"
    exit 1
fi

git rebase -i origin/$BASE_BRANCH

Troubleshooting Advanced Rebase

Recovery from Failed Rebase

# Find rebase state
ls -la .git/rebase*

# Check reflog for recovery
git reflog HEAD

# Reset to before rebase
git reset --hard HEAD@{5}  # Adjust index as needed

# Alternative: use ORIG_HEAD
git reset --hard ORIG_HEAD

Debugging Rebase Issues

# Enable rebase debugging
export GIT_TRACE=1
git rebase -i HEAD~5

# Check rebase todo file
cat .git/rebase-merge/git-rebase-todo

# Check current rebase state
cat .git/rebase-merge/head-name
cat .git/rebase-merge/onto

Best Practices

Advanced Rebase Best Practices:
  • Never rebase public/shared branches
  • Use --force-with-lease for safer force pushes
  • Test thoroughly after complex rebases
  • Keep rebase operations focused and small
  • Document complex rebase procedures
  • Use interactive rebase to create logical commit progression

Professional Rebase Workflow

# Professional feature development workflow
git checkout -b feature/user-auth
# ... development work ...

# Before merging: clean up history
git rebase -i $(git merge-base main HEAD)
git rebase main  # Update to latest

# Final check
git log --oneline main..HEAD  # Review commits
npm test  # Ensure tests pass

# Safe push
git push --force-with-lease origin feature/user-auth

Integration with Development Tools

IDE Integration

# VS Code rebase tasks
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Interactive Rebase",
            "type": "shell",
            "command": "git",
            "args": ["rebase", "-i", "HEAD~${input:commitCount}"],
            "group": "build"
        }
    ]
}

Automated Quality Gates

# Pre-push hook with rebase validation
#!/bin/bash
# .git/hooks/pre-push

protected_branch='main'
current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')

if [ $protected_branch = $current_branch ]; then
    echo "Direct push to main not allowed"
    exit 1
fi

# Ensure branch is rebased on main
if ! git merge-base --is-ancestor main HEAD; then
    echo "Please rebase on main before pushing"
    exit 1
fi

Key Takeaways

  • History Perfection: Interactive rebase creates clean, logical commit sequences
  • Flexibility: Advanced rebase operations handle complex history rewriting
  • Collaboration: Use rebase safely in team environments with proper protocols
  • Quality: Clean commits improve code review and project maintenance
  • Professionalism: Master rebasing for professional-grade Git workflows

Advanced rebasing transforms messy development history into clean, professional commit sequences. Master these techniques to maintain high-quality project history and improve collaboration in complex development environments.