Git is flexible enough to support almost any workflow. That flexibility is both a blessing and a curse — without clear patterns, teams end up with merge conflicts, lost work, and frustration. Here are workflows that work.
Solo Developer: Simple Trunk# When you’re working alone, keep it simple:
1
2
3
4
5
6
7
8
# Work directly on main
git checkout main
git pull
# Make changes
git add .
git commit -m "Add feature X"
git push
That’s it. No branches, no PRs, no ceremony. Save complexity for when you need it.
When to Add Branches# Even solo, branches help when:
Experimenting with risky changes Working on multiple features simultaneously Needing to switch context quickly 1
2
3
4
5
6
# Feature branch
git checkout -b experiment/new-approach
# ... work ...
git checkout main
git merge experiment/new-approach
git branch -d experiment/new-approach
Small Team: GitHub Flow# For teams of 2-10, GitHub Flow is the sweet spot:
main is always deployableCreate feature branches from main Open PR when ready for review Merge to main after approval Deploy from main 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Start feature
git checkout main
git pull
git checkout -b feature/user-auth
# Work and commit
git add .
git commit -m "Add login form"
git push -u origin feature/user-auth
# Open PR on GitHub/GitLab
# After review and approval, merge via UI
# Clean up
git checkout main
git pull
git branch -d feature/user-auth
Branch Naming# 1
2
3
4
5
6
feature/short-description # New features
fix/bug-description # Bug fixes
hotfix/critical-issue # Urgent production fixes
chore/maintenance-task # Non-feature work
docs/what-documented # Documentation
refactor/what-changed # Code restructuring
Larger Teams: GitFlow# For teams with scheduled releases and multiple environments:
m h r d f a o e e e i t l v a n f e e t i a l u x s o r e p e ─ │ │ ● ● ─ │ │ │ ─ │ ─ ● ─ ─ ─ ─ ─ ─ ─ ─ ─ ● │ ┴ ● ─ ─ │ │ ─ ─ ─ ─ ─ ─ ─ ─ ● │ ┴ ─ │ │ ─ ● ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ● ┴ ─ ─ ─ │ ─ ● ─ ─ ─ ─ ─ ─ ─ ● ─ ─ ─ ● ─ │ ┘ ─ │ ● │ ─ ─ │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ( ( ( i ( ( e r n d p m e t e r e l e v o r e g e d g a r l u e s a o c n e t p t c i m i y p o e o r n n n f e ) t ) i p ) x ) e s )
Branches:
main — Production code, tagged releases onlydevelop — Integration branch, always deployable to stagingfeature/* — New features, branch from developrelease/* — Release preparation, branch from develophotfix/* — Emergency fixes, branch from main 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Start feature
git checkout develop
git pull
git checkout -b feature/new-thing
# Finish feature
git checkout develop
git merge --no-ff feature/new-thing
git push
git branch -d feature/new-thing
# Start release
git checkout develop
git checkout -b release/1.2.0
# ... version bumps, final fixes ...
# Finish release
git checkout main
git merge --no-ff release/1.2.0
git tag -a v1.2.0 -m "Release 1.2.0"
git checkout develop
git merge --no-ff release/1.2.0
git branch -d release/1.2.0
# Hotfix
git checkout main
git checkout -b hotfix/security-patch
# ... fix ...
git checkout main
git merge --no-ff hotfix/security-patch
git tag -a v1.2.1 -m "Security patch"
git checkout develop
git merge --no-ff hotfix/security-patch
git branch -d hotfix/security-patch
Trunk-Based Development# For teams with strong CI/CD and feature flags:
1
2
3
4
5
6
7
8
9
10
11
# Everyone works on main
git checkout main
git pull
# Short-lived branches (< 1 day)
git checkout -b short-feature
# ... small, focused change ...
git checkout main
git merge short-feature
git push
git branch -d short-feature
Key principles:
Branches live less than a day Feature flags hide incomplete work Strong CI catches issues immediately Everyone integrates frequently 1
2
3
4
5
# Feature flags instead of long branches
if feature_flags . enabled ( "new_checkout" ):
return new_checkout_flow ()
else :
return old_checkout_flow ()
Commit Messages# Conventional Commits# t L F y o i p n x e g e ( e s s r c # o e 1 p x 2 e p 3 ) l : a n s a h t o i r o t n d i e f s c n r e i e p d t e i d o . n
Types:
feat: — New featurefix: — Bug fixdocs: — Documentationstyle: — Formatting (no code change)refactor: — Code restructuringtest: — Adding testschore: — Maintenance1
2
3
4
5
6
feat( auth) : add OAuth2 login support
Implements Google and GitHub OAuth providers.
Includes token refresh and secure storage.
Closes #456
Good vs Bad# 1
2
3
4
5
6
7
8
9
10
# Bad
git commit -m "fix"
git commit -m "WIP"
git commit -m "stuff"
git commit -m "asdfasdf"
# Good
git commit -m "fix(api): handle null response from payment gateway"
git commit -m "feat(ui): add dark mode toggle to settings"
git commit -m "docs: update API authentication examples"
Handling Common Situations# Sync Feature Branch with Main# 1
2
3
4
5
6
7
8
9
10
11
# Option 1: Merge (preserves history)
git checkout feature/my-feature
git merge main
# Option 2: Rebase (cleaner history)
git checkout feature/my-feature
git rebase main
# If conflicts, resolve then:
git add .
git rebase --continue
Undo Last Commit# 1
2
3
4
5
6
7
8
# Keep changes staged
git reset --soft HEAD~1
# Keep changes unstaged
git reset HEAD~1
# Discard changes completely (careful!)
git reset --hard HEAD~1
Fix Commit Message# 1
2
3
4
5
6
# Last commit
git commit --amend -m "New message"
# Older commit (interactive rebase)
git rebase -i HEAD~3
# Change 'pick' to 'reword' for the commit
Squash Commits Before PR# 1
2
3
git rebase -i HEAD~5
# Change 'pick' to 'squash' for commits to combine
# Keep first commit as 'pick'
Cherry-Pick Specific Commit# 1
2
git checkout main
git cherry-pick abc1234
Stash Work in Progress# 1
2
3
4
5
6
7
8
9
10
11
12
13
# Save current changes
git stash
# Do other work...
# Restore changes
git stash pop
# List stashes
git stash list
# Apply specific stash
git stash apply stash@{ 2}
Pull Request Best Practices# Before Opening# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Update with latest main
git checkout main
git pull
git checkout feature/my-feature
git rebase main
# Run tests locally
npm test
# Check for lint issues
npm run lint
# Review your own changes
git diff main...feature/my-feature
PR Template# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
## Summary
Brief description of changes.
## Changes
- Added X
- Modified Y
- Removed Z
## Testing
- [ ] Unit tests pass
- [ ] Manual testing completed
- [ ] Edge cases considered
## Screenshots
(if UI changes)
## Related Issues
Closes #123
Review Checklist# Branch Protection# Configure in GitHub/GitLab:
1
2
3
4
5
6
# Required for main branch:
- Require PR reviews (1-2 approvers)
- Require status checks (CI must pass)
- Require up-to-date branches
- No force pushes
- No deletions
Quick Reference# Situation Command Start feature git checkout -b feature/nameSync with main git rebase mainSquash commits git rebase -i HEAD~nUndo last commit git reset --soft HEAD~1Stash changes git stash / git stash popCherry-pick git cherry-pick <sha>Clean branches git branch -d nameForce push (careful!) git push --force-with-lease
The best workflow is one your team actually follows. Start simple (GitHub Flow), add complexity only when needed. Clear conventions and automation matter more than the specific workflow you choose.