Skip to content

Commit 6fec24b

Browse files
committed
Public release
1 parent 9f8876d commit 6fec24b

46 files changed

Lines changed: 4962 additions & 1 deletion

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ dist/
88
coverage.out
99
*.test
1010
git-ark
11-
11+
git-ark.yml
12+
.idea/

README.md

Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,367 @@
1+
# git-ark
2+
3+
<p align="center">
4+
<img src="./logo-transparent.png" alt="git-ark logo" width="400" />
5+
</p>
6+
7+
<p align="center">
8+
<a href="https://github.com/sphireinc/git-ark/actions/workflows/ci.yml">
9+
<img alt="CI" src="https://github.com/sphireinc/git-ark/actions/workflows/ci.yml/badge.svg?branch=main" />
10+
</a>
11+
<a href="https://github.com/sphireinc/git-ark/actions/workflows/release.yml">
12+
<img alt="Release" src="https://github.com/sphireinc/git-ark/actions/workflows/release.yml/badge.svg" />
13+
</a>
14+
<a href="./LICENSE">
15+
<img alt="License" src="https://img.shields.io/badge/license-MIT-blue.svg" />
16+
</a>
17+
</p>
18+
19+
`git-ark` is a CLI tool written in Go for backing up a local Git repository to one or more configured remotes.
20+
21+
It is built around a simple idea: keep the default backup path safe, explicit, and easy to audit.
22+
23+
While service-side technical failures are rare on platforms like GitHub, GitLab, Bitbucket, et al. - they can still happen.
24+
25+
This project was created to mitigate data loss as a result of service-side technical failures, account loss, or some
26+
other act of (digital) nature.
27+
28+
Docs site: <https://sphireinc.github.io/git-ark/>
29+
30+
## What It Does
31+
32+
- Backs up branches and tags to multiple remotes.
33+
- Uses mirror mode only when you ask for it.
34+
- Can create a local bundle archive alongside remote backups.
35+
- Synchronizes local remotes from config when you want the repo to match the file.
36+
- Surfaces repo health, remote reachability, and provider-specific guidance.
37+
- Records backup history in metadata so `status` can show what happened last time.
38+
39+
## Installation
40+
41+
### Build From Source
42+
43+
```bash
44+
go build ./cmd/git-ark
45+
```
46+
47+
### Run Without Installing
48+
49+
```bash
50+
go run ./cmd/git-ark --help
51+
```
52+
53+
### Tagged Builds
54+
55+
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. Those can be found and downloaded from [Releases](https://github.com/sphireinc/git-ark/releases).
56+
57+
## Quick Start
58+
59+
1. Generate a starter config:
60+
61+
```bash
62+
git-ark init
63+
```
64+
65+
2. Review the generated file and point `remotes` at your backup destination.
66+
3. Validate the repo and config:
67+
68+
```bash
69+
git-ark validate
70+
```
71+
72+
4. Run a dry run first if you want to see the plan:
73+
74+
```bash
75+
git-ark backup --dry-run
76+
```
77+
78+
5. Run the real backup:
79+
80+
```bash
81+
git-ark backup
82+
```
83+
84+
6. Check the latest metadata and repo health:
85+
86+
```bash
87+
git-ark status
88+
git-ark doctor
89+
```
90+
91+
## Commands
92+
93+
| Command | What it does |
94+
| --- | --- |
95+
| `git-ark init` | Writes a starter `git-ark.yml` file. |
96+
| `git-ark validate` | Checks the config and local repo for obvious problems. |
97+
| `git-ark backup` | Runs the backup workflow against configured remotes. |
98+
| `git-ark status` | Shows repo state, configured remotes, and backup history. |
99+
| `git-ark doctor` | Runs health checks and provider-aware diagnostics. |
100+
| `git-ark remotes list` | Lists configured remotes and whether they exist locally. |
101+
| `git-ark remotes sync` | Adds or updates local Git remotes from config. |
102+
| `git-ark version` | Prints build/version information. |
103+
104+
## Common Flags
105+
106+
- `--config`: use an explicit config file path.
107+
- `--repo`: override the repo directory.
108+
- `--dry-run`: show the plan without mutating remotes or creating bundles.
109+
- `--json`: emit machine-readable output where supported.
110+
111+
`git-ark backup` also supports:
112+
113+
- `--mode`: override the configured mode.
114+
- `--remote`: run against a selected subset of remotes.
115+
- `--include-disabled`: allow selected remotes that are disabled in config.
116+
- `--yes`: skip the mirror-mode confirmation prompt.
117+
- `--verbose`: print more target detail.
118+
- `--quiet`: suppress normal plan and summary output.
119+
- `--prune`: prune remote refs not present locally.
120+
121+
## Configuration
122+
123+
`git-ark init` generates a commented starter file. A minimal config can be as small as:
124+
125+
```yaml
126+
remotes:
127+
github:
128+
url: [email protected]:example/example-backup.git
129+
```
130+
131+
A more complete config looks like this:
132+
133+
```yaml
134+
version: 1
135+
repo: "."
136+
mode: "safe"
137+
remotes:
138+
github:
139+
url: [email protected]:example/example-backup.git
140+
enabled: true
141+
required: true
142+
provider: github
143+
description: GitHub backup mirror
144+
gitlab:
145+
url: [email protected]:example/example-backup.git
146+
enabled: true
147+
required: true
148+
provider: gitlab
149+
options:
150+
manage_remotes: true
151+
push_branches: true
152+
push_tags: true
153+
push_notes: false
154+
push_all_refs: false
155+
prune: false
156+
verify_clean_worktree: false
157+
continue_on_error: true
158+
confirm_dangerous_operations: true
159+
fetch_before_backup: false
160+
pull_before_backup: false
161+
skip_lfs: false
162+
include_archived_branches: true
163+
write_metadata: true
164+
branch_filters:
165+
include:
166+
- main
167+
- release/*
168+
exclude:
169+
- wip/*
170+
tag_filters:
171+
include:
172+
- v*
173+
exclude:
174+
- test-*
175+
bundle:
176+
enabled: true
177+
path: ./backups
178+
filename_template: "{{repo}}-{{timestamp}}.bundle"
179+
include_all_refs: true
180+
logging:
181+
level: debug
182+
format: text
183+
metadata:
184+
path: .git/git-ark-last-backup.json
185+
```
186+
187+
### Top-Level Fields
188+
189+
| Field | Purpose |
190+
| --- | --- |
191+
| `version` | Config schema version. Current value: `1`. |
192+
| `repo` | Default repo path to operate on. |
193+
| `mode` | Backup mode: `safe`, `mirror`, or `bundle`. |
194+
| `remotes` | Map of remote names to remote definitions. |
195+
| `options` | Backup behavior toggles. |
196+
| `branch_filters` | Include/exclude glob filters for branches. |
197+
| `tag_filters` | Include/exclude glob filters for tags. |
198+
| `bundle` | Local bundle archive settings. |
199+
| `logging` | Output format settings. |
200+
| `metadata` | Path for the last-backup history file. |
201+
202+
### Remote Fields
203+
204+
| Field | Purpose |
205+
| --- | --- |
206+
| `url` | Remote URL. Required. |
207+
| `enabled` | Whether the remote is part of a normal backup run. |
208+
| `required` | Whether a failure on this remote should count as a required failure. |
209+
| `provider` | Provider hint for diagnostics, validation, and friendlier output. |
210+
| `description` | Human-friendly note for maintainers. |
211+
212+
Useful provider hints:
213+
214+
- `github`
215+
- `gitlab`
216+
- `bitbucket`
217+
- `codeberg`
218+
- `gitea`
219+
- `generic`
220+
- `ssh`
221+
- `https`
222+
223+
### Option Groups
224+
225+
- Safety and sync behavior:
226+
- `manage_remotes`
227+
- `confirm_dangerous_operations`
228+
- `continue_on_error`
229+
- `prune`
230+
- `push_all_refs`
231+
- Backup scope:
232+
- `push_branches`
233+
- `push_tags`
234+
- `push_notes`
235+
- `include_archived_branches`
236+
- `skip_lfs`
237+
- Preflight steps:
238+
- `verify_clean_worktree`
239+
- `fetch_before_backup`
240+
- `pull_before_backup`
241+
- History and output:
242+
- `write_metadata`
243+
244+
`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.
245+
246+
## Modes
247+
248+
### Safe Mode
249+
250+
Safe mode is the default. It pushes branches and tags without mirroring every ref.
251+
252+
```bash
253+
git push <remote> --all
254+
git push <remote> --tags
255+
```
256+
257+
### Mirror Mode
258+
259+
Mirror mode is explicit and destructive.
260+
261+
```bash
262+
git push <remote> --mirror
263+
```
264+
265+
If confirmation is enabled, `git-ark` requires `--yes` in non-interactive environments.
266+
267+
### Bundle Mode
268+
269+
Bundle mode creates a local Git bundle archive in addition to the selected backup behavior.
270+
271+
```bash
272+
git bundle create <output> --all
273+
```
274+
275+
## Filters
276+
277+
Branch and tag filters use glob matching.
278+
279+
If an include list is empty, everything is included unless excluded.
280+
281+
```yaml
282+
branch_filters:
283+
include:
284+
- main
285+
- release/*
286+
exclude:
287+
- wip/*
288+
289+
tag_filters:
290+
include:
291+
- v*
292+
exclude:
293+
- test-*
294+
```
295+
296+
## Remote Management
297+
298+
`git-ark remotes sync` is useful when you want the local repo to match the config file.
299+
300+
```bash
301+
git-ark remotes list
302+
git-ark remotes sync
303+
```
304+
305+
Use `--dry-run` if you only want to see what would change.
306+
307+
## Metadata and History
308+
309+
After a successful backup, `git-ark` writes a history file to `.git/git-ark-last-backup.json` by default.
310+
311+
`git-ark status` reads that history and shows:
312+
313+
- The latest run
314+
- The number of recorded backups
315+
- A short recent history summary
316+
317+
If you move the metadata file in config, `status` follows that path.
318+
319+
## Doctor and Provider Diagnostics
320+
321+
`git-ark doctor` checks:
322+
323+
- Whether `git` is available
324+
- Whether `ssh` is available
325+
- Whether the repo looks valid
326+
- Whether the local branch/tag state looks reasonable
327+
- Whether configured remotes are reachable
328+
- Whether configured providers look like they match the remote URL
329+
330+
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.
331+
332+
## Troubleshooting
333+
334+
- If mirror mode fails in a non-interactive shell, pass `--yes`.
335+
- If HTTPS remotes fail, try a token-based URL or switch to SSH.
336+
- If SSH remotes fail, make sure your agent is running and the key is loaded.
337+
- If `validate` says no remotes are configured, add at least one remote entry.
338+
- If `doctor` warns about a provider mismatch, check the provider value and the remote host.
339+
- If `status` shows no history, run `git-ark backup` once with `options.write_metadata: true`.
340+
341+
## Windows Notes
342+
343+
- Use a recent Git for Windows installation.
344+
- Make sure `git` is on `PATH`.
345+
- Forward-compatible SSH URLs like `[email protected]:org/repo.git` work well.
346+
- If you rely on SSH, make sure an agent is running and your key is loaded.
347+
348+
## Security
349+
350+
- Secrets are never printed intentionally.
351+
- HTTPS credentials in URLs are redacted in output.
352+
- Mirror mode can delete refs on the destination, so it requires explicit confirmation.
353+
- This tool shells out to the installed `git` binary; it does not implement a custom Git protocol client.
354+
355+
## Limitations
356+
357+
- v1 does not remove local remotes.
358+
- v1 does not implement a custom Git protocol client.
359+
- v1 does not attempt to reconcile remote history beyond the selected push mode.
360+
- Archived-branch handling is still limited to configuration and planning.
361+
- Full Git LFS backup is not implemented; `skip_lfs` only skips smudge downloads during preflight fetch/pull.
362+
363+
## GitHub Actions
364+
365+
- [`.github/workflows/ci.yml`](./.github/workflows/ci.yml) runs tests, vet, and build on Linux, macOS, and Windows.
366+
- [`.github/workflows/release.yml`](./.github/workflows/release.yml) builds tagged binaries for Linux, macOS, and Windows and publishes GitHub Releases.
367+
- [`.github/workflows/pages.yml`](./.github/workflows/pages.yml) deploys the docs site to GitHub Pages from `docs/`.

0 commit comments

Comments
 (0)