DEV Community

Rizwan Saleem
Rizwan Saleem

Posted on

How to write good commit messages and pull requests: a team guide

How to write good commit messages and pull requests: a team guide

Commit messages and pull requests that teams love

  • Conventional commits format
  • Writing descriptive commit bodies linking commits to issues
  • Squash vs merge commit strategies
  • Crafting PR descriptions with context, screenshots, testing notes
  • Review checklist making PRs easier to review
  • Real examples

Conventional commits format

  • Purpose: standardize how you describe changes so tooling and humans can quickly understand history.
  • Structure: type(scope?): subject
  • Types you’ll use most:
    • feat: a new feature
    • fix: a bug fix
    • docs: documentation only changes
    • style: formatting, missing semicolons, etc. No code logic
    • refactor: code changes that neither fix a bug nor add a feature
    • test: adding or updating tests
    • chore: maintenance, build tooling, or dependencies
  • Example: feat(auth): add login with OAuth2 flow
  • Commit bodies: explain what and why, not just what changed
    • Use three sections: Problem, Solution, Next steps
    • Include any important decisions, trade-offs, and side effects
  • Linking issues: reference issues with #NUMBER and, where supported, close them with keywords like “Closes #123” in the body

Descriptive commit bodies and linking to issues

  • Why: you’ll thank the future you when tracing why a change happened.
  • Anatomy:
    • Short, imperative subject line (max ~50 characters)
    • Blank line
    • Body: motivation, approach, alternatives considered, and impact
    • Footer: references to issues or breaking changes
  • Example:
    • Subject: fix(auth): gracefully handle missing refresh token
    • Body:
    • When the refresh token is missing, the user would see a 500 error.
    • Now we return a 401 with a clear error message and log the incident.
    • Previously we attempted a token refresh which caused obscure failures.
    • Footer: Closes #245, Refs #310

Squash vs merge commit strategies

  • Squash and merge
    • Pros: a clean, linear history; single commit per PR
    • Cons: loses individual commit history; harder to see incremental work
    • Best for: small, cohesive PRs; teams wanting readable main branch history
  • Merge commit (no-fast-forward)
    • Pros: preserves complete history; context from each commit, useful for debugging
    • Cons: history can become noisy with many small commits
    • Best for: large PRs with meaningful, incremental changes
  • Rebase and merge
    • Pros: linear history with individual commits reapplied on top
    • Cons: rewriting history; potential conflicts if branches diverge
    • Best for: teams that prefer a clean, linear history but want to preserve original commits
  • Practical guidance
    • For feature work: use squash and merge to keep main concise.
    • For long-running features or fixes requiring detailed history: use merge commits or rebase and merge.
    • Align with your repo’s policy and tooling (e.g., CI, changelog generators).

Crafting PR descriptions with context, screenshots, testing notes

  • Purpose: give reviewers enough context to understand the change without digging through code.
  • Structure:
    • Title: summarize the change (imperative, present tense)
    • Why this change? (motivation and problem)
    • What changed? (high-level overview, not line-by-line)
    • How to test
    • Screenshots or recordings (if UI)
    • Known issues and limitations
    • Related issues (IDs)
    • Impact and rollout plan
  • Testing notes
    • Prerequisites: environment, data, feature flags
    • Steps to reproduce: exact actions, expected vs actual results
    • Automated tests: what tests passed/failed, any new tests added
    • Manual testing checklist: smoketests, edge cases
  • Screenshots
    • Include before/after visuals if UI changes
    • Annotate with arrows or captions for clarity
  • Example PR description
    • Title: feat(dashboard): add KPI widgets and drill-down capabilities
    • Why: provide at-a-glance metrics to users
    • What: adds three KPI widgets, drill-down on click to detailed view, responsive layout
    • How to test:
    • Open dashboard, ensure KPI cards render
    • Click KPI to see detail pane
    • Resize to mobile and verify layout
    • Screenshots: [Attach before/after images]
    • Tests: unit tests for widget data bindings; integration test for drill-down
    • Related issues: Closes #1024

Review checklist to speed up PRs

  • For authors
    • [ ] Title is concise and imperative
    • [ ] Description includes why, what, and testing steps
    • [ ] Screenshots or videos included for UI changes
    • [ ] Linked to related issues and breaking changes, if any
    • [ ] Code changes follow conventions and have clear commit messages
    • [ ] Tests updated or added; CI passing
  • For reviewers
    • [ ] Verify the problem statement matches the change
    • [ ] Confirm tests cover critical paths
    • [ ] Check for potential edge cases and performance implications
    • [ ] Ensure no sensitive data is exposed in diffs or logs
    • [ ] Provide actionable feedback with references to lines or components

Real-world example set

  • Commit example 1
    • Type: fix
    • Scope: notification
    • Subject: fix(notification): avoid null pointer when user unsubscribes
    • Body:
    • Problem: unsubscribing with active notification preferences could trigger a NPE.
    • Solution: guard null fields and return a safe default.
    • Impact: this won’t affect normal flows; reduces crash reports.
    • Footer: Closes #512
  • Commit example 2
    • Type: feat
    • Scope: analytics
    • Subject: feat(analytics): add weekly digest email
    • Body:
    • Introduces a new digest endpoint that aggregates weekly activity and sends email.
    • Uses existing email template and scheduling system.
    • Footer: Related to #789

Putting it into practice: a mini workflow

  • Before you start a PR
    • Create a focused branch named feature/short-descr
    • Write a clear, conventional-commit-friendly history locally
    • Run tests and ensure green
  • When opening a PR
    • Use a concise title, reference related issues
    • Add a descriptive body with testing steps and visuals
    • Attach screenshots if UI changes
    • Choose squash and merge or merge commit based on policy
  • During review
    • Respond with direct references to reviewer comments
    • Update the PR description if you adjust scope or tests
    • Re-run CI and attach results if changes were made

Would you like me to tailor this into a ready-to-publish guide for your team, including a customizable PR template and a small example repository snippet? If yes, tell me your repo’s preferred commit types and your squash/merge policy.

-

Rizwan Saleem | https://rizwansaleem.co

Top comments (0)