Chapter 23Lesson 04~155 minutes

Patch-Based and Email Workflows: format-patch, am, apply, and Maintainer Flows: Diagnostics, Failure Modes, Security, and Performance

Diagnose wrong-base, path-prefix, whitespace, stateful git-am conflict, duplicate-patch, signoff/authentication, and secret-exposure failures without destroying local or submission evidence.

Diagnosticsam recoveryDuplicate detectionSecret safety

Learning objectives

  • Preserve original patch and repository evidence before retrying.
  • Diagnose wrong-base and path-prefix application failures.
  • Resolve or abort git-am sessions using their documented state machine.
  • Detect equivalent patches and distinguish signoff from authentication.
  • Prevent credentials or confidential source from leaking through patch/mail transport.

1. Diagnostic sequence — preserve the artifact before “fixing” it

  1. Preserve: original patch/mailbox bytes, current branch tip, ORIG_HEAD if am is active, status/index state, Git version/config, and expected base.
  2. Inspect: patch headers, paths, base/context, whitespace, current history, and whether an am session is already active.
  3. Classify: wrong base, path stripping, whitespace/EOL, three-way conflict, duplicate, metadata/policy, or transport/security issue.
  4. Choose the least destructive correction: apply to correct base, reroll, resolve then continue, or abort.
  5. Verify: history shape, author/message/trailers, tests, and exact patch-series version.

2. Capture evidence before retrying

git status --short --branch
git log --graph --decorate --oneline --all --max-count=30
git rev-parse HEAD
git rev-parse --verify ORIG_HEAD 2>/dev/null || true
git am --show-current-patch=diff 2>/dev/null || true
git config --list --show-origin --show-scope

If no am session is active, --show-current-patch is expected to fail. Do not treat that as repository corruption.

3. Failure mode — patch applies to the wrong historical base

A maintainer receives a patch whose context expects:

mode=baseline
retries=2

but the current branch already changed it to:

mode=production
retries=5
git apply --check incoming.diff

Typical interpretation: “patch does not apply” means context/path does not match the current tree. First identify the intended base from the contributor's cover letter/history rather than adding whitespace-ignore flags until the command succeeds. The safest correction may be switching to the documented base or requesting a reroll.

4. Intentionally broken example — wrong path stripping with -p0

A normal Git diff uses paths such as a/src/app.c and b/src/app.c. Git apply's default -p1 removes the first component. The operator instead runs:

git apply --check -p0 incoming.diff

Expected error pattern: Git cannot find the expected a/... path or reports that the patch does not apply. Diagnose the patch header:

sed -n '1,35p' incoming.diff
git apply --check incoming.diff

The repair is to use the path-prefix rule that matches the artifact, not to rename repository files to fit an incorrect -p value.

5. Failure mode — whitespace policy rejects the submitted bytes

git apply --check --whitespace=error incoming.diff

If new lines contain whitespace errors as defined by core.whitespace, an error policy refuses the patch. Prefer asking the contributor to fix/reroll source changes when exact review provenance matters. --whitespace=fix changes the imported bytes and therefore needs explicit policy/validation.

6. Failure mode — git am --3way stops on a real integration conflict

git am --3way incoming/v2-0001-policy.patch || true
git status --short
git ls-files -u
git am --show-current-patch=diff
git rev-parse ORIG_HEAD

When original blob IDs are present and available, three-way fallback can turn a textual apply failure into an ordinary conflict. The am session has not completed; inspect base/ours/theirs semantics just as in Chapter 20.

# Resolve the file deliberately, then:
git add path/to/conflicted-file
run-project-tests
git am --continue

--continue creates the commit using author/message metadata extracted from the mailbox and the resolved index.

7. If the series/base is wrong, abort rather than forcing the current patch through

git am --abort
git status --short --branch
git rev-parse HEAD

Current Git documents --abort as restoring the original branch and the files involved in the am operation to their pre-am state. This is the correct restart path; destructive reset/clean commands are unnecessary here.

8. am --quit is intentionally different from abort

--quit stops the am machinery while leaving HEAD and index untouched. That is useful only when an experienced operator intentionally wants to keep the partially handled state. Beginners should not treat quit and abort as synonyms.

9. Failure mode — an equivalent patch is already present

Reapplying a patch can fail, become empty, or produce confusing three-way behavior depending on history. Detect equivalence before mutation:

git show existing-commit | git patch-id --stable
git patch-id --stable < incoming.patch

If the stable patch IDs match, the content change is already represented. Inspect commit messages/trailers before deciding whether any metadata follow-up is still needed. Contributors can also use format-patch --ignore-if-in-upstream where its range semantics fit.

10. Failure mode — “it has Signed-off-by, therefore it is authenticated”

This conclusion is false. Signoff is a text trailer with project-defined meaning. Cryptographic commit/tag signature verification is a separate trust mechanism, and authorization is a separate server/team policy. A malicious person can type another person's name into a trailer.

11. Failure mode — patch/email artifacts expose credentials or confidential source

A patch file contains the changed lines in portable plain text. If a commit introduces an API key, private key, internal hostname, or confidential file, exporting the patch reproduces that content. Scan/review the generated files before any external transport.

git diff --check trunk..topic
git grep -n 'FAKE_SECRET_MARKER' topic
grep -R -n 'FAKE_SECRET_MARKER' outgoing-patches/
Never use real credentials in labs. If a real secret has already escaped, revoke/rotate it first; deleting an email or rerolling a patch does not invalidate the exposed credential.

12. Failure mode — SMTP credentials are written into reusable config/logs

Current git send-email supports sendemail.smtpPass, but also documents that when a username exists and no password was supplied, Git's credential subsystem can obtain one. Do not normalize storing plaintext SMTP passwords in project config or examples. Debug output and shell history also deserve secret review.

13. Commit messages can accidentally resemble patch delimiters

Current git am documentation warns that unindented diff-looking text in a commit message can be interpreted as the beginning of the patch. If a commit message needs to quote a diff, indent it or format it so mail parsing cannot confuse commentary with the actual patch section.

14. Performance relevance — keep series reviewable instead of optimizing email count blindly

Very large series cost review time, mailbox parsing, patch application, and tests. Splitting a logical topic into coherent patches can improve bisectability/review, but thousands of micro-patches can be operationally expensive. Measure maintainer throughput and project conventions; do not squash everything merely to reduce file count.

15. Red-zone operations are not normal patch troubleshooting

Do not respond to an am/apply failure with hard reset, broad clean, forced shared-ref updates, reflog expiry, object pruning, or history rewrite. Preserve the patch and repository evidence; use git am --abort, a disposable integration branch, or a corrected/rerolled artifact.

16. Symptom → likely cause → safe next action

Symptom Likely layer Next action
git apply --check fails everywhere wrong base/context/path inspect base and patch headers; do not mutate
-p0 cannot find a/... path stripping use correct/default prefix level
am stopped with unmerged index stages three-way conflict inspect current patch, resolve/test/add, continue—or abort
incoming change appears already present duplicate/equivalent patch compare patch IDs/history before applying
patch files contain a credential secret exposure stop transport, rotate/revoke real credential, then remediate artifacts/history

17. Knowledge check

Question 1. Why is changing -p a better first repair than renaming files when a Git diff has a/ and b/ prefixes?

Question 2. What should happen before git am --continue?

Question 3. When should you choose git am --abort?

Question 4. Why is Signed-off-by not authentication?

Question 5. What is the primary response to a real credential leaked in a patch/email?

18. Summary

Patch troubleshooting is evidence-driven: preserve the original artifact, identify base/path/whitespace/session/duplicate/security layers, then choose check, reroll, resolve/continue, or abort. Patch transport does not weaken the security rules learned for Git history—portable artifacts can leak just as effectively as commits.

Next

Checkpoint the contributor-to-maintainer lifecycle

Lesson 5 exports v1, forces and resolves an am conflict in a maintainer clone, verifies metadata, creates v2, compares with range-diff, and produces a maintainer handoff checklist.

Authoritative references

 git-am
 git-apply
 git-format-patch
 git-patch-id
 git-send-email

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.