Skip to content

git-fire/git-rain

Repository files navigation

git-rain — Multi-Repo Sync CLI

git-rain: storm cloud, lightning bolt, falling DAG, commit node, wordmark git-rain: storm cloud, lightning bolt, falling DAG, commit node, wordmark

Status: 1.0 Go 1.24.2 License: MIT

The reverse of git-fire.

git-fire  →  commit + push everything out
git-rain  →  fetch (default) or full reverse sync with --sync

git-rain discovers git repositories under your scan path (and known registry entries), then by default fetches mainline remote-tracking refs only (main, master, trunk, develop, dev, gitflow prefixes, plus your configured patterns). Use --sync for full hydration: fast-forwarding branches, updating non-checked-out refs, and skipping anything that would rewrite local-only commits unless you enable risky mode.

Invocation note: git-rain and git rain are equivalent when git-rain is on your PATH.

Table of Contents

Quick Start

# preview first — shows what would be synced without touching anything
git-rain --dry-run

# default: scan repos, then fetch mainline remote-tracking refs from remotes
git-rain

# full local branch sync (same safety/risky rules as before)
git-rain --sync

# interactive TUI: pick repos, then default fetch or --sync behavior
git-rain --rain

Install

Method Command Platform
Homebrew brew install git-fire/tap/git-rain macOS, Linuxbrew
WinGet winget install git-rain.git-rain Windows
Linux package Download .deb or .rpm from GitHub Releases Linux
Go go install github.com/git-rain/git-rain@latest All (Go 1.24.2+)
Binary archive GitHub Releases All

Homebrew (macOS/Linuxbrew)

brew tap git-fire/tap
brew install git-rain

WinGet (Windows)

winget install git-rain.git-rain

Linux native packages (.deb / .rpm)

Download from GitHub Releases, then:

# Debian/Ubuntu
sudo dpkg -i ./git-rain_<version>_amd64.deb

# Fedora/RHEL/CentOS (dnf)
sudo dnf install ./git-rain_<version>_amd64.rpm

Go install

go install github.com/git-rain/git-rain@latest

Or pin an explicit release:

go install github.com/git-rain/git-rain@v1.0.0

Binary archive (manual)

Download and extract the right archive from GitHub Releases, then place the binary on your PATH.

PATH setup (required)

Go install (Linux/macOS):

export PATH="$HOME/go/bin:$PATH"

Add that line to ~/.zshrc or ~/.bashrc to persist.

Manual binary install (Linux/macOS):

chmod +x git-rain
sudo mv git-rain /usr/local/bin/

Manual binary install (Windows PowerShell):

New-Item -ItemType Directory -Force "$env:USERPROFILE\bin" | Out-Null
Move-Item .\git-rain.exe "$env:USERPROFILE\bin\git-rain.exe" -Force

Then add $env:USERPROFILE\bin to your user PATH if not already present.

Verify install

git-rain --version
which git-rain

Build from source

git clone https://github.com/git-fire/git-rain.git
cd git-rain
make build         # produces ./git-rain
make install       # installs to ~/.local/bin/git-rain

Requires Go 1.24.2+.

How It Works

  1. Scan — walks your configured scan path and includes known registry repos (--no-scan limits to registry only)
  2. Default: mainline fetch — for each repo, runs targeted git fetch <remote> --prune for mainline branches so origin/main (etc.) advance; local branch refs are not moved
  3. With --sync (or non-mainline branch_mode in config, or --risky) — full hydrate: runs git fetch --all --prune (optional --tags), then for each eligible local branch with a tracked upstream:
    • If the branch can be fast-forwarded: updates it
    • If the branch has local-only commits: skips (safe mode) or backs up and resets (risky mode)
    • If the working tree is dirty on the checked-out branch: skips
  4. Report — per-branch outcomes: fetched, synced, up-to-date, skipped (with reason), failed

Key Features

  • One-command workflow — discover repos, then default mainline fetch or full --sync hydrate
  • Safety-first defaults — never rewrites local-only commits; dirty worktrees are skipped, not clobbered
  • Risky mode — opt-in destructive realignment: creates a git-rain-backup-* ref, then hard-resets to upstream
  • Non-checked-out branches — updated directly without touching the worktree
  • Interactive TUI (--rain) — streaming repo picker (mirrors git-fire --fire), then the same default fetch or --sync behavior
  • Registry — discovered repos persist across runs; mark repos ignored to skip them permanently
  • Dry run — preview all repos that would be synced without making any changes
  • Fetch-only mode (--fetch-only) — run git fetch --all --prune per repo (all refs), without the mainline-only default

Core Commands

# dry run — preview repos, no changes
git-rain --dry-run

# default run — scan repos, fetch mainline remote-tracking refs
git-rain

# full local branch sync after scan
git-rain --sync

# interactive TUI before default fetch or sync
git-rain --rain

# fetch everything from all remotes (broader than default mainline fetch)
git-rain --fetch-only

# sync only known registry repos, skip filesystem scan
git-rain --no-scan

# scan a specific path
git-rain --path ~/projects

# risky full sync — realign local-only commits after creating backup branches
git-rain --sync --risky

# generate example config file
git-rain --init

Flags

Flag Description
--dry-run Show what would run without making changes
--rain Interactive TUI repo picker before running (like git-fire --fire)
--sync Update local branches from remotes (default is mainline fetch only)
--fetch-only git fetch --all --prune per repo (all refs); skips local branch updates
--path <dir> Scan path override (default: config global.scan_path)
--no-scan Skip filesystem scan; hydrate only known registry repos
--risky Allow destructive local branch realignment after creating backup refs
--init Generate example ~/.config/git-rain/config.toml
--config <file> Use an explicit config file path
--force-unlock-registry Remove stale registry lock file without prompting
--version Print version and exit

Configuration

Config file: ~/.config/git-rain/config.toml

Generate an example:

git-rain --init

Key options:

[global]
scan_path    = "/home/you/projects"   # root to discover repos under
scan_depth   = 5                      # max directory depth
scan_workers = 8                      # parallel scan workers
risky_mode   = false                  # enable risky mode globally
default_mode = "safe"                 # "safe" or "risky"
disable_scan = false                  # skip scan; use registry only

scan_exclude = [
  "node_modules",
  ".cache",
  "vendor",
]

All options can be overridden with environment variables using the GIT_RAIN_ prefix:

GIT_RAIN_GLOBAL_RISKY_MODE=true git-rain
GIT_RAIN_GLOBAL_SCAN_PATH=/tmp/repos git-rain

Interactive TUI

git-rain --rain opens an interactive picker. Repositories stream in as the filesystem scan finds them — no waiting for the full scan to complete before you can start picking. After you confirm, the tool runs the default mainline fetch unless you also passed --sync (or config implies full sync).

Key bindings:

Key Action
space Toggle repo selection
a Select all / deselect all
enter Confirm selection and begin fetch or sync
q / esc Abort
/ Navigate

Safe Mode vs Risky Mode

Situation Safe mode (default) Risky mode (--risky)
Branch is fast-forwardable ✓ Updated ✓ Updated
Branch has local-only commits ⊘ Skipped ⚠ Backed up + reset
Checked-out branch, dirty worktree ⊘ Skipped ⊘ Skipped
No upstream tracked ⊘ Skipped ⊘ Skipped

In risky mode, a git-rain-backup-<branch>-<timestamp> ref is created before any hard reset so local work is always recoverable.

Registry

Discovered repositories are stored in ~/.config/git-rain/repos.toml. Each entry tracks path, name, status, and last-seen time.

Repo statuses:

  • active — present on disk and eligible for sync
  • missing — was discovered previously but the directory is gone
  • ignored — permanently excluded from sync

The registry uses a file lock to prevent concurrent git-rain instances from corrupting it. If a previous run exited uncleanly, git-rain detects the stale lock and prompts to remove it (or pass --force-unlock-registry for non-interactive use).

Security Notes

git-rain shells out to the system git binary and inherits your existing git credentials (SSH agent, credential helper, etc.). No credentials are stored or transmitted by git-rain itself.

Secret detection: git-rain sanitizes error messages and log output to avoid echoing paths or git output that might contain tokens. This is a best-effort measure — keep secrets out of repo paths and remote URLs.

Contributing

Contributions are welcome. Tests use git-testkit for building git repository fixtures in integration-style tests. Prefer table-driven tests and real git invocations over mocks.

make test-race   # run all tests with race detector
make lint        # go vet

Open an issue before starting large changes.

License

MIT. See LICENSE.

About

Reverse sync — pull all your local repos from their remotes

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors