From 9c16e34a407598350925b22a6fa9f2dc907d4281 Mon Sep 17 00:00:00 2001 From: SowinskiBraeden Date: Sat, 17 Oct 2026 23:26:27 -0700 Subject: [PATCH] add git-fleet project entry 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 --- public/content/index.json | 39 +++++++++++++++++++------ public/content/projects/git-fleet.md | 43 ++++++++++++++++++++++++++++ sitemap.xml | 5 ++++ 3 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 public/content/projects/git-fleet.md diff --git a/public/content/index.json b/public/content/index.json index 9b48291..ffc936e 100644 --- a/public/content/index.json +++ b/public/content/index.json @@ -1,5 +1,26 @@ { "projects": [ + { + "title": "git-fleet", + "slug": "git-fleet", + "type": "projects", + "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", + "github": "https://git.sowinski.dev/SowinskiBraeden/git-fleet", + "demo": null, + "featured": true, + "order": 1, + "tags": [ + "OCaml", + "CLI", + "Git", + "Dune", + "Developer Tools" + ], + "path": "./public/content/projects/git-fleet.md" + }, { "title": "Reforger Mods API", "slug": "reforger-mods-api", @@ -11,7 +32,7 @@ "github": "https://github.com/SowinskiBraeden/ReforgerWorkshopAPI", "demo": "https://api.reforgermods.net", "featured": true, - "order": 1, + "order": 2, "tags": [ "Go", "REST API", @@ -33,7 +54,7 @@ "github": "https://git.sowinski.dev/SowinskiBraeden/boker", "demo": "https://myboker.org", "featured": true, - "order": 2, + "order": 3, "tags": [ "Python", "Flask", @@ -55,7 +76,7 @@ "github": "https://git.sowinski.dev/SowinskiBraeden/ScheduleGeneratorApp", "demo": null, "featured": true, - "order": 3, + "order": 4, "tags": ["Python", "Desktop App", "Scheduling", "Data Processing"], "path": "./public/content/projects/schedule-generator-app.md" }, @@ -70,7 +91,7 @@ "github": "https://git.sowinski.dev/SowinskiBraeden/dayz-reforger", "demo": null, "featured": true, - "order": 4, + "order": 5, "tags": ["Node.js", "Discord.js", "MongoDB", "Analytics", "Nitrado"], "path": "./public/content/projects/dayz-reforger-bot.md" }, @@ -85,7 +106,7 @@ "github": "https://github.com/LinesMerrill/police-cad", "demo": "https://www.linespolice-cad.com/", "featured": false, - "order": 5, + "order": 6, "tags": ["Node.js", "Express", "MongoDB", "Web App"], "path": "./public/content/projects/lines-police-cad.md" }, @@ -100,7 +121,7 @@ "github": "https://git.sowinski.dev/SowinskiBraeden/SowinskiBraeden", "demo": null, "featured": false, - "order": 6, + "order": 7, "tags": ["HTML", "CSS", "JavaScript", "Portfolio"], "path": "./public/content/projects/portfolio.md" }, @@ -115,7 +136,7 @@ "github": null, "demo": "https://vairo-performance.com", "featured": false, - "order": 7, + "order": 8, "tags": ["Freelance", "Web Design", "Domain Setup", "Client Work"], "path": "./public/content/projects/vairo-performance-website.md" }, @@ -130,7 +151,7 @@ "github": "https://git.sowinski.dev/SowinskiBraeden/school-management-api", "demo": null, "featured": false, - "order": 8, + "order": 9, "tags": ["Go", "API", "Documentation", "Education Tech"], "path": "./public/content/projects/school-management-api.md" }, @@ -145,7 +166,7 @@ "github": "https://git.sowinski.dev/SowinskiBraeden/XP-System", "demo": null, "featured": false, - "order": 9, + "order": 10, "tags": ["Web App", "Education Tech", "Gamification"], "path": "./public/content/projects/xp-system.md" } diff --git a/public/content/projects/git-fleet.md b/public/content/projects/git-fleet.md new file mode 100644 index 0000000..b21b321 --- /dev/null +++ b/public/content/projects/git-fleet.md @@ -0,0 +1,43 @@ +--- +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. diff --git a/sitemap.xml b/sitemap.xml index 6cbbd24..59804ed 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -18,6 +18,11 @@ weekly 0.7 + + https://sowinski.dev/entry.html?type=projects&slug=git-fleet + 2026-10-17 + 0.5 + https://sowinski.dev/entry.html?type=projects&slug=schedule-generator-app 2023-08-01