CodeRaptor
Back to Guides
Developer Guide

Git Best Practices for Teams

Master Git workflows, branching strategies, and collaboration patterns that scale from small teams to large engineering organizations.

15 min read
Last updated: March 2025

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 login
fix(api): handle null response in user profile endpoint
docs(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

fixed bug
updated files
WIP
asdf

Good Examples

fix: prevent crash on null user input
feat: add search filter to dashboard
refactor: extract validation logic
perf: optimize database queries

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 -p to 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:

  1. Create a branch from main
  2. Add commits with your changes
  3. Open a pull request
  4. Discuss and review code
  5. Merge to main
  6. 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.

Preserves full history
Easy to revert features
Messy history graph

Squash and Merge

Combines all commits into one on merge.

Clean linear history
One commit per feature
Loses individual commits

Rebase and Merge

Replays commits on top of main branch.

Clean linear history
Preserves commits
Rewrites commit history

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