git-sync mirrors refs from a source remote to a target remote without creating a local checkout. It uses an in-memory go-git object store and talks smart HTTP directly:
info/refsref advertisement for source and targetupload-packfetch from source with target tip hashes advertised ashavereceive-packpush to target with explicit ref update commands and a streamed packfile
That keeps the target side incremental without fetching target objects into the local process first.
Mirroring Git data between remotes usually means a local mirror clone followed by a mirror push. That's fine for small repos but turns a remote-to-remote operation into a local storage problem at scale, and shell glue around git fetch / git push tends to skip planning and structured output.
git-sync fills that gap. It streams source packs directly into target receive-pack when it can, plans every action before pushing, and emits typed JSON for automation.
For when to use it (and when not), see docs/architecture.md.
The main commands are:
git-sync sync: mirror source refs into the targetgit-sync replicate: overwrite target refs to match source via relay, and fail rather than materialize locally
sync automatically bootstraps an empty target, so the same command covers initial seeding and ongoing sync. To preview what would happen without pushing, run git-sync plan β it takes the same flags as sync, and --mode replicate previews a replicate run.
For command examples, JSON output, auth, protocol flags, and advanced command notes, see docs/usage.md.
git-sync is also a Go library. Use entire.io/entire/git-sync for the stable embedding surface (Probe, Plan, Sync, Replicate, typed results, auth and HTTP injection). entire.io/entire/git-sync/unstable exposes advanced controls (Bootstrap, Fetch, batching knobs, heap measurement) and is not stable.
brew tap entireio/tap
brew install --cask git-syncRequires Go 1.26 or newer.
go install entire.io/entire/git-sync/cmd/git-sync@latestThis drops a git-sync binary into $(go env GOPATH)/bin. Make sure that directory is on your PATH.
git clone https://github.com/entireio/git-sync.git
cd git-sync
go build -o git-sync ./cmd/git-syncgit-sync sync \
--source-token "$GITSYNC_SOURCE_TOKEN" \
--target-token "$GITSYNC_TARGET_TOKEN" \
https://github.com/source-org/source-repo.git \
https://github.com/target-org/target-repo.gitgitsync.mp4
sync picks the bootstrap relay path automatically when the target is empty. For non-empty targets, safe fast-forward updates also use a relay path that streams the source pack directly into target receive-pack without local materialization. Anything not relay-eligible (force, prune, deletes, tag retargets) falls back to a materialized path bounded by --materialized-max-objects.
For branch filtering, ref mapping, tags, pruning, protocol selection, JSON output, and auth details, see docs/usage.md.
Default suite:
env GOCACHE=/tmp/go-build go test ./...Extended and environment-specific test instructions are in docs/testing.md.
- docs/usage.md β CLI commands, examples, sync behavior, JSON output, auth, protocol notes
- docs/architecture.md β product rationale, package layout, operation modes vs transfer modes, memory model
- docs/protocol.md β smart HTTP, pkt-line, capability negotiation, sideband, relay framing
- docs/testing.md β test suites and integration coverage
git-sync syncs the complete Git object history required for the selected refs. It does not create a shallow clone. Some planning paths may use filtered fetches, but the target receives the full objects needed for valid refs.
Objects as well. Refs are what git-sync plans and updates, but it also transfers the commits, trees, blobs, and tags needed for those refs to exist on the target.
No. git-sync is one-way: source remote to target remote. To go the other way you'd run a second invocation with the endpoints swapped.
Yes. It supports creating refs, updating refs, force updates with --force, and deleting managed refs with --prune. replicate can overwrite target refs, but it is relay-only and more restrictive than sync.
git-sync has two transfer paths:
- Relay β pack data streams from source
upload-packdirectly into targetreceive-pack. The local process holds no object graph, so memory stays bounded regardless of repo size. Used when the target supports relay. - Materialized fallback β when relay isn't available,
git-syncfetches the needed objects into an in-memorygo-gitstore, plans, then encodes and pushes a packfile. Memory scales with the diff being pushed and is guarded by an explicit object-count limit. Bootstrap can batch large initial syncs to keep this bounded.
Planning itself is cheap: ref-only round-trips, plus a filter tree:0 fetch for ancestry checks when the source advertises filter support.
It depends on repository size, network speed, and whether the relay path is available. As a rule of thumb, the relay path is bounded by source pack generation + network transfer + target receive-pack time β roughly the time of a git clone from the source plus a git push of the same pack. The materialized fallback adds local memory work for objects that need inspection.
For concrete numbers on your own setup, run the included benchmark tool against a representative repo; see docs/testing.md.
No. git-sync supports smart HTTP/HTTPS only.
No. git-sync is a one-shot CLI/library operation. To sync on a schedule or in response to events, run it from cron, CI, a worker, or another service.
See CONTRIBUTING.md, SECURITY.md, and CODE_OF_CONDUCT.md.
