Git Advanced Guide 2026 — Branching Strategies, Rebase, and Team Workflows
Advertisement
Introduction
Why This Matters
Most developers use 10% of Git's capabilities. The other 90% — interactive rebase, bisect, hooks, cherry-pick, and branching strategies — are what separate engineers who ship clean code from those who ship messy histories. Mastering Git makes you faster at debugging, better at code review, and a more effective collaborator in any team.
Branching Strategies
Trunk-Based Development (recommended for teams using CI/CD):
main ← always deployable, deployed on every merge
├── feature/add-oauth → merge within 1-2 days
├── fix/payment-bug → merge within hours
└── release/v2.0 → cut from main, hotfixes onlyGit Flow (for software with scheduled release cycles):
main ← production releases only
develop ← integration branch
├── feature/* → branch from develop, merge to develop
├── release/* → from develop → merge to main + develop
└── hotfix/* → from main → merge to main + developFor most teams in 2026: trunk-based development with feature flags is the faster approach.
Interactive Rebase: Clean Up History
# Squash last 5 messy commits into clean commits before pushing
git rebase -i HEAD~5
# Editor opens with:
# pick a1b2c3 Add user auth
# pick e4f5g6 Fix typo
# pick h7i8j9 Add tests
# pick l0m1n2 WIP
# pick p3q4r5 Fix WIP
# Change to:
# pick a1b2c3 Add user auth
# squash e4f5g6 Fix typo (merge into previous)
# pick h7i8j9 Add tests
# fixup l0m1n2 WIP (merge + discard message)
# fixup p3q4r5 Fix WIP
# Commands:
# pick = use as-is
# squash = merge into previous, combine messages
# fixup = merge into previous, discard message
# reword = change commit message only
# drop = delete commit entirelyCherry-Pick: Apply Specific Commits
# Apply a single commit from another branch
git cherry-pick a1b2c3
# Cherry-pick a range
git cherry-pick a1b2c3..p3q4r5
# Cherry-pick without committing (inspect first)
git cherry-pick --no-commit a1b2c3
# Common use case: backport a hotfix to a release branch
git checkout release/v2.0
git cherry-pick a1b2c3 # Only the bugfix commitGit Bisect: Binary Search for Bugs
# "My app broke somewhere in the last 300 commits. Which one?"
git bisect start
git bisect bad # Current HEAD is broken
git bisect good v1.5.0 # This tag was working fine
# Git checks out the midpoint commit
# Test your app, then tell Git:
git bisect good # This commit is OK → search later half
git bisect bad # This commit broke it → search earlier half
# After ~8 iterations (log base 2 of 300), Git shows the culprit
git bisect reset # Return to HEAD when done
# Fully automated: provide a test script
git bisect run npm test # Passes = good, fails = badStash: Save Work Without Committing
# Save current changes
git stash
git stash push -m "WIP: payment integration"
git stash push --include-untracked # Include new files
# List stashes
git stash list
# stash@{0}: WIP: payment integration
# stash@{1}: On main: UI experiment
# Apply stash
git stash pop # Apply and remove stash@{0}
git stash apply stash@{1} # Apply without removing
git stash drop stash@{0} # Delete specific stash
git stash branch feat/from-stash stash@{0} # Create branch from stashGit Hooks with Husky
# Install Husky and lint-staged
npm install -D husky lint-staged
npx husky init{
"lint-staged": {
"*.{ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{json,md,yml}": ["prettier --write"]
}
}#!/bin/sh
# .husky/pre-commit
npx lint-staged#!/bin/sh
# .husky/commit-msg
# Enforce Conventional Commits format
commit_msg=$(cat "$1")
pattern="^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?: .{1,72}"
if ! echo "$commit_msg" | grep -qE "$pattern"; then
echo "Commit message must follow Conventional Commits:"
echo " type(scope): description"
echo " Example: feat(auth): add JWT refresh rotation"
exit 1
fiConventional Commits
# Format: type(scope): description
feat(auth): add Google OAuth login
fix(api): handle null user in getProfile
docs(readme): update local dev setup
refactor(db): extract repository pattern
test(auth): add unit tests for JWT refresh
perf(search): add vector index for AI search
ci(actions): add staging deploy workflow
chore(deps): bump Next.js to 15.3.0Monorepo with Turborepo
{
"name": "my-monorepo",
"workspaces": ["apps/*", "packages/*"]
}{
"$schema": "https://turborepo.com/schema.json",
"pipeline": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "dist/**"]
},
"test": { "outputs": ["coverage/**"] },
"lint": {}
}
}# Run commands across all packages with caching
turbo build # Build all (uses cache for unchanged)
turbo test # Test all in parallel
turbo lint --filter=web # Only the web app
turbo build --filter=...api # api + all its dependenciesCommon Mistakes
- Rebasing shared branches — never rebase commits that have been pushed and pulled by teammates; it rewrites history they depend on
- Giant commits — each commit should represent one logical change; giant commits make
git bisectandgit blameuseless - No
.gitignore— always ignorenode_modules,.env, build artifacts, and OS files from the start - Force-pushing to main — this is irreversible and overwrites teammates' work; protect main with branch protection rules
- Skipping pre-commit hooks —
git commit --no-verifydefeats the entire purpose of automated quality checks
Best Practices
- Write commit messages in the imperative mood: "Add auth" not "Added auth" or "Adding auth"
- Use
git log --oneline --graph --allto visualize branch relationships when debugging merge conflicts - Set up branch protection rules: require PRs, status checks, and at least one reviewer before merging to main
- Use
git reflogto recover from mistakes — it tracks every HEAD movement for 90 days, even after rebase and reset - Run
git diff --stagedbefore committing to review exactly what you are about to commit
Key Takeaways
- Trunk-based development with short-lived feature branches is faster than Git Flow for teams deploying multiple times per day
- Interactive rebase (
git rebase -i HEAD~N) cleans up commit history before merging — squash WIP commits into meaningful ones git bisectuses binary search to find the exact commit that introduced a bug across hundreds of commits in under 10 steps- Cherry-pick applies individual commits across branches — the right tool for backporting hotfixes to release branches
- Husky pre-commit hooks enforce linting and formatting automatically, keeping code quality consistent across the team
- Conventional Commits (
feat:,fix:,chore:) enable automated changelogs and semantic version bumping - Turborepo builds only what changed in a monorepo and caches results remotely — speeds up CI by 60-80% on large repos
git reflogis the safety net: it records every action including rebase and reset, letting you recover lost commits
Advertisement