Skip to content

artifact-fs sync: fast-forward mounted branch from remote (like gh repo sync) #27

Description

@ducan-ne

Summary

Today the daemon’s background refresh only runs git fetch. artifact-fs status can show behind > 0, but HEAD and the FUSE mount stay on the old commit until the user manually fast-forwards or checks out.

For agent/sandbox workflows (the primary audience in the README), we want a simple way to keep the mounted working tree aligned with origin/<branch>, similar to how gh repo sync updates a destination branch to match a source using fast-forward by default.

Motivation / use case

I use ArtifactFS for fast access to large repos without a full clone. I also use gh repo sync day to day: one command, branch matches upstream when FF is possible.

With ArtifactFS I expected “background refresh” to mean the mount stays current. Instead:

  1. refreshLoop fetches periodically (--refresh, default 30s).
  2. behind / ahead / diverged update in status.
  3. The visible tree does not advance until HEAD moves (manual git merge --ff-only, git pull, etc.).

That gap is awkward for:

  • Read-mostly agent sandboxes that should always read latest main.
  • Disposable CI/dev containers using the Docker example.
  • Anyone who treats status’s behind= as “updates available” and assumes the mount already reflects them.

Proposed behavior (mirror gh repo sync semantics)

Reference: gh repo sync — sync destination from source; fast-forward unless --force (hard reset).

1. New CLI: artifact-fs sync

# Sync registered repo: fetch + fast-forward local branch to origin/<tracked-branch> when safe
artifact-fs sync --name workers-sdk

# Optional branch override
artifact-fs sync --name workers-sdk --branch main

Default (no --force):

  • git fetch (same as today).
  • If behind > 0 and ahead == 0 and !diverged → fast-forward refs/heads/<branch> to origin/<branch> (reuse logic similar to PrepareFetchedBranch in gitstore).
  • Watcher / onHEADChanged already re-indexes snapshot and reconciles overlay when HEAD moves — mount updates without new FUSE machinery.

Skip FF (exit 0 with message, or exit 1 — maintainers’ choice) when:

  • overlay_dirty=true (local overlay writes; avoid surprising data loss).
  • ahead > 0 (local commits not on remote).
  • diverged=true.
  • FF not possible for any other git reason.

Optional --force (advanced, document loudly):

  • Analogous to gh repo sync --force: hard reset local branch to origin/<branch>.
  • Only when explicitly requested; never default for daemon auto-sync.
  • Must interact safely with overlay (document risks or refuse when overlay_dirty unless --force).

2. Optional daemon mode: auto-sync after fetch

Complement one-shot sync with an opt-in policy on the repo (not default-on):

artifact-fs add-repo ... --sync-policy ff-only   # or: off | ff-only | force
# or
artifact-fs set-sync --name workers-sdk --policy ff-only

When sync-policy=ff-only, after each successful background fetch in refreshLoop, run the same safe FF rules as artifact-fs sync (no --force in the loop).

Default remains fetch-only (off) so local developers aren’t surprised by the tree moving under their editor.

What exists already (implementation sketch)

Piece Location / notes
Periodic fetch daemon.refreshLoop
Ahead/behind/diverged gitstore.ComputeAheadBehind, status
Overlay dirty RepoRuntimeState.DirtyOverlay
Branch update after fetch gitstore.PrepareFetchedBranch (async prepare path)
Mount refresh on HEAD change watcheronHEADChanged

This is mostly wiring + policy, not a new subsystem.

Non-goals

  • Auto-push / two-way sync (separate feature).
  • Merge commits on diverged branches (user runs git manually).
  • Default-on auto FF for all mounts without an explicit flag.
  • Replacing normal git pull for interactive dev on dirty overlays.

Docs

  • Clarify in README: background fetch ≠ fast-forward; link to sync / sync-policy.
  • Fix minor confusion: architecture text suggests watcher runs on fetch; today fetch alone does not move HEAD.

Acceptance criteria (suggested)

  • artifact-fs sync --name <repo> fetches and FF when safe; mount tree matches new HEAD.
  • Sync no-ops cleanly when already up to date.
  • Sync refuses FF when overlay_dirty or ahead > 0 or diverged (unless --force where implemented).
  • Optional sync-policy on daemon refresh with default off.
  • Tests: FF success, skip when dirty/diverged/ahead, watcher re-index.

Environment

  • ArtifactFS (main / 1.0.0-rc.x), macOS + macFUSE or Linux + fuse3.
  • Inspiration: gh repo sync local workflow (gh repo sync / gh repo sync --branch <name>).

Happy to help with a PR if the approach looks right.

Metadata

Metadata

Assignees

No one assigned

    Labels

    potential-low-quality-prSummary-template issue/PR or large PR from a new account

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions