diff --git a/README.md b/README.md index 4003b16..ed88468 100644 --- a/README.md +++ b/README.md @@ -6,33 +6,92 @@ A Git extension for managing repositories across multiple Git hosts and destinat ## Status -**v0.1.0: CLI foundation** +**v0.2.0: remote management** -Initial release is just figuring out the project structure and command-line interface: +- `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 -- Native OCaml executable -- Dune build system -- Cmdliner command interface -- `git fleet` Git subcommand integration -- Automated tests +## How it works -Remote and multi-destination management will begin in v0.2.0. +`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 -Once `git-fleet` is installed somewhere on your `PATH`, Git automatically exposes it as a subcommand: +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 ``` -You can also invoke the executable directly: - -```sh -git-fleet --help -``` - ## Development Install the project dependencies: @@ -41,24 +100,15 @@ Install the project dependencies: opam install . --deps-only --with-test ``` -Build: +Build, test and run: ```sh dune build -``` - -Run the tests: - -```sh dune runtest +dune exec git-fleet -- status ``` -Run the development executable: - -```sh -dune exec git-fleet -- --help -dune exec git-fleet -- --version -``` +The tests create temporary repositories and never change the configuration of this one. ## License