Skip to content
/ gfetch Public

Git sync daemon that polls remote repos and keeps local mirrors up to date. Supports SSH and HTTPS, branch/tag pattern matching, and OpenVox mode — where each matching ref gets its own checkout directory.

License

Notifications You must be signed in to change notification settings

Obmondo/gfetch

Repository files navigation

gfetch

GitHub Tests GitHub Docker Go Report Card Ask DeepWiki

A CLI tool that selectively mirrors remote Git repositories to local paths based on YAML configuration.

Features

  • Selective sync — choose exactly which branches and tags to mirror using exact names, wildcards (*), or regex patterns
  • Pruning — detect and remove local branches/tags that no longer match any configured pattern
  • Stale pruning — optionally remove inactive branches that have no new commits in a specified period (e.g., last 6 months); prune_stale only takes effect when prune is also enabled — stale branches are skipped before branch sync when both are set
  • Daemon mode — run as a foreground polling service with per-repo poll intervals
  • SSH and HTTPS auth — private repos via SSH key, public repos via anonymous HTTPS
  • Working tree checkout — optionally keep a working tree checked out on a specific branch or tag
  • OpenVox mode — create per-branch/tag directories with sanitized names, ideal for Puppet environments
  • Lightweight clones — repos are initialized empty and only configured refs are fetched

Quick Start

# Install
go install github.com/obmondo/gfetch/cmd/gfetch@latest

# Create a config file
cat <<'EOF' > config.yaml
repos:
  my-repo:
    url: https://github.com/example/repo.git
    local_path: /var/repos/my-repo
    poll_interval: 5m
    branches:
      - main
EOF

# Run a one-shot sync
gfetch sync

Or run with Docker:

docker run -v /path/to/config.yaml:/home/gfetch/config.yaml \
           -v /var/repos:/var/repos \
           ghcr.io/obmondo/gfetch daemon

Installation

From source

git clone https://github.com/obmondo/gfetch.git
cd gfetch
go build -o gfetch ./cmd/gfetch

With go install

go install github.com/obmondo/gfetch/cmd/gfetch@latest

Releases

Pre-built binaries for Linux and macOS (amd64/arm64) are available via GitHub Releases. Each release includes a checksums.txt for verification.

Docker

A pre-built image is published to the GitHub Container Registry on every tagged release.

# Pull the latest image
docker pull ghcr.io/obmondo/gfetch

# Run the daemon with config and repo storage mounted
docker run -v /path/to/config.yaml:/home/gfetch/config.yaml \
           -v /var/repos:/var/repos \
           ghcr.io/obmondo/gfetch daemon

To build locally:

docker build -t gfetch .

# With version info
docker build --build-arg VERSION=1.0.0 \
             --build-arg COMMIT=$(git rev-parse --short HEAD) \
             --build-arg DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
             -t gfetch .

Configuration

gfetch reads a YAML config file (default: config.yaml in the current directory). Use a defaults: key to share settings across multiple repositories.

defaults:
  ssh_key_path: /home/gfetch/.ssh/id_rsa
  poll_interval: 10m
  prune: true                   # remove branches/tags no longer matching any pattern
  prune_stale: true             # remove branches with no commits in 6 months (requires prune: true)
  stale_age: 180d               # supports d (days)

# TODO: Add integration tests for real SSH Git repositories.
# TODO: Implement concurrent syncing for OpenVox mode to improve performance and reliability.
# TODO: Add configurable concurrency limit per repository.

repos:
  my-service:
    url: git@github.com:obmondo/my-service.git
    branches:
      - main
      - /^release-.*/        # regex pattern
    tags:
      - "*"                  # wildcard matches all tags

  internal-tool:
    url: git@github.com:org/tool.git
    prune_stale: false          # override default for this repo
    branches:
      - main

See docs/configuration.md for the full configuration reference, including all fields, pattern syntax, auth methods, and validation rules.

Usage

Global Flags

Flag Default Description
--config, -c config.yaml Path to config file
--log-level info Log level: debug, info, warn, error

gfetch sync

One-shot sync of all repos (or a specific repo).

gfetch sync                    # sync all repos
gfetch sync --repo my-service  # sync a specific repo
gfetch sync --prune            # sync and remove obsolete branches/tags
gfetch sync --prune-stale      # sync and remove branches with no commits in 6 months
gfetch sync --stale-age 30d    # custom threshold for stale pruning
gfetch sync --prune --dry-run  # show what would be pruned without deleting
gfetch sync --prune --prune-stale  # also skips stale branches before branch sync
Flag Default Description
--repo (empty) Sync only the named repo
--prune false Delete local branches/tags that no longer match any pattern
--prune-stale false Delete local branches with no commits in the last 6 months; with --prune, stale branches are skipped before branch sync
--stale-age 180d Custom age threshold for stale pruning (e.g., 30d)
--dry-run false Show what would be pruned without actually deleting

gfetch daemon

Run as a foreground polling daemon. Each repo syncs immediately on start, then polls at its configured poll_interval. Shuts down gracefully on SIGINT or SIGTERM.

gfetch daemon
gfetch daemon --config /etc/gfetch/config.yaml --log-level debug

Pruning is controlled via prune and prune_stale config fields per-repo. Set prune: true in config to enable obsolete-ref pruning; prune_stale: true (also requires prune: true) to additionally prune inactive branches. The daemon does not reload config on changes — restart it to pick up new configuration.

gfetch validate-config

Validate the config file and exit.

gfetch validate-config
gfetch validate-config -c /path/to/config.yaml

gfetch cat

Print the fully resolved configuration as YAML. Loads the config, applies defaults, validates, and outputs the result to stdout.

gfetch cat
gfetch cat -c /path/to/config.yaml

gfetch version

Print version information.

$ gfetch version
gfetch dev (commit: none, built: unknown)

Version, commit, and build date are injected at build time via ldflags when using GoReleaser or a manual build with -ldflags.

Documentation

License

TBD

About

Git sync daemon that polls remote repos and keeps local mirrors up to date. Supports SSH and HTTPS, branch/tag pattern matching, and OpenVox mode — where each matching ref gets its own checkout directory.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages