Add the git-fleet project to the content index as the first featured project, bumping the remaining project orders, and register its entry page in the sitemap. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
44 lines
2.6 KiB
Markdown
44 lines
2.6 KiB
Markdown
---
|
|
title: git-fleet
|
|
slug: git-fleet
|
|
summary: A Git extension written in OCaml for managing repositories across multiple Git hosts, keeping a single remote mirrored to several push destinations.
|
|
label: Project
|
|
date: 2026-10-17
|
|
status: Active
|
|
featured: true
|
|
order: 1
|
|
github: https://git.sowinski.dev/SowinskiBraeden/git-fleet
|
|
tags: OCaml, CLI, Git, Dune, Developer Tools
|
|
---
|
|
|
|
## Overview
|
|
|
|
`git-fleet` is a native CLI that simplifies the Git workflows I use across self-hosted Git services and public hosts. I run my own Gitea instance but still mirror most repositories to GitHub, and keeping both in sync meant hand-editing remote configuration in every new project.
|
|
|
|
The project started as a handful of personal shell scripts for configuring dual-push repositories, and is being rebuilt in OCaml as a single, reusable command. Because Git exposes any `git-*` executable on `PATH` as a subcommand, the tool installs as `git fleet`.
|
|
|
|
## How It Works
|
|
|
|
Rather than inventing its own state, `git-fleet` configures ordinary Git remotes. A remote fetches from one URL and may push to several, which is how one repository stays mirrored across more than one host.
|
|
|
|
The subtlety is that a remote with no `pushurl` pushes to the URL it fetches from, but 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, and `git fleet remove` collapses the configuration back to plain Git behaviour once the only destination left is the fetch URL.
|
|
|
|
```sh
|
|
git fleet status
|
|
git fleet add git@github.com:user/project.git
|
|
git fleet remove git@github.com:user/project.git --dry-run
|
|
```
|
|
|
|
## Focus Areas
|
|
|
|
- Modelling remote configuration as a plan that can be previewed before it is applied, so `--dry-run` works on every command that changes something
|
|
- Invoking Git directly as a subprocess rather than through a shell, avoiding quoting and injection problems entirely
|
|
- Keeping the resulting configuration indistinguishable from what someone would write by hand
|
|
- Testing against temporary repositories so the test suite never touches the configuration of the repository it runs in
|
|
|
|
## Notes
|
|
|
|
This is my first real project in OCaml, and the language has been a good fit for it. The remote state is a small, closed set of shapes, and the type system makes it awkward to forget a case — which matters when the tool's whole job is rewriting configuration that people's pushes depend on.
|
|
|
|
Version 0.2.0 covers remote management: `status`, `add`, and `remove`. The longer-term goal is to cover the rest of the multi-host workflow, starting with creating a repository on several hosts at once.
|