Skip to content

Software companies

Rejected pull requests: why abandoned code changes are valuable

By SourceX Editorial · Updated

Short answer

Rejected pull requests are valuable because each one pairs a plausible code change with a reviewer's reason for turning it down, the kind of judgment coding agents need to learn. A closed, unmerged PR is worth keeping when its thread explains the rejection and points to what shipped instead; one closed silently by a stale bot adds little.

Key takeaways

  • A rejected pull request with a written reason is a negative example with its explanation attached.
  • Pairs of rejected and merged changes for the same issue are more useful than either one alone.
  • Not every closed, unmerged PR is a rejection; classify closures before counting them.
  • Abandoned branches are where secrets, debug code and customer test data tend to hide, so they need their own scan.

Why would anyone want code that never shipped?#

Code that never shipped is useful because the record of a reviewer rejecting it explains what a correct change must avoid. Coding agents are good at producing changes that look plausible; what they lack is an experienced reviewer's sense of why a plausible change is still wrong for this codebase.

A rejected pull request captures that judgment where it happened. The diff shows the attempt, the review comments name the problem, and the follow-up shows the accepted approach. For evaluation, the same record becomes a test: can a model spot the issue the human reviewer spotted?

Few teams think of this history as worth keeping. It sits in the code host as closed, unmerged pull requests, and it is easy to lose during cleanups and migrations.

Not every closed pull request is a rejection#

Closed pull requests fall into several types, and only some of them record a decision. Classifying them first keeps an inventory from padding its counts with noise and tells a buyer exactly what each slice contains.

The classification can usually be done from metadata: who closed the PR, whether reviews requested changes, whether a later PR references it, and whether a bot was involved.

Not every closed pull request is a rejection
Closure typeHow to recognize itValue to AI teams
Rejected with reasonsReview requested changes or explained a problem, then the PR was closedHigh
SupersededClosed with a link to a replacement PR that mergedHigh, especially as a pair
Reverted after mergeMerged, then undone by a revert PR with an explanationHigh: the failure surfaced after shipping
Exploratory draftDraft or spike label, closed after discussionModerate: shows options considered
DuplicateClosed with a reference to another PRLow
Abandoned by authorNo reviews, closed by a stale botLow
Automated dependency updateOpened and closed by a botUsually excluded

What makes a rejection reason useful?#

A rejection reason is useful when it names the specific problem and, ideally, points to the evidence. A comment such as not now or please rework tells a model nothing; a comment saying the change breaks retries because the handler is not idempotent, with a link to the failing test, tells it a great deal.

Reasons gain value when they connect to something outside the thread: the issue the PR was meant to fix, a design doc that set the rule being enforced, a CI run that failed, or the later PR that took the reviewer's advice. Those links turn a comment into a traceable decision. Tagging each rejection with a reason category also helps a buyer find the slices it needs.

  • Correctness: the change fails an edge case or breaks existing behavior.
  • Architecture: the fix sits in the wrong layer or bypasses an agreed pattern.
  • Performance: the change adds a slow query or an unbounded loop.
  • Security: the change exposes data, weakens validation or adds an unsafe dependency.
  • Product: the behavior conflicts with a product decision or falls outside scope.
  • Convention: the change ignores team standards for tests, naming or error handling.

Illustrative: one rejected pull request, start to finish#

Illustrative: a fictional shipment tracking software company receives a support ticket from a customer whose dashboard shows some deliveries twice. An engineer opens a Jira issue and, soon after, a pull request. The sequence below follows that work to the end.

Kept together, that thread is a complete lesson: a plausible fix, a precise reason it was wrong, the governing design rule and the correct change. If the first pull request is deleted, only the merged change survives, along with the false impression that the right answer was obvious from the start.

  • Pull request one filters duplicate delivery events out of the dashboard query.
  • A senior reviewer requests changes: the duplicates come from carrier webhooks retried on timeout, so API customers still receive them, and the fix belongs at ingestion.
  • The reviewer links the design doc that requires idempotency keys on all inbound webhooks.
  • The author closes pull request one with a comment pointing to the new approach.
  • Pull request two adds an idempotency key check to the webhook handler and a test that replays the same event twice.
  • Pull request two is approved and merged, ships in the next release, and support replies to the customer with the release note.

Where do rejected pull requests get lost?#

Rejected pull requests get lost in three common ways: branch cleanups, history rewrites and moves between code hosts. The pull request page and its comments usually stay on the host, but whether the diff and its commits survive a deleted branch, a force-push or a repository cleanup depends on the host and how it stores pull request references.

Migrations carry the bigger risk. Moving from one code host to another, or from a self-managed server to a cloud service, may carry merged history faithfully while leaving closed pull requests, review threads or deleted branches behind. Migration tools differ, so check what yours carries before the old host is retired, and take these steps first.

  • Export closed pull requests with their review comments and events, not only merged ones.
  • Preserve the commits behind each closed PR, for example by fetching the host's pull request references or archiving branch heads before branches are pruned.
  • Record the link between each closed PR, its issue and any replacement PR.
  • Store the export with the date taken and the host and version it came from.

What to check before including rejected changes#

Rejected changes need a closer check than merged code, because abandoned branches rarely went through the cleanup that a merge brings. Debug output, hard-coded credentials and real customer records used as quick test fixtures are more common in work that was never finished.

Secret scanning is the first pass. Gitleaks, an MIT-licensed scanner, looks for passwords, API keys and tokens in git repositories; its maintainer has since declared it feature complete, with future releases limited to security patches, so check the status of any scanner before standardizing on it. Any secret found should be rotated, not just removed from the export.

What to check before including rejected changes
CheckWhy it mattersTypical action
Secrets in abandoned commitsCredentials may still be liveScan every closed PR, rotate and remove
Customer data in test fixturesQuick fixes often copy real recordsReplace with synthetic values or exclude
Personal remarks in reviewsBlunt comments about named colleaguesPseudonymize names and drop personal remarks
Contractor and outside contributionsOwnership may sit with someone elseConfirm assignment terms with counsel
Open-source and vendored codeLicense terms travel with the codeExclude it or follow the license conditions
Security vulnerability threadsDetails could expose live systemsExclude, or hold until fixed and reviewed

How SourceX treats rejected changes in a code history package#

SourceX treats closed pull requests as decision records rather than leftovers. In the SourceX Enterprise Data Value Framework, human-generated signal and domain expertise are both value drivers, and a reviewer's written reason for turning down a change is both, so a package that keeps rejected and superseded PRs beside the merged ones usually tells a buyer more than merged code alone.

In the Supply step of the SourceX five-step transaction, the fit check asks only for metadata, such as which hosts and repositories exist and whether closed PRs and review threads are retained. Preparation then covers secrets, fixtures and names, and the SourceX Evidence Packet records which closure types were included and what was removed.

Frequently asked questions

Should we include pull requests closed by stale bots?

Usually not as a main record type. A stale-bot closure records that nobody acted, not that anyone decided. These PRs can be listed in the inventory for completeness, but a package should lead with closures that carry a human reason.

Does a rejected pull request need a linked issue?

It helps but is not essential. A clear review reason and a visible replacement PR can carry the lesson alone. A linked issue adds the original problem statement, which lets a buyer test whether a model can reach the right fix starting from the report.

Are reverted commits the same as rejected pull requests?

No. A revert means the change merged and later caused trouble, so it records a failure that review did not catch. Both are useful, but they teach different things and should be labeled separately in the manifest.

What about pull requests from former employees?

Employment agreements commonly assign work product to the company, but the terms vary, so confirm with counsel. Former employees' names should be pseudonymized like everyone else's, and their review comments kept where they carry useful reasons.

Can we license rejected pull requests without the merged code?

In principle, yes, but the value drops sharply, because a rejection is easiest to learn from next to the change that replaced it. If a repository cannot be included, its review threads and issue links may still be scoped as a smaller record family.

Sources

  • Gitleaks is an MIT-licensed tool for detecting secrets such as passwords, API keys and tokens in git repositories, files and stdin; on May 21, 2026, its README was updated to state that Gitleaks is feature complete and future releases will be security patches only. Source

Related resources

See if your company qualifies

A short company assessment. No data uploads are needed.

See if you qualify