User guide / Git

Fetch, pull, and push

Development reference · View source

Tab f in the branch list fetches one branch. Pull and push use Tab p and Tab P in the branch list and the changed-file list. :git-refresh re-reads what is already local.

Fetch (Tab f)

  • A remote row fetches its exact server branch into the selected remote-tracking ref. A local row fetches its configured upstream, including a differently named or currently missing upstream.
  • Configure a remote upstream first for a local branch that has none. A local . upstream is not a network target. Excluded or ambiguous fetch mappings, symbolic destinations, and mappings outside refs/remotes/ are refused.
  • Only the selected remote-tracking ref changes. Other cached branches and tags stay in place; no pruning or tag fetching occurs. A force-pushed upstream may replace that cached ref, and the retained Git operation notification identifies the forced update.
  • Local branches, the index, and working files remain intact. Unsaved buffers and a dirty working tree do not prevent fetching.
  • The branch list refreshes and retains its selected ref, including after failure or cancellation. Discovering branches not yet known locally belongs in an external Git tool; there is no whole-remote fetch action.

:git-fetch-branch performs the same action on the selected branch-list row.

Pull (Tab p)

SituationWhat happens
A fast-forward is possibleIt happens silently: the branch had no commits of its own to lose
Both sides have new commitsIt shows the drift and offers to replay your commits on theirs
Unsaved buffers in the repositoryRefused first, since pulled files are reloaded
Dirty worktreeRefused

The offer reads like: main and origin/main have both moved on. Press Enter to replay 2 local commits on top of the 1 on origin/main. Escape leaves the branch as it was.

  • The replay is a rebase, so there is never a merge commit whose message nothing here could write. It rewrites the replayed commits; they stay reachable from the reflog under their old identities, which is why it asks.
  • On conflict it undoes itself: the rebase is aborted, the working tree keeps what it held, and the refusal says so. Runyte has no surface for resolving conflicts, so it never leaves you holding one; finish those in your usual Git tool.
  • Afterwards open files are reloaded and gutter bases refreshed, as after a checkout.
  • No autostash. Uncommitted changes are never stashed, even with merge.autoStash or rebase.autoStash. Git reapplies such a stash afterwards, and when that conflicts it still exits successfully — leaving conflict markers and a stash to recover, with nothing to roll back. A dirty worktree is refused up front instead.
  • Fetch and merge run separately, not as one git pull, so an unreachable remote is reported as such. The drift offered for replay is read from remote-tracking refs, which are only worth reading once a fetch has refreshed them.

Push (Tab P)

  • Publishes to the ref the branch tracks.
  • The first time, it sets an upstream: origin when it exists, or the only remote when there is exactly one.
  • Nothing forces. A push rejected because the remote has commits you lack is reported as such, naming Tab p as the way to catch up.