How no-mistakes Handles Fork Routing for GitHub PRs: A Technical Deep Dive
no-mistakes routes branch pushes to a contributor's fork while always targeting the upstream repository for pull request creation, using a dual-URL configuration stored in the repos table.
The open-source tool no-mistakes (available at kunchenguid/no-mistakes) implements a sophisticated fork routing system that separates where code is pushed from where pull requests are opened. This architecture allows contributors to work on forks without write access to the parent repository while ensuring all GitHub PRs are created against the canonical upstream project.
Dual-URL Configuration for Fork Routing
The system maintains two distinct remote URLs for every repository entry in its database. The upstream_url field stores the canonical GitHub repository (the parent), while the optional fork_url field contains the contributor's personal fork address.
These values are persisted in the repos table and drive all subsequent routing decisions. When fork_url is populated, the tool assumes the contributor intends to push changes to their own fork rather than the upstream repository.
The PushURL Method: Routing Commits to the Correct Remote
The core routing logic resides in internal/db/repo.go within the PushURL() method. This function determines which remote receives branch updates by checking the presence of a configured fork:
// PushURL returns the remote URL that should receive branch updates.
func (r *Repo) PushURL() string {
if r == nil {
return ""
}
if strings.TrimSpace(r.ForkURL) != "" {
return r.ForkURL // fork takes precedence
}
return r.UpstreamURL // otherwise push to the parent
}
When the push step executes in internal/pipeline/steps/push.go, it invokes sctx.Repo.PushURL() to determine the destination for git push operations. This ensures that contributors without upstream write permissions can still publish branches to their own forks.
GitHub PR Creation: Always Targeting Upstream
For GitHub PR creation, no-mistakes employs a different routing strategy than it uses for pushes. The workflow enforces that the pull request target must always be the parent repository, regardless of whether a fork is configured.
The implementation in internal/pipeline/steps/host.go constructs the gh pr create command with the following behavior:
- The
--repoflag always points to the upstream repository (derived fromupstream_url) - When
fork_urlis present, the command adds--head <fork_owner>:<branch>to specify the fork as the PR head - The
fork_urlitself is never passed directly to theghcommand; only the fork owner name is extracted from the URL
This split-routing approach ensures that while branch updates land on the contributor's fork, the pull request itself is opened against the trusted upstream repository.
Security and Workflow Benefits
This dual-routing architecture provides critical security and convenience advantages:
- Permission isolation: Contributors can open PRs without requiring write access to the upstream default branch
- Trusted targets: Maintainers control the target branch configuration on the upstream repository, preventing accidental PRs against incorrect branches
- Clean history: Branch updates occur on the fork, keeping the upstream repository's branch list uncluttered
Summary
- no-mistakes stores two URLs per repository:
upstream_urlfor the parent repo andfork_urlfor contributor forks - The
PushURL()method ininternal/db/repo.goprioritizes the fork URL when determining where to push branches - Push operations in
internal/pipeline/steps/push.gouse the fork when available, enabling contributions without upstream write access - PR creation always targets the upstream repository via
--repo, using--head <fork_owner>:<branch>when a fork is configured - The
fork_urlis never used directly for PR creation; only the owner name is extracted ininternal/pipeline/steps/host.go
Frequently Asked Questions
What is fork routing in no-mistakes?
Fork routing is the system's mechanism for directing Git operations to different remotes based on context. It pushes code to a contributor's fork (when configured) while ensuring GitHub pull requests are always created against the upstream parent repository.
How does no-mistakes decide whether to push to a fork or upstream?
The decision occurs in the PushURL() method inside internal/db/repo.go. If the ForkURL field contains a non-empty string, that URL is returned and used for push operations. Otherwise, the method falls back to UpstreamURL.
Why doesn't no-mistakes use the fork URL directly when creating PRs?
The tool intentionally avoids passing the fork URL to gh pr create because GitHub CLI requires the --repo flag to specify the target repository for the PR (which must be the upstream), while the fork is referenced only as the head source via --head <owner>:<branch>. This maintains the security model where the upstream repository controls the merge target.
Which database fields control fork routing behavior?
The routing behavior is controlled by two columns in the repos table: upstream_url (the canonical parent repository) and fork_url (the optional contributor fork). The presence of a value in fork_url triggers fork-specific routing for pushes and modifies the PR creation command to include the fork owner prefix.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →