Broken code in production on a Friday night. Merge conflicts that should’ve been caught days ago. Familiar?
Most Git workflow guides target massive teams. For 2-10 developers, you need something simpler.
This guide covers conventions that prevent disasters without drowning you in process.
⏱️ Reading time: 15-20 minutes
Why Bother With Git Strategy?
No structure means people push straight to main, merge conflicts pile up, and nobody knows what’s deployed where.
A simple Git workflow fixes that:
- No Friday disasters - Clear rules, fewer accidents
- Code gets reviewed - Branch protection enforces it
- Staging stays stable - Separate environments help
- New devs onboard fast - They know where to push on day one
- Async work works - Timezones don’t cause collisions
A good Git strategy isn’t about following rules perfectly - it’s about making it harder to accidentally break production while keeping deployment fast.
Our Recommended Branching Model
A simplified Git Flow for small teams, with four branch types:
How This Actually Works: Real Example
Sarah builds user authentication. Mike works on a dashboard. Two features, two developers, no drama.
Phase 1: Project Setup (Yes, boring but important)
# Someone (usually whoever starts the project) does this once:
git init
git commit -m "chore: initial commit"
# Create develop branch - this is where features get integrated
git checkout -b develop
git commit -m "chore: setup dev environment"
git push -u origin develop
Now you have main (production) and develop (integration).
Phase 2: Dev-A Works on User Authentication
Dev-A’s workflow:
# Dev-A creates feature branch from develop
git checkout develop
git pull origin develop
git checkout -b feature/user-auth
# Dev-A implements login form
git add src/auth/LoginForm.tsx
git commit -m "feat(auth): add login form component"
# Dev-A implements authentication logic
git add src/auth/authentication.ts
git commit -m "feat(auth): add JWT authentication logic"
# Dev-A pushes feature branch
git push -u origin feature/user-auth
Dev-A works in isolation on feature/user-auth. Nobody else is affected.
Phase 3: Dev-A Creates Pull Request
Dev-A creates PR:
# Dev-A ensures branch is up to date
git checkout feature/user-auth
git pull origin develop # Get latest changes
git push origin feature/user-auth
# Create Pull Request via GitLab/GitHub UI or CLI
gh pr create \
--base develop \
--head feature/user-auth \
--title "feat: Add user authentication system" \
--body "## Changes
- Add login form component
- Implement JWT authentication
- Add token refresh mechanism
## Testing
- [x] Unit tests pass
- [x] Manual testing completed
- [x] No breaking changes
Closes #123"
PR Review Process:
- Dev-B reviews the code
- Dev-B comments: “Add error handling for token expiration”
- Dev-A pushes fixes
- Dev-B approves
Merge to develop:
# After PR approval, Dev-A or team lead merges
git checkout develop
git pull origin develop
git merge --no-ff feature/user-auth
git tag -a v1.1.0-dev -m "Dev release: User authentication"
git push origin develop --follow-tags
# Clean up feature branch
git branch -d feature/user-auth
git push origin --delete feature/user-auth
Result: auth merged into develop as v1.1.0-dev, feature branch deleted.
Phase 4: Deploy to Staging for Testing
Team lead creates PR: develop -> staging:
# Team lead creates staging release PR
gh pr create \
--base staging \
--head develop \
--title "release: v1.1.0-rc1 - User authentication" \
--body "## Release Candidate v1.1.0-rc1
### Features
- User authentication system (PR #45)
### QA Checklist
- [ ] Login flow works correctly
- [ ] Token refresh working
- [ ] Error handling verified
- [ ] Performance acceptable
- [ ] Security scan passed
### Deployment
- Target: Staging environment
- Expected deployment time: 5 minutes"
Merge to staging:
# After PR approval from team lead
git checkout staging
git pull origin staging
git merge --no-ff develop
git tag -a v1.1.0-rc1 -m "Release Candidate: User authentication"
git push origin staging --follow-tags
Result: develop merged to staging with RC tag. CI/CD auto-deploys. QA begins.
Phase 5: Deploy to Production
After staging tests pass, team lead creates production PR:
# Team lead creates production release PR
gh pr create \
--base main \
--head staging \
--title "release: v1.1.0 - User authentication system" \
--body "## Production Release v1.1.0
### What's New
- User authentication with JWT tokens
- Login/logout functionality
- Token refresh mechanism
### QA Status
- All tests passed on staging
- Manual QA completed
- Security scan: No issues
- Performance: Within acceptable limits
### Rollback Plan
If issues occur, rollback to v1.0.0:
\`\`\`bash
git checkout main
git reset --hard v1.0.0
git push --force origin main
\`\`\`"
Merge to production:
# After all approvals (requires 2 reviewers for main)
git checkout main
git merge --no-ff staging
git tag -a v1.1.0 -m "Release v1.1.0: User authentication system"
git push origin main --follow-tags
Result: 2 approvals obtained, user auth live as v1.1.0, rollback plan documented.
Phase 6: Dev-B Works on Dashboard (Parallel Development)
Dev-B starts before v1.1.0 reaches production:
# Dev-B creates feature branch from latest develop
git checkout develop
git pull origin develop # Gets v1.1.0-dev code
git checkout -b feature/dashboard
# Dev-B implements dashboard
git add src/dashboard/
git commit -m "feat(dashboard): create user dashboard with metrics"
# Dev-B pushes work
git push -u origin feature/dashboard
Dev-B works independently while Dev-A’s code is being tested.
Phase 7: Dev-B Creates Pull Request for Dashboard
Dev-B creates PR:
# Dev-B ensures feature is ready
git checkout feature/dashboard
git pull origin develop # Sync with latest develop
git push origin feature/dashboard
# Create Pull Request
gh pr create \
--base develop \
--head feature/dashboard \
--title "feat: Add user dashboard with metrics" \
--body "## Changes
- Create dashboard layout component
- Add real-time metrics display
- Implement data fetching hooks
## Testing
- [x] Unit tests pass
- [x] Integration tests pass
- [x] Tested on Chrome, Firefox, Safari
## Dependencies
- Requires authentication feature (already merged)
Closes #124"
PR Review Process:
- Dev-A reviews the code
- Dev-A comments: “Add loading states”
- Dev-B pushes update
- Dev-A approves
Merge to develop:
# After PR approval
git checkout develop
git pull origin develop
git merge --no-ff feature/dashboard
# No tag needed this time (optional for dev releases)
git push origin develop
# Clean up
git branch -d feature/dashboard
git push origin --delete feature/dashboard
Result: dashboard integrated into develop.
Phase 8: Deploy Dashboard to Staging
Team lead creates staging PR:
# Create PR: develop → staging
gh pr create \
--base staging \
--head develop \
--title "release: v1.2.0-rc1 - User dashboard" \
--body "## Release Candidate v1.2.0-rc1
### New Features
- User dashboard with real-time metrics (PR #46)
### Included in this release
- User authentication (v1.1.0)
- Dashboard feature (v1.2.0)
### QA Checklist
- [ ] Dashboard displays correctly
- [ ] Metrics update in real-time
- [ ] Loading states work
- [ ] Compatible with existing auth
### Deployment
- Target: Staging environment"
Merge to staging:
# After PR approval
git checkout staging
git pull origin staging
git merge --no-ff develop
git tag -a v1.2.0-rc1 -m "Release Candidate: Dashboard feature"
git push origin staging --follow-tags
Result: staging has both auth and dashboard. QA validates.
Phase 9: Deploy Dashboard to Production
After QA approval, team lead creates production PR:
# Create production release PR
gh pr create \
--base main \
--head staging \
--title "release: v1.2.0 - User dashboard" \
--body "## Production Release v1.2.0
### What's New
- User dashboard with real-time metrics
- Performance monitoring charts
- Responsive design for mobile/desktop
### QA Status
- All staging tests passed
- Performance: Page load < 2s
- Accessibility: WCAG AA compliant
- Cross-browser tested
### Rollback Plan
If issues occur, rollback to v1.1.0:
\`\`\`bash
git checkout main
git reset --hard v1.1.0
git push --force origin main
\`\`\`
### Deployment Window
- Scheduled: Tuesday 2PM UTC (low traffic period)
- Duration: ~5 minutes
- Monitoring: 1 hour post-deployment"
Merge to production:
# After 2 reviewers approve
git checkout main
git merge --no-ff staging
git tag -a v1.2.0 -m "Release v1.2.0: User dashboard"
git push origin main --follow-tags
Result: 2 approvals, dashboard live as v1.2.0, team monitors for 1 hour.
Key Takeaways from This Workflow
Parallel Development
- Dev-A and Dev-B worked simultaneously without conflicts
- Feature branches kept work isolated
Quality Gates
- Every feature went through: develop -> staging -> main
- QA tested on staging before production
Clear History
- Version tags show what’s in each release
- Easy to track what reached production and when
Safe Rollbacks
- Roll back to any previous version via git tags
- Staging catches issues before production
Team Coordination
- Develop integrates features
- Staging gates production
- Main always reflects production
Branch Structure Overview
| Branch | Purpose | Lifetime | Protected | Deploys To |
|---|---|---|---|---|
main | Production-ready code | Permanent | ✅ Yes | Production |
staging | Pre-production testing | Permanent | ✅ Yes | Staging Environment |
develop | Integration branch | Permanent | ✅ Yes | Development Environment |
feature/* | Feature development | Temporary | ❌ No | Preview (optional) |
bugfix/* | Bug fixes | Temporary | ❌ No | - |
hotfix/* | Emergency production fixes | Temporary | ❌ No | - |
Branch Purposes and Rules
1. Main Branch (main)
Purpose: Production-ready, tested, approved code only.
Rules:
- Always deployable
- Protected — no direct commits
- Only accepts merges from
staging - Requires code review approval
- All CI/CD tests must pass
- Tagged with semantic versions (v1.0.0, v1.1.0, etc.)
Who can merge: Team lead or release manager
Deployment: Auto-deploys to production after merge (with approval)
# ❌ NEVER do this
git checkout main
git commit -m "Quick fix"
git push
# ALWAYS do this
git checkout -b hotfix/critical-bug
# Make changes
git push origin hotfix/critical-bug
# Create pull request to staging → main
2. Staging Branch (staging)
Purpose: Pre-production testing. Mirrors production.
Rules:
- Protected — no direct commits
- Only accepts merges from
developorhotfix/* - Requires 1 approval
- All automated tests must pass
- Used for QA and client demos
- Tagged with release candidates (v1.1.0-rc1, v1.1.0-rc2)
Who can merge: Any developer with approval
Deployment: Auto-deploys to staging environment
Testing checklist before promoting to main:
- All features work as expected
- No breaking changes
- Performance is acceptable
- Security scan passed
- Client/stakeholder approval (if needed)
3. Develop Branch (develop)
Purpose: Integration branch where features come together.
Rules:
- Protected — no direct commits
- Accepts merges from
feature/*andbugfix/* - Requires code review (lighter than staging)
- CI/CD tests should pass
- Most active branch
Who can merge: Any developer after review
Deployment: Auto-deploys to development environment
# Feature is complete and tested
git checkout develop
git pull origin develop
git merge --no-ff feature/user-authentication
git push origin develop
4. Feature Branches (feature/*)
Purpose: Isolated feature development.
Rules:
- Branch from
develop - Merge back to
developwhen complete - Delete after merging
- One feature per branch
- Sync with
developregularly
Lifetime: Created at feature start, deleted after merge
Naming convention: feature/short-descriptive-name
# Create feature branch
git checkout develop
git pull origin develop
git checkout -b feature/user-dashboard
# Work on feature
git add .
git commit -m "feat: add user dashboard layout"
git push origin feature/user-dashboard
# Keep up to date with develop
git checkout develop
git pull origin develop
git checkout feature/user-dashboard
git merge develop
5. Bugfix Branches (bugfix/*)
Purpose: Fix bugs found in development or staging.
Rules:
- Branch from
develop - Merge back to
develop - Delete after merging
Naming convention: bugfix/issue-description
6. Hotfix Branches (hotfix/*)
Purpose: Emergency production fixes.
Rules:
- Branch from
main - Merge to both
mainANDdevelop - Highest priority
- Minimal changes only
Naming convention: hotfix/critical-issue-description
Workflow:
# Production is broken!
git checkout main
git pull origin main
git checkout -b hotfix/payment-gateway-crash
# Fix the issue
git add .
git commit -m "fix: resolve payment gateway timeout"
git push origin hotfix/payment-gateway-crash
# Create pull requests:
# 1. hotfix/payment-gateway-crash → staging → main
# 2. hotfix/payment-gateway-crash → develop
Branch Protection Rules
What to configure in GitHub/GitLab — the settings that prevent disasters:
Protect Your Main Branch (Non-negotiable)
Production. Lock it down.
- ✅ 2 approvals required - No solo merges to prod
- ✅ CI must pass - Build, tests, security scans
- ❌ No force pushes - Ever
- 🔒 Only team leads can merge - Someone owns this
Skip: signed commits, conversation resolution, branch deletion protection. Overhead for small teams.
If you forgot to create a feature branch and committed directly to main (we’ve all done it), check out our guide on how to fix accidental commits to main. It walks you through moving your commits to a feature branch safely without losing any work.
Staging Branch Protection
Lighter than main:
- ✅ 1 approval required - Quick review before testing
- ✅ CI must pass - Build and tests (skip heavy scans)
- ❌ No force pushes - Keep history clean
Develop Branch Protection
Basic guardrails:
- ✅ 1 approval - Catch obvious issues
- ✅ Build + lint must pass - Don’t break the integration branch
- ❌ No force pushes - Play nice with others
These prevent 90% of problems.
Naming Conventions
Branch Naming
Pattern: <type>/<short-description>
Types:
feature/- New featuresbugfix/- Bug fixeshotfix/- Production hotfixesrefactor/- Code refactoringdocs/- Documentation updatestest/- Adding testschore/- Maintenance tasks
Examples:
| ✅ Good Branch Names | ❌ Bad Branch Names | Why? |
|---|---|---|
feature/user-authentication | fix-stuff | Vague, no context |
feature/payment-integration | johns-branch | Says nothing about the work |
bugfix/login-redirect-loop | temp | ”Temporary” branches live forever |
hotfix/database-connection-timeout | new-feature | Which feature? |
refactor/api-error-handling | branch-1 | Meaningless in 2 weeks |
docs/api-documentation | wip | Everything is WIP |
feature/123-user-dashboard | test | Testing what? |
Branch naming rules:
- Kebab-case only -
feature/user-auth, notfeature/userAuthorfeature/user_auth - 2-4 words max - Descriptive but concise
- Present tense -
feature/add-loginnotfeature/added-login - Include issue numbers -
feature/123-user-dashboardlinks to issue #123 - No special characters - Only
/and-
Commit Messages (Keep It Simple)
Pattern:
<type>: what you actually did
The three types you need:
feat:- New feature (e.g., “feat: add login page”)fix:- Bug fix (e.g., “fix: prevent crash on empty input”)chore:- Maintenance (e.g., “chore: update dependencies”)
More types exist (docs, style, refactor, perf, test, ci, build), but start with these three.
Good commit messages:
feat: add JWT token refresh mechanism
fix: resolve timeout in user API endpoint
chore: update axios to v1.6.0
Bad commit messages (we’ve all done these):
fixed bug
updated files
WIP
asdfgh
more stuff
final version
final version 2 # <- guilty
Optional scope for larger projects:
feat(auth): add JWT refresh
fix(api): resolve user endpoint timeout
For small teams, the simple version works.
Commit message template:
Create .gitmessage in your repository:
# <type>(<scope>): <subject>
# |<---- Using a Maximum Of 50 Characters ---->|
# Explain why this change is being made
# |<---- Try To Limit Each Line to a Maximum Of 72 Characters ---->|
# Provide links or keys to any relevant tickets, articles or other resources
# Example: Closes #23
# --- COMMIT END ---
# Type can be
# feat (new feature)
# fix (bug fix)
# refactor (refactoring production code)
# style (formatting, missing semi colons, etc; no code change)
# docs (changes to documentation)
# test (adding or refactoring tests; no production code change)
# chore (updating grunt tasks etc; no production code change)
# perf (performance improvements)
# ci (CI/CD changes)
# build (build system changes)
# --------------------
# Remember to
# Capitalize the subject line
# Use the imperative mood in the subject line
# Do not end the subject line with a period
# Separate subject from body with a blank line
# Use the body to explain what and why vs. how
# Can use multiple lines with "-" for bullet points in body
# --------------------
Configure git to use this template:
git config --global commit.template .gitmessage
Tag Naming Convention
Use Semantic Versioning (semver.org): vMAJOR.MINOR.PATCH
Format: vX.Y.Z
- MAJOR (X): Breaking changes
- MINOR (Y): New features (backward compatible)
- PATCH (Z): Bug fixes (backward compatible)
Examples:
# Production releases (on main)
v1.0.0 # Initial release
v1.1.0 # Added new feature
v1.1.1 # Bug fix
v2.0.0 # Breaking changes
# Release candidates (on staging)
v1.1.0-rc1 # First release candidate
v1.1.0-rc2 # Second release candidate
# Pre-releases (on develop)
v1.1.0-alpha
v1.1.0-beta
Creating tags:
# Annotated tag (recommended)
git tag -a v1.2.0 -m "Release version 1.2.0: Add user dashboard and notifications"
# Push tag to remote
git push origin v1.2.0
# Push all tags
git push origin --tags
Complete Workflow Examples
Scenario 1: Developing a New Feature
# 1. Start from latest develop
git checkout develop
git pull origin develop
# 2. Create feature branch
git checkout -b feature/notification-system
# 3. Work on feature (make multiple commits)
git add src/notifications/
git commit -m "feat(notifications): add email notification service"
git add src/notifications/
git commit -m "feat(notifications): add push notification support"
git add tests/notifications/
git commit -m "test(notifications): add notification service tests"
# 4. Keep branch updated (if develop has moved ahead)
git checkout develop
git pull origin develop
git checkout feature/notification-system
git merge develop
# 5. Push feature branch
git push origin feature/notification-system
# 6. Create Pull Request: feature/notification-system → develop
# - Add description of changes
# - Request reviewer
# - Link related issues
# 7. After approval and merge, delete branch
git checkout develop
git pull origin develop
git branch -d feature/notification-system
git push origin --delete feature/notification-system
Scenario 2: Releasing to Production
# 1. Merge develop to staging
git checkout staging
git pull origin staging
git merge develop
git push origin staging
# Tag release candidate
git tag -a v1.3.0-rc1 -m "Release candidate for v1.3.0"
git push origin v1.3.0-rc1
# 2. Test on staging environment
# - Run manual tests
# - Check all features
# - Get stakeholder approval
# 3. If tests pass, merge staging to main
git checkout main
git pull origin main
git merge staging
git push origin main
# 4. Tag production release
git tag -a v1.3.0 -m "Release v1.3.0: Add notification system and user dashboard"
git push origin v1.3.0
# 5. Ensure develop is synced
git checkout develop
git merge main
git push origin develop
Scenario 3: Emergency Production Hotfix
# 1. Branch from main
git checkout main
git pull origin main
git checkout -b hotfix/payment-api-timeout
# 2. Fix the issue
git add src/payment/
git commit -m "fix(payment): increase API timeout to 30s"
# 3. Test locally
npm test
# 4. Push and create PR to staging first
git push origin hotfix/payment-api-timeout
# Create PR: hotfix/payment-api-timeout → staging
# 5. After staging tests pass, merge to main
# Create PR: staging → main
# 6. Merge hotfix to develop
git checkout develop
git pull origin develop
git merge hotfix/payment-api-timeout
git push origin develop
# 7. Tag hotfix release
git checkout main
git tag -a v1.3.1 -m "Hotfix v1.3.1: Fix payment API timeout"
git push origin v1.3.1
# 8. Delete hotfix branch
git branch -d hotfix/payment-api-timeout
git push origin --delete hotfix/payment-api-timeout
Scenario 4: Handling Merge Conflicts
# You're on feature branch and want to merge develop
git checkout feature/user-profile
git merge develop
# Conflict detected!
# Auto-merging src/components/Profile.tsx
# CONFLICT (content): Merge conflict in src/components/Profile.tsx
# 1. Check conflicted files
git status
# 2. Open files and resolve conflicts
# Look for conflict markers:
# <<<<<<< HEAD
# Your changes
# =======
# Changes from develop
# >>>>>>> develop
# 3. After resolving, mark as resolved
git add src/components/Profile.tsx
# 4. Complete the merge
git commit -m "merge: resolve conflicts with develop"
# 5. Push updated branch
git push origin feature/user-profile
Pull Request Guidelines
Creating Pull Requests
PR Title Format:
PR titles show up in changelogs, Git history, and Slack notifications. Make them count.
Format:
<type>: <what you actually did>
✅ Good PR titles:
feat: Add user notification system
fix: Resolve login redirect loop on expired tokens
docs: Update API authentication guide
refactor: Optimize database query performance in user service
hotfix: Patch XSS vulnerability in comment form
feat(auth): Add JWT refresh token rotation
❌ Bad PR titles:
Update notifications # Update how? What changed?
Fixed bug # Which bug? Where?
Docs # What docs? Too vague
Code cleanup # What code? Cleanup how?
Security fix # Need specifics for hotfixes
Add feature # Which feature?
Title length: 50-72 characters. Longer means your PR is probably too big.
PR Description Template:
## Description
Brief description of changes made
## Type of Change
- [ ] New feature
- [ ] Bug fix
- [ ] Breaking change
- [ ] Documentation update
- [ ] Refactoring
- [ ] Performance improvement
## Related Issues
Closes #123
Related to #456
## Changes Made
- Added notification email service
- Implemented push notification support
- Created notification preferences UI
- Added unit tests for notification service
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing completed
- [ ] Tested on Chrome, Firefox, Safari
## Screenshots (if applicable)
[Add screenshots here]
## Checklist
- [ ] Code follows project style guidelines
- [ ] Self-review completed
- [ ] Comments added for complex code
- [ ] Documentation updated
- [ ] No new warnings introduced
- [ ] Tests added/updated
- [ ] All tests passing
Code Review Checklist
For Reviewers:
- Follows team conventions
- No unnecessary complexity
- Proper error handling
- Security considerations addressed
- Performance implications considered
- Tests are adequate
- Documentation updated
- No debugging code left behind
- Commit messages follow convention
Merging Strategies
Different strategies for different branches:
# For feature → develop: Squash and merge (clean history)
git checkout develop
git merge --squash feature/user-auth
git commit -m "feat: add user authentication system"
# For develop → staging: Merge commit (preserve feature commits)
git checkout staging
git merge --no-ff develop
# For staging → main: Merge commit (preserve all history)
git checkout main
git merge --no-ff staging
Why?
- Squash merge: One commit per feature in
develop. Clean history - Merge commit: Full history preserved for staging and production
Automating Quality Checks with Git Hooks
Git hooks catch bad code before it reaches the repository. They validate code quality, enforce commit standards, and prevent mistakes before review or CI.
What they prevent:
- Linting errors and failing tests
- Invalid commit message formats
- Hardcoded secrets or API keys
- Direct commits to protected branches
For detailed instructions on setting up Git hooks with Husky, integrating with CI/CD, and common hook patterns, see our dedicated guides:
Git Hooks for Automation: Catch Mistakes Before They Embarrass You → - Theory and patterns
Implementing Git Hooks with Husky: A Real-World Example → - Practical setup guide
The guides include:
- Pre-commit, commit-msg, and pre-push hook examples
- Husky setup for team-wide hook sharing
- Real-world implementation in an Astro project
- Common patterns (prevent commits to main, check for secrets)
- Troubleshooting and CI/CD integration
5 minutes to set up. Saves hours of debugging.
For CI/CD integration examples (including multi-environment deployments), see the Git Hooks automation guide.
Team Workflow Best Practices
Daily Development Flow
Morning:
# Start your day by syncing
git checkout develop
git pull origin develop
During Development:
# Commit often with good messages
git add .
git commit -m "feat(feature): add specific functionality"
# Push regularly to backup and share progress
git push origin feature/your-feature
Before Lunch/End of Day:
# Sync with develop to avoid conflicts later
git checkout develop
git pull origin develop
git checkout feature/your-feature
git merge develop
Communication Guidelines
Notify your team:
- Before merging to
develop,staging, ormain - When deploying hotfixes
- When blocked
Channels:
- Slack/Teams: Quick updates, PR review requests
- Daily standups: Current branch, blockers
- PR comments: Code-specific discussions
- Documentation: Architectural decisions
Troubleshooting Common Issues
Issue 1: “I committed to wrong branch”
# You're on develop but should be on feature branch
# 1. Create feature branch from current state
git checkout -b feature/my-feature
# 2. Reset develop to remote state
git checkout develop
git reset --hard origin/develop
# 3. Your commits are now on feature branch
git checkout feature/my-feature
Issue 2: “I need to undo last commit”
# Undo commit but keep changes
git reset --soft HEAD~1
# Undo commit and discard changes
git reset --hard HEAD~1
# Undo commit that was already pushed (creates new commit)
git revert HEAD
Issue 3: “My branch is behind main”
# Update your branch with latest main
git checkout feature/my-feature
git fetch origin
git merge origin/main
# Or use rebase for cleaner history
git rebase origin/main
Issue 4: “Accidentally pushed to protected branch”
# If push was rejected - good! Branch protection worked
# If push succeeded - contact admin immediately
# Admin can:
# 1. Revert the commit
git revert <commit-hash>
git push origin main
# 2. Or reset branch (if no one pulled yet)
git reset --hard <commit-before-mistake>
git push --force origin main # Only admin can do this
Metrics and Monitoring
Track these to spot workflow issues:
Git Health Metrics
- Average PR merge time: < 24 hours
- Branch lifetime: Feature branches < 3 days
- Merge conflicts: < 10% of merges
- Failed builds: < 5% of pushes
- Hotfix frequency: < 1 per week
Tools for Monitoring
# Check branch age
git for-each-ref --sort=committerdate refs/heads/ \
--format='%(committerdate:short) %(refname:short)'
# Count commits per author
git shortlog -sn --all
# Check merge frequency
git log --merges --oneline | wc -l
Onboarding New Team Members
Day 1 Checklist
- Clone repository
- Install git hooks
- Read this guide
- Configure git username and email
- Set up commit message template
- Add SSH key to Git host
- Join team chat channels
- Review recent PRs
Practice Exercise
Give new members a safe task:
# 1. Create practice branch
git checkout -b feature/onboarding-<name>
# 2. Make a small change
# Edit README.md - add your name to contributors
# 3. Commit with proper format
git commit -m "docs(readme): add <name> to contributors"
# 4. Push and create PR
git push origin feature/onboarding-<name>
# 5. Get it reviewed and merged
Summary Cheat Sheet
Quick Commands
# Start new feature
git checkout develop && git pull && git checkout -b feature/name
# Update feature with develop
git checkout develop && git pull && git checkout - && git merge develop
# Finish feature
git push origin feature/name # Then create PR
# Quick status
git status && git log --oneline -5
# Clean up merged branches
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
Branch Lifecycle
How branches flow from creation to deletion:
Branch lifespan by type:
| Branch Type | Created When | Deleted When | Typical Lifespan |
|---|---|---|---|
feature/* | Starting new work | After merged to develop | 1-7 days |
bugfix/* | Fixing non-critical bug | After merged to develop | 1-3 days |
hotfix/* | Production emergency | After merged to main | 2-4 hours |
develop | Project start | Never (permanent) | Entire project |
staging | Project start | Never (permanent) | Entire project |
main | Project start | Never (permanent) | Entire project |
Key points:
- Feature branches are temporary. Delete after merging
- Over 1 week old? Expect painful reviews
- Over 2 weeks? Break the feature down
Protection Summary
| Branch | Protection | Required Approvals | Auto-Deploy |
|---|---|---|---|
main | Maximum | 2 reviewers | Manual only |
staging | High | 1 reviewer | Auto to staging |
develop | Medium | 1 reviewer | Auto to dev |
feature/* | None | - | Optional preview |
The Bottom Line
This workflow gives you:
- No Friday disasters - Branch protection catches mistakes before prod
- Code reviews that happen - Required, not optional
- New devs who aren’t lost - Clear rules from day one
- Confident deployments - Staging caught the bugs already
Adapt to your team size. Team of 3? Skip some ceremony. Growing to 10? Add guardrails. The point is structure so nobody nukes production.
Protect main this week. Add the rest as you go.
Next Steps: Implement This Today
A 3-week action plan:
Day 1 - Branch Protection (30 minutes)
- Protect
mainwith 2 required approvals - Protect
staginganddevelopwith 1 required approval - Enable status checks (CI/CD must pass)
Day 2 - Documentation (1 hour)
- Add
GIT_WORKFLOW.mdto your repo (template below) - Share this guide with your team
- Schedule a 30-minute team walkthrough
Day 3 - Git Hooks (1 hour)
- Set up Husky and commitlint
- Configure pre-commit linting
- Test with a dummy commit
- Each team member practices with a feature branch
- At least one PR per person
- Refine based on feedback
- Address questions in standup
- Move all active work to the new workflow
- Monitor merge conflicts (should decrease)
- Measure PR review times
- Celebrate wins, learn from issues
Check the related guides or drop a comment below.
Additional Resources
- Conventional Commits
- Semantic Versioning
- Git Flow Original Paper
- GitHub Flow
- GitLab Flow
- Atlassian Git Tutorials
Appendix: Team Agreement Template
Create a GIT_WORKFLOW.md file in your repository:
# Our Git Workflow Agreement
## Branches We Use
- main (production)
- staging (pre-production)
- develop (integration)
- feature/\* (features)
- hotfix/\* (emergency fixes)
## Rules We Follow
1. Never commit directly to main, staging, or develop
2. Always create PR for code review
3. Delete branches after merging
4. Write meaningful commit messages
5. Keep feature branches short-lived (<3 days)
6. Sync with develop daily
7. Test before pushing
8. Tag all production releases
## Code Review Standards
- Response time: < 24 hours
- Be constructive and specific
- Approve only if you'd deploy it
- Block if security/performance issues
## Emergency Protocol
1. Hotfix branches from main
2. Notify team in #urgent channel
3. Fast-track review
4. Deploy immediately after testing
5. Create incident report
Signed by team: [Names and dates]
Protect main first. Add conventions as your team gets comfortable.