https://github.com/sphireinc/git-ark
A cross-platform CLI/script that takes one local git repo and pushes it to multiple remote git providers as backup mirrors
https://github.com/sphireinc/git-ark
backup code git github mirroring repository
Last synced: 23 days ago
JSON representation
A cross-platform CLI/script that takes one local git repo and pushes it to multiple remote git providers as backup mirrors
- Host: GitHub
- URL: https://github.com/sphireinc/git-ark
- Owner: sphireinc
- License: mit
- Created: 2026-04-27T16:03:28.000Z (about 2 months ago)
- Default Branch: main
- Last Pushed: 2026-05-20T05:52:30.000Z (29 days ago)
- Last Synced: 2026-05-20T09:20:07.280Z (29 days ago)
- Topics: backup, code, git, github, mirroring, repository
- Language: Go
- Homepage: https://sphireinc.github.io/git-ark/
- Size: 3.7 MB
- Stars: 5
- Watchers: 0
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# git-ark
`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 GitLab, Bitbucket, et al. - they can still happen - take for instance GitHub.
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:
## What It Does
- 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 `status` can show what happened last time.
## Installation
### Build From Source
```bash
go build ./cmd/git-ark
```
### Run Without Installing
```bash
go run ./cmd/git-ark --help
```
### Tagged Builds
Tagged pushes trigger the release workflow in [.github/workflows/release.yml](./.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](https://github.com/sphireinc/git-ark/releases).
## Quick Start
1. Generate a starter config:
```bash
git-ark init
```
2. Review the generated file and point `remotes` at your backup destination.
3. Validate the repo and config:
```bash
git-ark validate
```
4. Run a dry run first if you want to see the plan:
```bash
git-ark backup --dry-run
```
5. Run the real backup:
```bash
git-ark backup
```
6. Check the latest metadata and repo health:
```bash
git-ark status
git-ark doctor
```
## Commands
| 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. |
## Common Flags
- `--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.
## Configuration
`git-ark init` generates a commented starter file. A minimal config can be as small as:
```yaml
remotes:
github:
url: git@github.com:example/example-backup.git
```
A more complete config looks like this:
```yaml
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
```
### Top-Level Fields
| 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. |
### Remote Fields
| 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:
- `github`
- `gitlab`
- `bitbucket`
- `codeberg`
- `gitea`
- `generic`
- `ssh`
- `https`
### Option Groups
- Safety and sync behavior:
- `manage_remotes`
- `confirm_dangerous_operations`
- `continue_on_error`
- `prune`
- `push_all_refs`
- Backup scope:
- `push_branches`
- `push_tags`
- `push_notes`
- `include_archived_branches`
- `skip_lfs`
- Preflight steps:
- `verify_clean_worktree`
- `fetch_before_backup`
- `pull_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.
## Modes
### Safe Mode
Safe mode is the default. It pushes branches and tags without mirroring every ref.
```bash
git push --all
git push --tags
```
### Mirror Mode
Mirror mode is explicit and destructive.
```bash
git push --mirror
```
If confirmation is enabled, `git-ark` requires `--yes` in non-interactive environments.
### Bundle Mode
Bundle mode creates a local Git bundle archive in addition to the selected backup behavior.
```bash
git bundle create --all
```
## Filters
Branch and tag filters use glob matching.
If an include list is empty, everything is included unless excluded.
```yaml
branch_filters:
include:
- main
- release/*
exclude:
- wip/*
tag_filters:
include:
- v*
exclude:
- test-*
```
## Remote Management
`git-ark remotes sync` is useful when you want the local repo to match the config file.
```bash
git-ark remotes list
git-ark remotes sync
```
Use `--dry-run` if you only want to see what would change.
## Metadata and History
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.
## Doctor and Provider Diagnostics
`git-ark doctor` checks:
- Whether `git` is available
- Whether `ssh` is 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.
## Troubleshooting
- 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 `validate` says no remotes are configured, add at least one remote entry.
- If `doctor` warns about a provider mismatch, check the provider value and the remote host.
- If `status` shows no history, run `git-ark backup` once with `options.write_metadata: true`.
## Windows Notes
- Use a recent Git for Windows installation.
- Make sure `git` is on `PATH`.
- Forward-compatible SSH URLs like `git@github.com:org/repo.git` work well.
- If you rely on SSH, make sure an agent is running and your key is loaded.
## Security
- 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 `git` binary; it does not implement a custom Git protocol client.
## Limitations
- 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_lfs` only skips smudge downloads during preflight fetch/pull.
## GitHub Actions
- [`.github/workflows/ci.yml`](./.github/workflows/ci.yml) runs tests, vet, and build on Linux, macOS, and Windows.
- [`.github/workflows/release.yml`](./.github/workflows/release.yml) builds tagged binaries for Linux, macOS, and Windows and publishes GitHub Releases.
- [`.github/workflows/pages.yml`](./.github/workflows/pages.yml) deploys the docs site to GitHub Pages from `docs/`.