How the Rebase Step in no-mistakes Fetches from the Authoritative Remote to Avoid Stale Refs
The RebaseStep always fetches origin/<defaultBranch> from the authoritative remote before rebasing, and conditionally refreshes the branch-specific remote-tracking ref only for non-force-pushes, ensuring rebase targets point to fresh upstream commits while preserving stale refs as lease anchors when needed.
The rebase step in no-mistakes serves as the critical synchronization point that prevents stale references from corrupting your rebase operations. Located in internal/pipeline/steps/rebase.go, this implementation deliberately pulls the latest state from origin before any rebasing begins, guaranteeing that the tool never accidentally rebases onto outdated upstream commits. This fetch-first architecture eliminates the risk of silent merge conflicts or lost commits that could occur when working with cached remote-tracking branches.
Fetch-First Architecture of the Rebase Step
The RebaseStep implements a strict fetch-first policy that treats local remote-tracking refs as untrustable. According to the no-mistakes source code, the step executes targeted fetches from the authoritative remote (origin) to ensure all rebase targets reflect the true upstream state.
Always Fetching the Default Branch
Regardless of whether the operation involves a force-push or normal push, the step unconditionally fetches the repository's default branch from origin. In internal/pipeline/steps/rebase.go at lines 51-53, the code executes:
if err := git.FetchRemoteBranch(ctx, sctx.WorkDir, "origin", defaultBranch); err != nil {
sctx.LogFile(fmt.Sprintf("warning: could not fetch origin/%s: %v", defaultBranch, err))
}
This operation guarantees that origin/main (or equivalent) represents the actual upstream tip before any rebasing occurs. By refreshing this ref unconditionally, the step ensures that the primary rebase target never points to stale history.
Conditional Fetching for Non-Force-Pushes
When the step detects a normal push operation (not a force-push), it additionally refreshes the branch-specific remote-tracking ref. At lines 66-68 in rebase.go, the implementation fetches origin/<branch> for standard upstream branches:
if pushRemote == "origin" {
_ = git.FetchRemoteBranch(ctx, sctx.WorkDir, "origin", branch)
}
For fork-based workflows, lines 69-71 fetch the specific fork remote:
} else {
_ = git.FetchRemoteBranchToRef(ctx, sctx.WorkDir, pushRemote, branch, branchTarget)
}
This conditional logic ensures that branch-specific refs remain fresh for normal rebasing operations while allowing force-push scenarios to maintain their lease anchors.
Force-Push Handling and Stale Ref Preservation
The rebase step handles force-push scenarios differently to support the lease-based safety mechanism implemented in internal/pipeline/steps/forcepush.go. When isForcePushAgainstRemote returns true (lines 48-49), the step intentionally skips fetching the push-branch ref, preserving the stale remote-tracking state for use as a lease anchor.
Why Stale Refs Are Intentionally Retained
According to comments 55-63 in rebase.go, fetching the branch ref during a force-push would update the remote-tracking ref to the current live tip. This would destroy the lease anchor—the last known SHA that the push step uses to verify no external commits arrived on the remote. By intentionally leaving the push-branch ref stale, the system ensures that forcepush.go can detect when the remote has diverged from the expected state.
Lease Anchor Mechanics
The stale remote-tracking ref serves as the lastSeenSHA in the lease-with-content check. If the remote advanced while the user rewrote history, the discrepancy between the stale local ref and the live remote tip triggers a protective abort. This design prevents the tool from accidentally overwriting external commits that arrived during the rebase operation.
Implementation Details in rebase.go
The Execute method in RebaseStep orchestrates the fetch logic through a specific sequence that prioritizes safety over performance.
The Execute Method Flow
At lines 97-100, after completing the necessary fetches, the method calls rebaseTargetsForBranch to build an ordered list of refs for rebasing. This function operates on the freshly fetched refs, ensuring that git rebase commands target current upstream history rather than cached states.
When a force-push is detected and the default branch advanced during the operation, lines 82-95 emit a warning finding. This safety net catches the rare edge case where upstream moved while the user forced a rewrite, prompting manual review before proceeding.
Key Git Operations
The internal/git/git.go file provides the underlying fetch primitives used by the rebase step:
FetchRemoteBranchwrapsgit fetchto update a specific remote-tracking branchFetchRemoteBranchToRefhandles fork-specific fetch operations that map remote branches to local ref targets
These operations pull directly from the authoritative remote, bypassing any local cache that might contain stale information.
Summary
- The rebase step in no-mistakes always fetches
origin/<defaultBranch>before rebasing to ensure the primary target reflects the true upstream tip. - Conditional fetching of branch-specific refs occurs only for non-force-push operations, preventing accidental lease anchor corruption.
- During force-push scenarios, the step intentionally preserves stale remote-tracking refs to enable the lease-with-content safety check in
forcepush.go. - The implementation spans
internal/pipeline/steps/rebase.goandinternal/git/git.go, with critical logic at lines 48-71 and 97-100. - This architecture guarantees that rebase operations never target stale commits while maintaining the safety mechanisms required for force-push lease validation.
Frequently Asked Questions
How does the rebase step prevent rebasing onto stale remote refs?
The step unconditionally executes git.FetchRemoteBranch for the default branch from origin before constructing rebase targets. This fetch-first approach ensures that origin/<defaultBranch> always reflects the current upstream state, eliminating the risk of rebasing onto outdated commits that could result in silent merge conflicts or lost work.
Why does the rebase step skip fetching during a force-push?
When isForcePushAgainstRemote detects a force-push (lines 48-49), the step intentionally skips refreshing the push-branch remote-tracking ref. This preservation of the stale ref creates a lease anchor that forcepush.go uses to verify the remote hasn't advanced since the last fetch. If the step fetched during a force-push, it would update the local ref to the live tip, bypassing the lease safety check and risking accidental overwrites of external commits.
What happens if the default branch advances during a force-push operation?
The rebase step includes a safety check at lines 82-95 that detects when the default branch has moved while a force-push is in progress. In this scenario, the step emits a warning finding that prompts manual review, preventing the pipeline from blindly rebasing onto new commits that arrived during the force-push rewrite window.
Which source files control the fetch behavior in no-mistakes?
The fetch logic is implemented in internal/pipeline/steps/rebase.go (orchestration), internal/git/git.go (Git operations), and internal/pipeline/steps/forcepush.go (lease validation). Unit tests in rebase_test.go and rebase_force_test.go verify the interaction between fetching and force-push detection.
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 →