Skip to content
ExponaBLOG
GIT & GITHUB FOR PROFESSIONAL DEVELOPERS · DAY 032 / 100

Writing a great pull request description in Git & GitHub

Help reviewers help you.

Expona Admin7 min read

You've just pushed your feature branch and opened a pull request. Within minutes, your teammate asks for clarification. Two hours later, the reviewer requests a change that takes you back to square one. The difference between a smooth code review and a frustrating one often comes down to one thing: the quality of your pull request description. Writing a great pull request description in Git & GitHub isn't about being verbose—it's about being clear, concise, and empathetic to the person who has to review your work.

Why pull request descriptions matter

A pull request description is your chance to communicate directly with reviewers before they dive into the code. It's the difference between a reviewer who understands your context and one who's reverse-engineering your intent from diff hunks. When you're working in a team—especially across time zones or in asynchronous workflows—a strong description prevents miscommunication that can delay merging by hours or even days.

Think of it this way: code reviews are about validating logic, catching bugs, and maintaining standards. But reviewers can't do their job effectively if they don't understand what you were trying to solve. Your description is the bridge between your problem statement and your solution.

What changed and why

This is the core of your pull request description. Start with a clear summary of what you changed, then explain the business or technical reason behind it. This isn't about listing every file you touched—it's about framing the change in a way that makes sense to someone unfamiliar with your task.

Good approach: Start with a one-liner that summarizes the change, then add a paragraph explaining the context.

bash
Add exponential backoff to payment retry logic

Users are experiencing intermittent payment failures when our payment provider experiences brief outages. Currently, we retry immediately 3 times, which exhausts our API rate limit during high-traffic periods. This change implements exponential backoff with jitter to spread retries over 2 minutes, giving the provider time to recover and reducing cascading failures.

Related to issue #4521

Notice how this description answers several implicit questions: What's the problem? Why is it a problem now? How does this fix it? And how does it relate to existing work?

When you're working on a feature that refactors internal code without user-facing changes, be especially explicit about why the refactoring matters:

bash
Refactor order status state machine to use explicit enum

The order processing pipeline currently uses string constants scattered across three modules, making it hard to track valid state transitions and add new statuses safely. This refactor centralizes state definitions in a single enum and replaces all string comparisons with type-safe enum checks. This will make it easier to add status validation in the future and reduce the risk of typos causing silent failures.

Without this context, a reviewer might see a refactoring PR and wonder if it's just busywork. With it, they understand the architectural benefit and can evaluate whether the change actually delivers on that promise.

How to test it

Testing instructions are the practical heart of a good pull request description. Don't assume reviewers will know how to exercise your changes. Walk them through the exact steps to see the behavior you've implemented.

For a backend change, include the curl commands or test runner instructions they need:

bash
Testing
-------

1. Run the test suite:
   npm run test -- src/payment/retry.test.ts

2. Manual testing with docker-compose:
   docker-compose up
   npm run dev

   Then trigger a payment retry:
   curl -X POST http://localhost:3000/api/internal/debug/payment-retry \
     -H "Content-Type: application/json" \
     -d '{"orderId": "order_12345"}'

   Check the logs to verify exponential backoff timing:
   docker-compose logs -f api | grep "retry_attempt"

3. Watch for successful payment after retry #2 (should take ~30s).

For a frontend change, include specifics about which component changed and how to navigate to it in development:

bash
Testing
-------

1. Run the app: npm run dev
2. Navigate to the checkout page
3. Try entering an expired credit card (e.g., 4000000000000069)
4. Verify the error message appears below the card input field
5. Confirm the error clears when you change the card number

If your change touches configuration or requires environment variables, mention that too. The clearer you are about setup, the faster reviewers can verify your work.

Screenshots for UI changes

If you've modified anything visual, include before-and-after screenshots. This gives reviewers instant confidence that the change looks right without having to run the code locally. On GitHub, you can paste images directly into the PR description.

Use a simple format:

bash
Screenshots
-----------

Before:
[Link or embedded image of old UI]

After:
[Link or embedded image of new UI]

Mobile responsiveness tested at 375px and 768px breakpoints.

For subtle changes—spacing, colors, typography—consider adding a Figma link or mentioning the design system token you're using. This prevents reviewers from wondering whether a change is intentional or accidental.

If the change affects different states or user flows, show multiple states:

bash
Loading state: [screenshot]
Success state: [screenshot]
Error state: [screenshot]

Risks and rollback plan

This section shows you've thought through failure modes. It's especially important for changes that affect critical paths like payments, authentication, or data integrity.

Be specific about what could go wrong and how you'd fix it:

bash
Risks and Rollback
------------------

Risk: If exponential backoff timing is too aggressive, we could miss payment windows and users might see "payment processing" for too long.

Mitigation: Added monitoring on retry_attempt_duration histogram to track actual timing. If P95 latency exceeds 3 minutes, we'd reduce max backoff from 60s to 30s.

Rollback: Revert the three commits in this PR and redeploy. The change is additive (doesn't modify existing payment records) so no data migration is needed. Payments in-flight will fall back to immediate retries.

For database changes, be extra detailed:

bash
Risk: Adding a NOT NULL constraint to the users.phone_number column could fail if we have existing null values.

Mitigation: Pre-deployment check confirms all users have phone_number populated (or have a default). If not, we backfill with a placeholder and alert the support team.

Rollback: Drop the constraint and redeploy. The migration includes a down step for this exact scenario.

Even if you think the risk is low, acknowledging it shows you've done the due diligence reviewers expect from senior engineers.

Common mistakes

Being too brief: "Fixed the bug" or "Updated checkout" leaves reviewers guessing. Use those words, but add the story behind them.

Assuming context: What's obvious to you isn't obvious to someone context-switching from another task. Spell out acronyms, link to related tickets, and explain jargon.

Mixing multiple concerns: If your PR touches payment logic, then refactors unrelated config code, split them. Reviewers can't confidently approve a grab bag of changes. Each PR should have a single, clear reason to exist.

Forgetting to link issues: Always reference the ticket or issue number. Use "Fixes #1234" or "Related to #1234" so GitHub automatically links them.

No testing instructions: Saying "I tested this locally" isn't enough. Other developers shouldn't have to reverse-engineer how to verify your change.

Hiding breaking changes: If your PR changes an API contract or requires a config update, call it out prominently in the description. Don't bury it in a commit message.

Key takeaways

  • A pull request description is your communication tool—use it to guide the reviewer through what changed and why it matters.
  • Start with a one-liner, then provide context, testing steps, and visual proof for UI changes.
  • Include explicit testing instructions so reviewers don't have to guess how to verify your work.
  • Screenshot UI changes and include before-and-after comparisons.
  • Think through failure modes and explain how you'd rollback if something breaks.
  • Link to related issues and tickets so the full story is traceable.
  • Keep each PR focused on one concern—if it touches multiple unrelated things, split it.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles