Skip to main content

repofleet

Clone, update and track a fleet of git repositories from a single declarative config.

One command (repofleet sync) gets any machine into the same state:

  • repos in the list but not on disk are cloned,
  • repos already on disk are fetched, switched to their default branch and pulled (local work is auto-stashed and restored),
  • repos found on disk that are not in the list yet are updated and then added to the config, so the shared list grows organically.

It is generic: nothing is hard-coded to a team, org or git host. Any team can ship its own repofleet.toml (or a plain repos.txt) and get the same workflow.

Documentation: full usage guide · publishing guide · changelog

Contents

Install · Quick start · Commands · Configuration · Output & exit codes · Authentication · Troubleshooting · Development


Install

pip install repofleet          # from your package index
pipx install repofleet         # isolated, always on PATH
pip install -e ".[dev]"        # from a checkout of this folder

Private feed:

pip install repofleet --index-url https://pkgs.dev.azure.com/<org>/_packaging/<feed>/pypi/simple/

No install? Unzip the folder and use the bundled launcher:

python bootstrap.py sync

Requires Python 3.9+ and git on PATH. Verify with repofleet --version.


Quick start

You already have the repos checked out

cd "/path/to/your/workspace"
repofleet init --name "Backend Services" --match "svc.*"
repofleet sync

init scans the folder, records every git repo it finds and writes repofleet.toml plus an empty repo-urls.txt you can paste more URLs into.

You have nothing yet (typical for a new joiner)

Drop the shared repofleet.toml in an empty folder and run:

repofleet sync

Everything is cloned into the workspace directory declared in the config (directory = "...").

An example profile ships with the package at src/repofleet/profiles/example-workspace.toml - copy it, swap in your own URLs, and run:

repofleet sync -c example-workspace.toml

You just want a list of URLs cloned somewhere

repofleet clone --repos-file repo-urls.txt --root ./workspace

Commands

Command What it does
repofleet init Create a config from the repositories found on disk.
repofleet list Show every tracked repo and whether it is present locally.
repofleet status Per-repo branch + clean/dirty state, and what is missing.
repofleet clone Clone only the repositories that are missing.
repofleet update Fetch + pull every cloned repo (add --clone-missing to do both).
repofleet sync Clone missing, update existing, adopt new local repos into the config.
repofleet add <url...> Track new repositories (--clone to fetch them immediately).
repofleet remove <name...> Stop tracking repositories (files on disk are left alone).

Common options (available on every command):

-c, --config FILE     config file to use (default: nearest repofleet.toml, then $REPOFLEET_CONFIG)
    --root DIR        where the repositories live / should be cloned
    --repos-file FILE extra repo list, TOML or plain text (repeatable)
    --repo URL        extra repository straight from the command line (repeatable)
    --only PATTERN    restrict to matching repo names (glob)
    --exclude PATTERN skip matching repo names (glob)
    --remote NAME     remote to use (default: origin)
-j, --jobs N          run N repos in parallel
    --dry-run         print the plan without touching anything
-q, --quiet           summary only

update / sync also accept --no-stash (skip dirty repos instead of stashing) and --no-prune. sync accepts --no-adopt to disable writing newly discovered repos back to the config.

Examples:

repofleet update --only "svc.a*" -j 8
repofleet clone --repos-file repo-urls.txt --root ./workspace
repofleet sync --dry-run
repofleet add https://dev.azure.com/org/Project/_git/new.service --clone

Every flag is documented in the usage guide.


Configuration

repofleet.toml

[workspace]
name      = "Backend Services"
# "auto": use this file's folder when it already holds repos, else use `directory`.
root      = "auto"
directory = "Backend Services"
match     = ["svc.*"]          # which local folders may be auto-adopted
remote    = "origin"
repos_file = "repo-urls.txt"   # optional: extra repos listed one URL per line

[defaults]
stash     = true   # stash local changes before pulling, restore afterwards
prune     = true   # git fetch --prune
jobs      = 4      # parallel workers
autoadopt = true   # write newly discovered local repos back into this file

[[repos]]
name = "svc.api"
url  = "https://github.com/org/svc.api.git"
# branch = "develop"   # optional, defaults to the remote's default branch

name is optional - it is derived from the URL when omitted.

Plain text list (easiest to share)

# repo-urls.txt
https://github.com/org/svc.api.git
https://github.com/org/tooling.git
custom-folder-name = https://github.com/org/other.git
https://github.com/org/legacy.git   release/2024   # pin a branch

Use it with --repos-file repo-urls.txt, or reference it from repos_file in the TOML. repofleet init creates this file for you, pre-filled with commented-out examples.

Config lookup order

  1. --config/-c
  2. $REPOFLEET_CONFIG
  3. nearest repofleet.toml / .repofleet.toml walking up from the current directory
  4. %APPDATA%\repofleet\repofleet.toml (Windows) or ~/.config/repofleet/repofleet.toml

Where repos end up

--root wins; otherwise [workspace] root (relative to the config file); with the default "auto" the config's own folder is used when it already contains repos, and <config folder>/<directory> when it does not. repofleet status prints the resolved root.


Output & exit codes

config : C:\code\Backend Services\repofleet.toml
root   : C:\code\Backend Services
  [+] svc.api: updated
  [x] svc.auth: failed

--------------------------------------------------
Sync summary
--------------------------------------------------
svc.api   updated
          - on main
svc.auth  failed
          - git pull failed: ...
--------------------------------------------------
2 repo(s): 1 failed, 1 updated
Action Meaning
cloned Freshly cloned.
updated Pulled new commits.
up to date Already current.
skipped Nothing to do (already cloned, dirty with --no-stash, or dry run).
missing Listed but not cloned yet.
failed Git reported an error; details follow.

Exit codes: 0 success · 1 a repo failed / nothing selected · 2 config or environment error · 130 interrupted.


Authentication

repofleet uses your existing git credentials and sets GIT_TERMINAL_PROMPT=0, so a batch run fails fast instead of hanging on a password prompt. Configure Git Credential Manager, a credential helper, or SSH keys once before the first run.


Troubleshooting

Symptom Fix
'git' was not found on PATH Install git or open a fresh shell.
repofleet: command not found Use python -m repofleet ..., or install with pipx.
could not read Username Credentials are missing and prompts are disabled; clone one repo manually or use SSH.
No repositories selected No config found — run repofleet init, or pass --repo / --repos-file.
Repos cloned somewhere unexpected Check the root : header from repofleet status, or pass --root.
stash pop failed - stash kept Resolve the conflict in that repo, then git stash pop.

More cases in the usage guide.


Safety notes

  • Git is always invoked with an argument list, never through a shell.
  • GIT_TERMINAL_PROMPT=0 prevents a batch run from hanging on a credential prompt.
  • Any credentials embedded in a remote URL are masked in console output.
  • pull --ff-only is tried first; a merge pull is only attempted if fast-forward is impossible.
  • If git stash pop fails after a pull, the stash is kept and the repo is reported as failed - your work is never discarded.
  • remove only edits the config; it never deletes directories.

Development

pip install -e ".[dev]"
pytest -q

Tests spin up real local git repositories in a temp folder — no network needed. See the usage guide for the project layout and the publishing guide for cutting a release.

License

MIT.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

repofleet-0.2.0.tar.gz (33.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

repofleet-0.2.0-py3-none-any.whl (22.8 kB view details)

Uploaded Python 3

File details

Details for the file repofleet-0.2.0.tar.gz.

File metadata

  • Download URL: repofleet-0.2.0.tar.gz
  • Upload date:
  • Size: 33.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for repofleet-0.2.0.tar.gz
Algorithm Hash digest
SHA256 9046882b94b0cf012e3ac4d5c232607acbd11e91699306ae718230783a580207
MD5 629b5d1adb6e67aea3e010e904bbfdd6
BLAKE2b-256 5875b1599eea736aa0ae8066caab4d16af27d06e2f0e38b25023db6302f916ff

See more details on using hashes here.

Provenance

The following attestation bundles were made for repofleet-0.2.0.tar.gz:

Publisher: publish.yml on kavirayuni-dev/repofleet

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file repofleet-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: repofleet-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 22.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for repofleet-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1e18e0c2331cd095ca078c72be6656ff562c666e6947b2830ff81aa430d7f421
MD5 337f3e815f0b6f673160535de98d0ada
BLAKE2b-256 693918cf93f2587bea20b373a0a7d5271b2c2c5739bb6ebb9295466cb8753d4f

See more details on using hashes here.

Provenance

The following attestation bundles were made for repofleet-0.2.0-py3-none-any.whl:

Publisher: publish.yml on kavirayuni-dev/repofleet

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page