116 lines
3.4 KiB
Markdown
116 lines
3.4 KiB
Markdown
# git-fleet
|
|
|
|
A Git extension for managing repositories across multiple Git hosts and destinations.
|
|
|
|
`git-fleet` is a native CLI I'm building to simplify the Git workflows I use across self-hosted Git services and public hosts. The project started as a few personal scripts for configuring dual-push repositories and is being rebuilt in OCaml as a single, reusable command.
|
|
|
|
## Status
|
|
|
|
**v0.2.0: remote management**
|
|
|
|
- `git fleet status`, `git fleet add` and `git fleet remove`
|
|
- Multiple push destinations on a single remote
|
|
- Preserves the destination a remote already pushed to
|
|
- Collapses redundant configuration back to plain Git behaviour
|
|
- `--dry-run` on every command that changes something
|
|
- Git is run directly, never through a shell
|
|
|
|
## How it works
|
|
|
|
`git-fleet` configures ordinary Git remotes. A remote fetches from one URL and may push to several, which is how a repository stays mirrored across more than one host:
|
|
|
|
```ini
|
|
[remote "origin"]
|
|
url = git@git.example.invalid:user/project.git
|
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
|
pushurl = git@git.example.invalid:user/project.git
|
|
pushurl = git@github.com:user/project.git
|
|
```
|
|
|
|
A remote with no `pushurl` pushes to the URL it fetches from. As soon as it has one `pushurl`, Git pushes only to the URLs listed there, so `git fleet add` writes out the existing destination before adding a new one. Removing a destination reverses that: when the only one left is the fetch URL, the redundant configuration is dropped.
|
|
|
|
Every command works on `origin` unless `--remote` says otherwise.
|
|
|
|
## Usage
|
|
|
|
Show where a remote fetches from and pushes to:
|
|
|
|
```sh
|
|
git fleet status
|
|
git fleet status --remote upstream
|
|
```
|
|
|
|
```
|
|
origin
|
|
fetch git@git.example.invalid:user/project.git
|
|
push git@git.example.invalid:user/project.git
|
|
push git@github.com:user/project.git
|
|
```
|
|
|
|
Add a destination. With neither `--fetch` nor `--push`, the URL is added as a push destination. A remote that does not exist yet is created:
|
|
|
|
```sh
|
|
git fleet add git@github.com:user/project.git
|
|
git fleet add git@git.example.invalid:user/project.git --fetch
|
|
git fleet add git@git.example.invalid:user/project.git --fetch --push
|
|
git fleet add git@github.com:user/project.git --remote upstream
|
|
```
|
|
|
|
Remove a push destination. URLs are matched exactly, as they appear in `git fleet status`:
|
|
|
|
```sh
|
|
git fleet remove git@github.com:user/project.git
|
|
```
|
|
|
|
Preview the Git commands instead of running them:
|
|
|
|
```sh
|
|
git fleet add git@github.com:user/project.git --dry-run
|
|
```
|
|
|
|
```
|
|
Would change remote 'origin':
|
|
git remote set-url --add --push origin git@git.example.invalid:user/project.git
|
|
git remote set-url --add --push origin git@github.com:user/project.git
|
|
```
|
|
|
|
Commands exit with `1` and a single line on standard error when something is wrong, such as running outside a repository or naming a remote that does not exist.
|
|
|
|
## Installation
|
|
|
|
Build a release binary and put it on your `PATH`:
|
|
|
|
```sh
|
|
dune build --release
|
|
install -Dm755 _build/default/bin/main.exe ~/.local/bin/git-fleet
|
|
```
|
|
|
|
Git exposes any `git-*` executable on `PATH` as a subcommand, so `git-fleet` becomes:
|
|
|
|
```sh
|
|
git fleet --help
|
|
git fleet --version
|
|
```
|
|
|
|
## Development
|
|
|
|
Install the project dependencies:
|
|
|
|
```sh
|
|
opam install . --deps-only --with-test
|
|
```
|
|
|
|
Build, test and run:
|
|
|
|
```sh
|
|
dune build
|
|
dune runtest
|
|
dune exec git-fleet -- status
|
|
```
|
|
|
|
The tests create temporary repositories and never change the configuration of this one.
|
|
|
|
## License
|
|
|
|
MIT
|