git-ark is a CLI tool written in Go for backing up a local Git repository to one or more configured remotes.
It is built around a simple idea: keep the default backup path safe, explicit, and easy to audit.
While service-side technical failures are rare on platforms like GitHub, GitLab, Bitbucket, et al. - they can still happen.
This project was created to mitigate data loss as a result of service-side technical failures, account loss, or some other act of (digital) nature.
Docs site: https://sphireinc.github.io/git-ark/
- Backs up branches and tags to multiple remotes.
- Uses mirror mode only when you ask for it.
- Can create a local bundle archive alongside remote backups.
- Synchronizes local remotes from config when you want the repo to match the file.
- Surfaces repo health, remote reachability, and provider-specific guidance.
- Records backup history in metadata so
statuscan show what happened last time.
go build ./cmd/git-arkgo run ./cmd/git-ark --helpTagged pushes trigger the release workflow in .github/workflows/release.yml, which builds binaries for Linux, macOS, and Windows, creates a GitHub Release, and attaches release assets plus checksums. The same workflow can also be run manually from the GitHub Actions UI by providing a tag name like v1.0.2. Those releases can be found and downloaded from Releases.
- Generate a starter config:
git-ark init- Review the generated file and point
remotesat your backup destination. - Validate the repo and config:
git-ark validate- Run a dry run first if you want to see the plan:
git-ark backup --dry-run- Run the real backup:
git-ark backup- Check the latest metadata and repo health:
git-ark status
git-ark doctor| Command | What it does |
|---|---|
git-ark init |
Writes a starter git-ark.yml file. |
git-ark validate |
Checks the config and local repo for obvious problems. |
git-ark backup |
Runs the backup workflow against configured remotes. |
git-ark status |
Shows repo state, configured remotes, and backup history. |
git-ark doctor |
Runs health checks and provider-aware diagnostics. |
git-ark remotes list |
Lists configured remotes and whether they exist locally. |
git-ark remotes sync |
Adds or updates local Git remotes from config. |
git-ark version |
Prints build/version information. |
--config: use an explicit config file path.--repo: override the repo directory.--dry-run: show the plan without mutating remotes or creating bundles.--json: emit machine-readable output where supported.
git-ark backup also supports:
--mode: override the configured mode.--remote: run against a selected subset of remotes.--include-disabled: allow selected remotes that are disabled in config.--yes: skip the mirror-mode confirmation prompt.--verbose: print more target detail.--quiet: suppress normal plan and summary output.--prune: prune remote refs not present locally.
git-ark init generates a commented starter file. A minimal config can be as small as:
remotes:
github:
url: git@github.com:example/example-backup.gitA more complete config looks like this:
version: 1
repo: "."
mode: "safe"
remotes:
github:
url: git@github.com:example/example-backup.git
enabled: true
required: true
provider: github
description: GitHub backup mirror
gitlab:
url: git@gitlab.com:example/example-backup.git
enabled: true
required: true
provider: gitlab
options:
manage_remotes: true
push_branches: true
push_tags: true
push_notes: false
push_all_refs: false
prune: false
verify_clean_worktree: false
continue_on_error: true
confirm_dangerous_operations: true
fetch_before_backup: false
pull_before_backup: false
skip_lfs: false
include_archived_branches: true
write_metadata: true
branch_filters:
include:
- main
- release/*
exclude:
- wip/*
tag_filters:
include:
- v*
exclude:
- test-*
bundle:
enabled: true
path: ./backups
filename_template: "{{repo}}-{{timestamp}}.bundle"
include_all_refs: true
logging:
level: debug
format: text
metadata:
path: .git/git-ark-last-backup.json| Field | Purpose |
|---|---|
version |
Config schema version. Current value: 1. |
repo |
Default repo path to operate on. |
mode |
Backup mode: safe, mirror, or bundle. |
remotes |
Map of remote names to remote definitions. |
options |
Backup behavior toggles. |
branch_filters |
Include/exclude glob filters for branches. |
tag_filters |
Include/exclude glob filters for tags. |
bundle |
Local bundle archive settings. |
logging |
Output format settings. |
metadata |
Path for the last-backup history file. |
| Field | Purpose |
|---|---|
url |
Remote URL. Required. |
enabled |
Whether the remote is part of a normal backup run. |
required |
Whether a failure on this remote should count as a required failure. |
provider |
Provider hint for diagnostics, validation, and friendlier output. |
description |
Human-friendly note for maintainers. |
Useful provider hints:
githubgitlabbitbucketcodeberggiteagenericsshhttps
- Safety and sync behavior:
manage_remotesconfirm_dangerous_operationscontinue_on_errorprunepush_all_refs
- Backup scope:
push_branchespush_tagspush_notesinclude_archived_branchesskip_lfs
- Preflight steps:
verify_clean_worktreefetch_before_backuppull_before_backup
- History and output:
write_metadata
push_all_refs is broader than the normal safe mode. prune is opt-in and narrows the push behavior, but it can still delete remote refs that are no longer present locally.
Safe mode is the default. It pushes branches and tags without mirroring every ref.
git push <remote> --all
git push <remote> --tagsMirror mode is explicit and destructive.
git push <remote> --mirrorIf confirmation is enabled, git-ark requires --yes in non-interactive environments.
Bundle mode creates a local Git bundle archive in addition to the selected backup behavior.
git bundle create <output> --allBranch and tag filters use glob matching.
If an include list is empty, everything is included unless excluded.
branch_filters:
include:
- main
- release/*
exclude:
- wip/*
tag_filters:
include:
- v*
exclude:
- test-*git-ark remotes sync is useful when you want the local repo to match the config file.
git-ark remotes list
git-ark remotes syncUse --dry-run if you only want to see what would change.
After a successful backup, git-ark writes a history file to .git/git-ark-last-backup.json by default.
git-ark status reads that history and shows:
- The latest run
- The number of recorded backups
- A short recent history summary
If you move the metadata file in config, status follows that path.
git-ark doctor checks:
- Whether
gitis available - Whether
sshis available - Whether the repo looks valid
- Whether the local branch/tag state looks reasonable
- Whether configured remotes are reachable
- Whether configured providers look like they match the remote URL
If provider and host do not line up, doctor will call that out. That is intentional and usually means the URL or the provider field needs a quick review.
- If mirror mode fails in a non-interactive shell, pass
--yes. - If HTTPS remotes fail, try a token-based URL or switch to SSH.
- If SSH remotes fail, make sure your agent is running and the key is loaded.
- If
validatesays no remotes are configured, add at least one remote entry. - If
doctorwarns about a provider mismatch, check the provider value and the remote host. - If
statusshows no history, rungit-ark backuponce withoptions.write_metadata: true.
- Use a recent Git for Windows installation.
- Make sure
gitis onPATH. - Forward-compatible SSH URLs like
git@github.com:org/repo.gitwork well. - If you rely on SSH, make sure an agent is running and your key is loaded.
- Secrets are never printed intentionally.
- HTTPS credentials in URLs are redacted in output.
- Mirror mode can delete refs on the destination, so it requires explicit confirmation.
- This tool shells out to the installed
gitbinary; it does not implement a custom Git protocol client.
- v1 does not remove local remotes.
- v1 does not implement a custom Git protocol client.
- v1 does not attempt to reconcile remote history beyond the selected push mode.
- Archived-branch handling is still limited to configuration and planning.
- Full Git LFS backup is not implemented;
skip_lfsonly skips smudge downloads during preflight fetch/pull.
.github/workflows/ci.ymlruns tests, vet, and build on Linux, macOS, and Windows..github/workflows/release.ymlbuilds tagged binaries for Linux, macOS, and Windows and publishes GitHub Releases..github/workflows/pages.ymldeploys the docs site to GitHub Pages fromdocs/.
