# Write a commit message and PR description from a diff

> Turn a raw diff into a Conventional Commits message and a structured PR description, with questions for anything the diff doesn't explain.

- **Author:** [Minh Nguyen (@minh_nguyen)](https://promptabide.com/minh_nguyen)
- **Tested on:** Claude · Opus 5.5
- **You fill in:** `diff`, `context`
- **Published:** 2026-07-28
- **Updated:** 2026-09-24
- **Tags:** `coding`, `code-review`, `writing`, `productivity`
- **Keywords:** generate commit message from git diff, write pull request description with ai, conventional commits message generator prompt, pr description template for reviewers, ai git commit message prompt
- **Views:** 815
- **Likes:** 10

**Best for:** Developers who want clean commit history and reviewable PRs without spending ten minutes writing them by hand.

## Prompt

```
Write a commit message and a pull request description for this diff.

Diff:
{{diff}}

Ticket and context: {{context}}

Commit message:
- Conventional Commits format. Subject 72 characters or fewer, imperative mood.
- Body wrapped at 72 characters, explaining why the change was made and any behavior change a caller would notice. Not a list of edited lines.
- Footer with the ticket reference.

PR description, with these headings:
- Summary (2–3 sentences)
- Changes (bullets grouped by area)
- How to test (numbered steps a reviewer can follow)
- Risk and rollback
- Questions for the author

Rules:
- Describe only what the diff shows. If the diff does something the context doesn't explain (a removed check, a deleted timeout, a changed default), don't invent a reason. Put it under "Questions for the author".
- No filler openers like "This PR aims to".
```

## Variables

- `{{diff}}` — The output of git diff (staged or against main) (e.g. A diff adding retries to a webhook sender)
- `{{context}}` — Ticket number and why the change was made (e.g. PAY-412: merchants miss webhooks during their deploys)

## Example input

````
context: PAY-412. Merchants report missing order.paid webhooks when their servers return brief 502s during deploys.
diff:
```diff
--- a/src/webhooks/send.ts
+++ b/src/webhooks/send.ts
@@ -1,18 +1,33 @@
 import { fetch } from "undici"
+import { setTimeout as sleep } from "node:timers/promises"
+
+const RETRYABLE = new Set([408, 429, 500, 502, 503, 504])
+const MAX_ATTEMPTS = 4

 export async function sendWebhook(url: string, payload: unknown, secret: string) {
   const body = JSON.stringify(payload)
   const signature = sign(body, secret)
-  const res = await fetch(url, {
-    method: "POST",
-    headers: { "content-type": "application/json", "x-signature": signature },
-    body,
-    signal: AbortSignal.timeout(5000),
-  })
-  if (!res.ok) throw new Error(`Webhook failed: ${res.status}`)
+  for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
+    const res = await fetch(url, {
+      method: "POST",
+      headers: { "content-type": "application/json", "x-signature": signature },
+      body,
+    })
+    if (res.ok) return
+    if (!RETRYABLE.has(res.status) || attempt === MAX_ATTEMPTS) {
+      throw new Error(`Webhook failed after ${attempt} attempt(s): ${res.status}`)
+    }
+    await sleep(2 ** attempt * 250)
+  }
 }
```
````

## Output

*Produced by Claude · Opus 5.5.*

````
**Commit message**
```
fix(webhooks): retry transient failures with exponential backoff

Merchants lose order.paid events when their endpoint returns a brief
502 during a deploy, because sendWebhook gave up after one attempt.

sendWebhook now makes up to 4 attempts for 408, 429 and 5xx gateway
responses, waiting 500 ms, 1 s and 2 s between them. Other 4xx
responses still fail immediately. The error message now includes the
attempt count.

Refs: PAY-412
```

**PR description**

**Summary**
Webhook delivery now retries transient HTTP failures up to 4 times with exponential backoff, so a merchant's short deploy window no longer drops `order.paid` events. Non-retryable responses fail on the first attempt, as before.

**Changes**
- *Delivery (`src/webhooks/send.ts`)*
  - Retry loop with `MAX_ATTEMPTS = 4` and backoff of `2^attempt × 250 ms` (500, 1000, 2000 ms).
  - Retryable statuses: 408, 429, 500, 502, 503, 504.
  - Error message reports the number of attempts.
  - The 5-second request timeout (`AbortSignal.timeout(5000)`) is removed.

**How to test**
1. Point a test merchant's webhook URL at a local server that returns 502 twice, then 200.
2. Trigger an `order.paid` event.
3. Confirm the server logs three requests roughly 0.5 s and 1 s apart, and that no error is raised.
4. Change the server to always return 400 and confirm exactly one request followed by an error.

**Risk and rollback**
Delivery for a failing endpoint can now take about 3.5 s longer before erroring. Receivers may get the same event more than once if a 5xx happened after they processed it. Roll back by reverting this commit. No data migration.

**Questions for the author**
1. **The request timeout was removed.** Was that intentional? Without it, one hung merchant endpoint can block this call indefinitely, on every attempt.
2. Network errors (DNS failure, connection reset) make `fetch` throw, and those aren't retried. Only HTTP statuses are. Is that deliberate?
3. For 429, should we honor the `Retry-After` header instead of the fixed backoff?
4. Do payloads carry an event ID so receivers can de-duplicate retried deliveries?
````

## Why it works

**"Explain why, not what"** in the commit body gives you a message that's still useful in `git blame` two years later. The standout rule is **"don't invent a reason, put it under Questions for the author"**. Left alone, models write confident explanations for every line, including the removed timeout here, which was probably an accident. Turning unexplained changes into questions makes the PR description a review aid. **Numbered test steps** that a reviewer can actually follow beat "tested locally".

## When not to use it

For huge diffs (thousands of lines, generated files, lockfiles), trim to the meaningful files first, or the description turns into a list of files. If your team uses a different commit convention or a PR template, swap those into the prompt. Don't paste diffs containing secrets or customer data into a chat tool your company hasn't approved.

---

Canonical HTML: https://promptabide.com/bides/commit-message-and-pr-description-from-diff
Agent guide: https://promptabide.com/llms.txt · https://promptabide.com/agent-instructions.md
Sitemap: https://promptabide.com/sitemap.xml
