Git Workflow Guide: From Chaos to Clarity
Git is powerful, but teams usually struggle because they don't agree on a few basics. A simple workflow keeps history readable, reviews focused, and releases less stressful. This comprehensive guide will take you from Git chaos to clarity with battle-tested workflows used by top engineering teams.
Why Git Workflow Matters
A well-defined Git workflow is the backbone of effective collaboration. Without it, you risk:
- Merge conflicts that take hours to resolve
- Lost code from force pushes and rebases gone wrong
- Unclear history that makes debugging impossible
- Blocked deployments due to untested code in main
- Team friction from inconsistent practices
Core Git Concepts
Understanding the DAG
Git stores history as a Directed Acyclic Graph (DAG). Every commit has:
- A unique hash (SHA-1)
- Parent pointer(s) to previous commit(s)
- A tree representing file state
- Author and committer metadata
# Visualize your history git log --oneline --graph --all # Pretty format with branches git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
The Three States
Git operates in three main areas:
| Area | Purpose | Commands |
|---|---|---|
| Working Directory | Your actual files | Edit files here |
| Staging Area (Index) | Pre-commit snapshot | git add |
| Repository | Committed history | git commit |
Branching Strategies
1. Trunk-Based Development
Best for: High-velocity teams, CI/CD practices
# Main branch is always deployable main ├── feature/auth-login # Short-lived (hours to days) ├── feature/payment-gateway # Short-lived └── hotfix/security-patch # Immediate fix
Rules:
- Feature branches live less than 24 hours ideally
- All changes go through pull requests
- Main branch is always green (all tests pass)
2. Git Flow
Best for: Scheduled releases, versioned software
main # Production releases develop # Integration branch ├── feature/user-profiles ├── feature/email-notifications └── release/v2.1.0 hotfix # Emergency fixes to main
Rules:
- Main branch reflects production
- Develop branch is the integration point
- Features branch from develop
- Releases are prepared in release branches
- Hotfixes branch from main
3. GitHub Flow
Best for: Web applications, continuous deployment
main ├── add-dark-mode ├── refactor-checkout └── update-dependencies
Rules:
- Main branch is deployable
- Create feature branch from main
- Open pull request for review
- Merge to main after approval
- Deploy immediately
Essential Branch Commands
# Create and switch to new branch git checkout -b feature/my-feature git switch -c feature/my-feature # Newer syntax # List branches git branch # Local branches git branch -a # All branches (local + remote) git branch -vv # With tracking info # Switch branches git checkout main git switch main # Newer, clearer syntax # Delete branches git branch -d feature/old-feature # Safe delete (merged) git branch -D feature/abandoned # Force delete # Rename branch git branch -m old-name new-name
A Simple Team Workflow
Daily Development Cycle
- Start your day
# Get latest changes git checkout main git pull origin main # Create your feature branch git checkout -b feature/description
- Make regular commits
# Stage and commit changes git add . git commit -m "feat: add user authentication" # Or granular commits git add src/auth/ git commit -m "feat: implement JWT token generation" git add tests/auth/ git commit -m "test: add authentication unit tests"
- Keep your branch updated
# Rebase onto latest main (cleaner history) git checkout main git pull origin main git checkout feature/description git rebase main # Or merge main into your branch (preserves history) git merge main
- Open a pull request early
# Push your branch git push -u origin feature/description # Create PR with template gh pr create --title "feat: user authentication" --body-file .github/pull_request_template.md
- After review, merge back to main
# Squash merge (clean linear history) git checkout main git merge --squash feature/description # Or merge commit (preserves branch history) git merge --no-ff feature/description
Commit Message Best Practices
Conventional Commits
<type>[optional scope]: <description> [optional body] [optional footer(s)]
Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style (formatting, missing semi colons)refactor: Code refactoringperf: Performance improvementstest: Adding or correcting testschore: Build process, dependencies
# Good commit messages git commit -m "feat(auth): implement JWT token refresh" git commit -m "fix(api): handle null response from payment gateway git commit -m "fix: resolve memory leak in user session handler - Clear interval on component unmount - Add cleanup in useEffect return - Update tests to verify cleanup Fixes #456"
Commit Message Checklist
- Start with a clear verb (add, fix, remove, refactor)
- Keep the first line under 50 characters
- Use present tense ("Add feature" not "Added feature")
- Reference issues/PRs in the body
- Explain "why" not just "what"
Advanced Git Techniques
Interactive Rebase
Clean up your commit history before merging:
# Rebase last 5 commits git rebase -i HEAD~5 # Commands in interactive mode: # p, pick = use commit # r, reword = use commit, but edit the 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 this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit
Stashing Work
# Quick stash git stash push -m "WIP: refactoring user service" # Stash with untracked files git stash push -u # List stashes git stash list # Apply stash (keeps it in the list) git stash apply stash@{0} # Pop stash (removes from list) git stash pop stash@{0} # Drop stash git stash drop stash@{0} # Clear all stashes git stash clear
Cherry-Picking
Apply specific commits from other branches:
# Cherry-pick a commit git cherry-pick abc123 # Cherry-pick without committing git cherry-pick -n abc123 # Cherry-pick multiple commits git cherry-pick abc123 def456
Reflog: Your Safety Net
# View all HEAD movements git reflog # Recover a lost commit git checkout HEAD@{5} # Reset to before a bad operation git reset --hard HEAD@{3}
Handling Merge Conflicts
Prevention Strategies
- Pull frequently from the base branch
- Keep branches short-lived (hours to days)
- Communicate with teammates working on similar areas
- Use feature flags for long-running features
Conflict Resolution
# When conflict occurs during merge git merge main # Auto-merging file.txt # CONFLICT (content): Merge conflict in file.txt # See conflicted files git status # Open file and resolve (look for <<<<<<< markers) # <<<<<<< HEAD # your changes # ======= # their changes # >>>>>>> branch-name # Mark as resolved git add file.txt # Complete the merge git commit # Opens editor with merge commit message
Using Merge Tools
# Configure merge tool git config --global merge.tool vscode git config --global mergetool.vscode.cmd "code --wait $MERGED" # Launch merge tool git mergetool
Code Review Checklist
Before requesting review:
- Code compiles/builds successfully
- All tests pass locally
- New code has tests
- No console.log or debug code
- Commit messages follow convention
- Branch is up to date with main
- PR description explains changes and why
- Linked related issues
During review, focus on:
- Code correctness and edge cases
- Architecture and design patterns
- Performance implications
- Security considerations
- Test coverage
- Documentation updates
CI/CD Integration
Pre-commit Hooks
# .pre-commit-config.yaml repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/commitlint/commitlint rev: v17.0.0 hooks: - id: commitlint stages: [commit-msg]
Branch Protection Rules
Configure in your Git hosting platform:
- Require pull request reviews before merging
- Require status checks to pass (CI tests)
- Require branches to be up to date before merging
- Restrict pushes that create files larger than 100MB
- Require signed commits (for security)
Common Git Scenarios
Scenario 1: Undo Last Commit
# Undo commit, keep changes staged git reset --soft HEAD~1 # Undo commit, keep changes in working directory git reset HEAD~1 # Undo commit, discard changes (DANGEROUS) git reset --hard HEAD~1 # Undo a pushed commit (use carefully!) git revert HEAD git push
Scenario 2: Split a Commit
# Start interactive rebase git rebase -i HEAD~3 # Mark commit with 'edit' # Reset to before the commit, keep changes git reset HEAD^ # Stage and commit separately git add file1.js git commit -m "feat: add user validation" git add file2.js git commit -m "feat: add password hashing" # Continue rebase git rebase --continue
Scenario 3: Move Commit to Different Branch
# Cherry-pick the commit to new branch git checkout target-branch git cherry-pick abc123 # Remove from original branch git checkout original-branch git reset --hard HEAD~1 # If it's the last commit
Best Practices Summary
Do's
- Commit early, commit often
- Write meaningful commit messages
- Pull before pushing
- Use feature branches for all work
- Review code before merging
- Keep branches up to date
- Tag releases
Don'ts
- Commit directly to main/production branches
- Force push to shared branches
- Commit large binary files
- Include secrets in commits
- Make massive, unrelated commits
- Ignore merge conflicts
- Use
git push --forcewithout--force-with-lease
Tools and Extensions
CLI Tools
# tig: Text-mode interface for Git npm install -g tig # lazygit: Simple terminal UI for Git npm install -g lazygit # gh: GitHub CLI gh pr create gh pr merge gh issue list
VS Code Extensions
- GitLens - Enhanced Git capabilities
- Git Graph - Visual Git graph
- GitHub Pull Requests - Review PRs in editor
- Git History - View file history
Conclusion
The goal isn't "perfect Git" — it's fewer surprises and faster collaboration. Start simple, write down the rules, and improve them as your team grows.
Key takeaways:
- Choose a workflow that fits your team size and release schedule
- Keep branches short-lived to minimize conflicts
- Write good commit messages for future debugging
- Review code thoroughly before merging
- Automate checks with pre-commit hooks and CI
Remember: Git is a tool to help you collaborate, not a burden to endure. Master these fundamentals, and you'll spend less time wrestling with version control and more time building great software.