Git Advanced Workflows: Rebase, Cherry-pick, and Interactive History
DevOpsNovember 19, 202517 min read0 views
GitVersion ControlDevOpsWorkflowBest PracticesDevelopment
Share:
Git Advanced Workflows: Rebase, Cherry-pick, and Interactive History
Basic Git (add, commit, push) gets you started. Advanced Git makes you a pro. Let's master the techniques that separate beginners from experts.
Why Advanced Git Matters
Professional developers need:
- 📝 Clean commit history
- 🔄 Flexible branching strategies
- 🛠️ Ability to fix mistakes
- 👥 Smooth team collaboration
Git Rebase: Rewrite History
Merge vs Rebase
Merge:
main: A---B---C---D
\ \
feature: E---F---G---M
Rebase:
main: A---B---C---D
\
feature: E'--F'--G'
Basic Rebase
# On feature branch git checkout feature git rebase main # Or in one command git rebase main feature
What happens:
- Git finds common ancestor
- Saves your commits (E, F, G)
- Applies main's commits
- Replays your commits on top
Handling Conflicts
# During rebase, you hit a conflict <<<<<<< HEAD const version = "2.0"; ======= const version = "1.5"; >>>>>>> feature-branch # Fix the conflict manually, then: git add . git rebase --continue # Or abort if needed git rebase --abort
Interactive Rebase: Clean Up Commits
Squash Commits
# Rebase last 3 commits git rebase -i HEAD~3 # Editor opens: pick abc1234 Add user model pick def5678 Fix typo pick ghi9012 Add validation # Change to: pick abc1234 Add user model squash def5678 Fix typo squash ghi9012 Add validation # Save and exit # All 3 commits become 1
Reorder Commits
git rebase -i HEAD~4 # Original order: pick abc1234 Add feature A pick def5678 Add feature B pick ghi9012 Fix bug in A pick jkl3456 Add tests # Reorder: pick abc1234 Add feature A pick ghi9012 Fix bug in A pick def5678 Add feature B pick jkl3456 Add tests
Edit Commit Message
git rebase -i HEAD~2 # Change: pick abc1234 WIP: Add feature pick def5678 Tests # To: reword abc1234 WIP: Add feature pick def5678 Tests # Save - new editor opens for message
Split a Commit
git rebase -i HEAD~1 # Change: pick abc1234 Add user and order models # To: edit abc1234 Add user and order models # Git pauses, now: git reset HEAD^ git add user.model.js git commit -m "Add user model" git add order.model.js git commit -m "Add order model" git rebase --continue
Cherry-pick: Select Specific Commits
Basic Cherry-pick
# On main branch git log --oneline feature # Output: abc1234 Add feature A def5678 Add feature B ghi9012 Add feature C # Only want feature B git cherry-pick def5678
Cherry-pick Range
# Pick multiple commits git cherry-pick abc1234..ghi9012 # Pick commits (excluding first) git cherry-pick abc1234^..ghi9012
Cherry-pick Without Commit
# Apply changes without committing git cherry-pick -n def5678 # Make changes git add . git commit -m "Custom message"
Git Reflog: Recover Lost Commits
# View all actions git reflog # Output: abc1234 HEAD@{0}: commit: Add feature def5678 HEAD@{1}: rebase: Add tests ghi9012 HEAD@{2}: reset: moving to HEAD~1 # Recover deleted commit git reset --hard HEAD@{1} # Or create new branch from it git checkout -b recovered HEAD@{2}
Git Stash: Save Work in Progress
Basic Stash
# Save current changes git stash # Save with message git stash save "WIP: User authentication" # List stashes git stash list # Apply latest stash git stash pop # Apply specific stash git stash apply stash@{2}
Stash Specific Files
# Stash only staged files git stash --staged # Stash including untracked files git stash -u # Stash specific files git stash push -m "Stash config" config.js
Create Branch from Stash
# Stash changes git stash # Create branch from stash git stash branch feature-from-stash stash@{0}
Git Bisect: Find Bugs with Binary Search
# Start bisect git bisect start # Mark current as bad git bisect bad # Mark known good commit git bisect good abc1234 # Git checks out middle commit # Test it, then mark: git bisect good # or bad # Repeat until bug found # Git will say: "abc1234 is the first bad commit" # Finish bisect git bisect reset
Automated Bisect
# Automate with test script git bisect start HEAD abc1234 git bisect run npm test # Git automatically finds bad commit
Git Worktree: Multiple Working Directories
# List worktrees git worktree list # Create new worktree git worktree add ../feature-branch feature-branch # Now you have: # /project (main branch) # /feature-branch (feature branch) # Remove worktree git worktree remove ../feature-branch
Advanced Reset Strategies
Soft Reset (Keep Changes Staged)
# Undo last commit, keep changes staged git reset --soft HEAD~1 # Changes are in staging area git status # Changes to be committed: # modified: file.js
Mixed Reset (Default - Keep Changes Unstaged)
# Undo last commit, keep changes unstaged git reset HEAD~1 # Changes are in working directory git status # Changes not staged for commit: # modified: file.js
Hard Reset (Discard Changes)
# Undo last commit, discard all changes git reset --hard HEAD~1 # Everything gone!
Git Hooks: Automate Workflows
Pre-commit Hook
# .git/hooks/pre-commit #!/bin/sh # Run linter npm run lint # If fails, prevent commit if [ $? -ne 0 ]; then echo "Linting failed. Fix errors before committing." exit 1 fi # Run tests npm test if [ $? -ne 0 ]; then echo "Tests failed. Fix tests before committing." exit 1 fi
Commit Message Hook
# .git/hooks/commit-msg #!/bin/sh # Enforce commit message format commit_msg=$(cat $1) if ! echo "$commit_msg" | grep -qE "^(feat|fix|docs|style|refactor|test|chore): "; then echo "Invalid commit message format." echo "Use: feat|fix|docs|style|refactor|test|chore: message" exit 1 fi
Git Aliases: Save Time
# Add to ~/.gitconfig [alias] # Shortcuts co = checkout br = branch ci = commit st = status # Log with graph lg = log --graph --oneline --all --decorate # Undo last commit undo = reset --soft HEAD~1 # Amend without editing message amend = commit --amend --no-edit # Show branches sorted by last commit recent = branch --sort=-committerdate # Clean branches (merged to main) cleanup = !git branch --merged main | grep -v "main" | xargs git branch -d
Workflow Strategies
Git Flow
main (production)
↓
develop (integration)
↓
feature/user-auth
feature/payment
hotfix/critical-bug
# Start feature git checkout -b feature/user-auth develop # Finish feature git checkout develop git merge --no-ff feature/user-auth git branch -d feature/user-auth # Hotfix git checkout -b hotfix/1.2.1 main # Fix... git checkout main git merge --no-ff hotfix/1.2.1 git checkout develop git merge --no-ff hotfix/1.2.1 git branch -d hotfix/1.2.1
Trunk-Based Development
main (always deployable)
↓
short-lived feature branches (< 1 day)
# Create short-lived branch git checkout -b quick-feature # Work... git add . git commit -m "feat: Add quick feature" # Rebase on main (keep history clean) git rebase main # Merge to main git checkout main git merge quick-feature git branch -d quick-feature
Best Practices
- ✅ Commit often, perfect later (interactive rebase)
- ✅ Write meaningful commit messages
- ✅ Rebase feature branches before merging
- ✅ Use branches for everything
- ✅ Never rebase public history
- ✅ Review changes before committing
- ✅ Keep commits atomic (one logical change)
Common Mistakes to Avoid
❌ Don't rebase public branches
# Never do this on main/develop git checkout main git rebase feature # ❌ BAD
❌ Don't force push to shared branches
# Dangerous on shared branches git push --force origin main # ❌ BAD
❌ Don't commit secrets
# Remove from history if committed git filter-branch --force --index-filter "git rm --cached --ignore-unmatch config/secrets.yml" --prune-empty --tag-name-filter cat -- --all
Conclusion
Advanced Git gives you superpowers:
- Clean, professional commit history
- Flexible workflows
- Easy bug hunting
- Confidence to experiment
Master these techniques, and Git becomes a powerful ally, not just a version control tool! 🎯✨