Git Best Practices for Teams
Master Git workflows, branching strategies, and collaboration patterns that scale from small teams to large engineering organizations.
Git is the backbone of modern software development, but using it effectively requires discipline and consistent practices. Whether you're a solo developer or part of a 100-person engineering team, following Git best practices makes your codebase easier to understand, your history cleaner, and your collaboration smoother.
This guide covers everything from commit messages to branching strategies, based on patterns used by successful engineering teams at companies like GitHub, GitLab, and Atlassian.
Writing Great Commit Messages
1. Use the Conventional Commits Format
Conventional Commits provide a standardized format that makes it easy to understand what a commit does at a glance and enables automated changelog generation.
Format:
<type>(<scope>): <subject> [optional body] [optional footer]
Common Types:
- •
feat:A new feature for the user - •
fix:A bug fix - •
docs:Documentation changes - •
refactor:Code change that neither fixes a bug nor adds a feature - •
test:Adding or updating tests - •
chore:Maintenance tasks, dependency updates - •
perf:Performance improvements
Examples:
feat(auth): add OAuth2 support for GitHub loginfix(api): handle null response in user profile endpointdocs(readme): update installation instructions for Node 18+2. Write Meaningful Subject Lines
The first line of your commit message should be clear, concise, and written in imperative mood (as if giving a command).
Bad Examples
Good Examples
3. Keep Commits Atomic and Focused
Each commit should represent a single logical change. Avoid mixing multiple unrelated changes in one commit.
- One commit = one purpose (bug fix, feature, refactor, etc.)
- If you use "and" in your commit message, it's probably too big
- Each commit should pass tests and not break the build
- Use
git add -pto stage parts of files selectively
Branching Strategies
Git Flow (Traditional)
Best for teams with scheduled releases and long-lived release branches. Common in enterprise environments.
Branch Structure:
- mainProduction-ready code, always deployable
- developIntegration branch for features
- feature/*New features (branch from develop)
- release/*Release preparation (branch from develop)
- hotfix/*Emergency fixes (branch from main)
When to use: Teams with scheduled releases, regulated industries, or when you need to support multiple versions in production.
GitHub Flow (Simplified)
Lightweight branching strategy perfect for continuous deployment and fast-moving teams.
Workflow:
- Create a branch from
main - Add commits with your changes
- Open a pull request
- Discuss and review code
- Merge to
main - Deploy immediately (or via CI/CD)
When to use: Continuous deployment, SaaS products, small to medium teams that ship frequently.
Trunk-Based Development (Modern)
Developers work in short-lived branches (or directly on main) and merge frequently. Requires strong CI/CD and feature flags.
Key Principles:
- Merge to main at least once per day
- Keep branches short-lived (max 2-3 days)
- Use feature flags for incomplete features
- Comprehensive automated testing required
When to use: High-velocity teams, microservices, companies practicing DevOps/SRE (Google, Facebook, Netflix).
Pull Request Best Practices
1. Keep PRs Small and Focused
Large PRs are hard to review and take longer to merge. Aim for PRs under 400 lines of code.
Pro tip: If your PR is getting large, break it into multiple smaller PRs with a clear dependency chain.
2. Write Descriptive PR Titles and Descriptions
Your PR description should answer: What changed? Why? How was it tested?
Example PR template:
## What changed - Added JWT authentication - Implemented refresh token rotation ## Why - Security requirement for compliance - Users complained about frequent logouts ## How tested - Added 15 unit tests - Manual testing in staging - Load tested with 10K users ## Screenshots [Attach if UI changed]
3. Self-Review Before Requesting Reviews
Go through your own diff line-by-line before hitting "Request Review." Catch obvious mistakes first.
- Remove console.log() and debug code
- Run linters and formatters locally
- Verify all tests pass
Merging Strategies
Merge Commit
Creates a merge commit that preserves complete history.
Squash and Merge
Combines all commits into one on merge.
Rebase and Merge
Replays commits on top of main branch.
Common Git Workflows
Starting a New Feature
# Update your local main branch git checkout main git pull origin main # Create and switch to a new feature branch git checkout -b feature/user-authentication # Work on your changes... git add . git commit -m "feat(auth): implement JWT authentication" # Push your branch to remote git push -u origin feature/user-authentication # Open a pull request on GitHub/GitLab
Keeping Your Branch Up to Date
# Option 1: Merge (preserves history) git checkout main git pull origin main git checkout feature/your-feature git merge main # Option 2: Rebase (cleaner history) git checkout main git pull origin main git checkout feature/your-feature git rebase main # If conflicts occur, resolve them, then: git add . git rebase --continue # Force push after rebase (only if needed) git push --force-with-lease
Fixing Mistakes
# Undo last commit (keep changes) git reset --soft HEAD~1 # Amend last commit message git commit --amend -m "New message" # Discard local changes git checkout -- filename.txt # Undo a merge git merge --abort # Undo a rebase git rebase --abort
Team Collaboration Guidelines
1. Never Push Directly to Main/Master
Always use pull requests, even for small changes. This ensures code review and maintains a clean history.
2. Don't Rewrite Public History
Avoid force pushing to shared branches. Only rebase or amend commits on your own feature branches.
3. Delete Merged Branches
Clean up merged branches to keep your repository organized. Most Git hosting platforms can do this automatically.
4. Use Branch Protection Rules
Enable branch protection on main to require:
- Pull request reviews before merging
- Status checks to pass (tests, linting)
- Up-to-date branches before merging
Security Best Practices
- Never commit secrets: Use environment variables or secret management tools (AWS Secrets Manager, HashiCorp Vault)
- Use .gitignore properly: Exclude .env files, credentials.json, API keys, and sensitive data
- Sign your commits: Use GPG signing to verify commit authenticity
- If you leaked a secret: Rotate it immediately—deleting the commit isn't enough (it's still in history)
Git Commands Quick Reference
Branch Management
git branch - List branches
git branch -d name - Delete branch
git checkout -b name - Create & switch
git switch name - Switch branch
Syncing
git fetch - Download changes
git pull - Fetch + merge
git push - Upload changes
git remote -v - List remotes
History
git log - View commits
git log --oneline - Compact view
git diff - Show changes
git blame file - Who changed what
Undoing Changes
git reset HEAD~1 - Undo commit
git revert hash - Revert commit
git stash - Save changes
git stash pop - Restore changes