git-back-dots
Git-backed configuration backups for CachyOS and Arch Linux.
git-back-dots discovers configuration files, groups them by package or
component, and manages git repos with a Textual terminal UI. It has a headless
runner for systemd timers, path triggers, and shutdown commits.
Discovery, the git runner, logging, scheduling, environment-token detection, snapshot repositories, package-config suggestions, workarounds, OAuth device-flow login, and the core TUI all work and are covered by tests. The provider-side remote-creation flow and branch-merge UI are not finished yet.
Repository modes
inplace — the git root contains the tracked files. /etc is the canonical
example: gbd run etc commits changes directly inside /etc. Use this for
system configuration trees.
snapshot — a managed repo stores copies of scattered source files under a
deterministic files/… tree. Before every commit the runner syncs each tracked
source into the snapshot; restore copies back atomically. Use this for
dotfiles and package configs that live anywhere on disk.
gbd repo add dots ~/.local/share/git-back-dots/dots --mode snapshot \
--track ~/.config/fish/config.fish --track ~/.bashrc
gbd run dots --mode commit
gbd repo restore dots ~/.config/fish/config.fish
Install
From PyPI (recommended):
uv tool install git-back-dots
That installs gbd and git-back-dots into uv's tool bin directory
(~/.local/bin by default — make sure it is on your PATH).
For the checkout being developed here:
cd ~/Projects/etc/20260725/git-back-dots
uv tool install --editable .
For an unreleased GitHub checkout:
uv tool install git+https://github.com/boundring/git-back-dots.git
Requirements
- Linux with systemd (timers/path units are how scheduled runs fire)
- git, and an SSH key or PAT for pushing to remotes
- CachyOS/Arch for the pacman-aware
scan packages/repo suggestfeatures; everything else is distribution-agnostic
Shell completion and man page
gbd --install-completion # completion for bash/zsh/fish
gbd man --install ~/.local/share/man/man1 # then: man gbd
gbd man with no options prints the manual to the terminal. gbd --help
and gbd COMMAND --help cover every subcommand.
Commands
gbd # launch the TUI
gbd doctor # git, systemd, ssh-key, PAT, and registry checks
gbd scan etc # discover /etc candidates and package owners
gbd scan home # discover dotfiles and ~/.config candidates
gbd scan packages # pacman-aware config suggestions per naming schema
gbd repo suggest # turn package suggestions into snapshot repos
gbd auth env # detect GITHUB_TOKEN, GH_TOKEN, CODEBERG_TOKEN
gbd auth ssh # list public keys and test provider SSH auth
gbd auth login github # OAuth device-flow login (needs --client-id or env)
gbd man # print the manual; --install DIR installs gbd.1
gbd repo list # show registered repositories
gbd run NAME --mode push
gbd workaround add NAME --target PATH # track a live patch
gbd workaround check # drift report (exit 1 when stale)
gbd workaround apply NAME # re-apply now
gbd run is the command generated systemd units execute. It commits only when
the repo is dirty, then pushes with BatchMode SSH and hard timeouts.
Repository naming schema
| Prefix | Scope | Use |
|---|---|---|
dots-<pkg> |
user | dotfiles owned by a package |
etc-<pkg> |
system | package-owned system configuration |
etc-base |
system | the whole /etc tree (inplace) |
wa-<name> |
any | workaround repos (see below) |
Workarounds
A workaround is a live patch applied to another tool's files — for example a
hotfix inside an installed application that its next update will clobber.
git-back-dots tracks the patched files in a dedicated snapshot repo under
~/.local/share/git-back-dots/workarounds/<name>/, generates an idempotent
apply.sh, and can re-apply automatically:
gbd workaround add my-fix --target ~/.local/lib/tool/patched.py
gbd workaround schedule my-fix # path unit watches the live file
The path unit fires when the target changes. The runner then checks drift:
if the live file differs from the snapshot (the update clobbered the patch),
apply.sh installs the tracked copy back before committing — the repo always
records the patched state. Your own edits are safe: the runner syncs them
into the snapshot on the same pass, so intentional changes are committed, not
reverted. Disable with --no-auto and apply manually with
gbd workaround apply NAME.
apply.sh runs as the installing user (via sudo -E for --system
workarounds). It is generated from the repo and committed to git history —
review it like any other privileged script. Keep workaround repos private if
the patched files come from proprietary or third-party source.
Packages
gbd scan packages combines a well-known profile list (Emacs, KDE/Plasma,
fish, common AI CLIs, …) with an /etc sweep over everything pacman has
installed. Library, framework, and game packages are filtered out by default;
--all shows them dimmed, and ignore_packages in the config extends the
filter. AI-CLI profiles are explicit allowlists — auth tokens, session
databases, and history files are never tracked, and the pre-commit secret
scanner is the backstop.
gbd repo suggest --apply registers the suggestions as snapshot repos using
the naming schema above.
Authentication
Authentication sources are resolved in this order:
- SSH remotes and local SSH authentication.
- Provider PATs in the current process environment.
- Tokens stored through the system keyring, falling back to an owner-only file.
GitHub environment variables: GITHUB_TOKEN, then GH_TOKEN.
Codeberg environment variables: CODEBERG_TOKEN, then GITEA_TOKEN.
OAuth device flow
gbd auth login github (or codeberg) walks the OAuth device flow: it
prints a one-time code and verification URL, polls until you authorize,
validates the token, stores it via the system keyring (or an owner-only file),
and registers the account. The TUI Accounts screen offers the same flow on
l. The device flow needs a public OAuth app client ID — register an OAuth
app with the provider (device flow enabled), then pass --client-id or set
GBD_GITHUB_CLIENT_ID / GBD_CODEBERG_CLIENT_ID.
gbd auth env masks token values and only prints the final four characters.
Tokens are never put in a remote URL or written to the run journal.
System services do not inherit your login environment. For root-owned
repos, use a root-owned SSH key and SSH remote. The system registry is copied
to /etc/git-back-dots/config.toml during schedule installation; it contains
repo metadata only, never PAT values.
Scheduling model
Per repo, git-back-dots generates:
- a delayed boot/interval timer that runs
pushafter networking is available; - an optional
PathChanged=unit for selected hot files; - a shutdown service that performs a local commit only.
The shutdown unit never attempts a network push. A later timer or the next boot sends the committed change. Pushes use a 15-second limit and SSH batch mode, so they cannot request a password or hang indefinitely.
Validate the generated units before installing them:
gbd schedule install NAME
systemctl --user list-timers 'gbd-*' # user repos
systemctl list-timers 'gbd-*' # system repos
journalctl -t git-back-dots
Current limits
- A timer can fire while a file is mid-edit; git commits whatever bytes are on disk. Inherent to any file-based backup — prefer quiescent times (boot, shutdown, idle intervals) for system repos.
- OAuth device-flow login is wired (
gbd auth login, TUIl). It stores tokens and registers accounts, but it does not yet create provider-side remotes for you — create the empty repo on GitHub/Codeberg yourself, thengbd repo add NAME PATH --remote URL. HTTPS credential injection for git pushes is also not wired — use SSH remotes or env-var PATs for pushing. - The TUI includes dashboard, discovery, repo files/history/schedule views, accounts, logs, notifications, workarounds, and a per-file history browser with restore-from-any-version. Branch merge UI is still planned.
Development
uv sync --extra dev
uv run ruff check src/ tests/
uv run pytest tests/ -q
uv build
License
GPL-3.0-only. See LICENSE.
Release files for git-back-dots 0.2.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| git_back_dots-0.2.3.tar.gz | 57.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| git_back_dots-0.2.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 132.8 kB
Release files / git_back_dots-0.2.3.tar.gz
| Download URL | git_back_dots-0.2.3.tar.gz |
|---|---|
| Size | 57.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bba313af277ddffedc048e8978cb6368b8b543a2a245a5fa2404638a8695ed5b
|
|
BLAKE2b-256 checksum How to use checksums |
96d7763ca80afcc711748d800097a0b63772ffe551ad5824b7a85f10e1b021f3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / git_back_dots-0.2.3-py3-none-any.whl
| Download URL | git_back_dots-0.2.3-py3-none-any.whl |
|---|---|
| Size | 75.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
23987f1976d1a367a51f8786b0c53f6a2e1176493d89d25eb4fb0a7a96bfdb24
|
|
BLAKE2b-256 checksum How to use checksums |
c3c6d42b9297b13a159a58fe7f7ef718c318c6e9b7a1f359c35c95b9b49b67f7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"CachyOS Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|