From 2e5037389caca7d187d94de9848b30b736eedffb Mon Sep 17 00:00:00 2001 From: Local Dev Date: Mon, 31 Aug 2026 14:50:59 +0200 Subject: [PATCH] =?UTF-8?q?tools(hephaestus):=20add=20push-split.sh=20help?= =?UTF-8?q?er=20for=20the=20monorepo=20=E2=86=92=20splits=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since silentmode/silentmode was deleted and each project now lives in its own repo, cross-cutting commits made in the local working copy need to be routed per-project via git-subtree-split. Rather than remember the incantation, wrap it: scripts/push-split.sh Hephaestus # → 'hephaestus' remote scripts/push-split.sh TheseusNavigator # → 'theseus' (Navigator suffix stripped) scripts/push-split.sh AriadneResolver # → 'ariadne' (Resolver suffix stripped) scripts/push-split.sh site-sirius-x sirius # explicit override for non-matching names Preserves history (uses --branch, not --squash), pushes to :master, cleans up the ephemeral branch on exit. --- scripts/push-split.sh | 60 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 scripts/push-split.sh diff --git a/scripts/push-split.sh b/scripts/push-split.sh new file mode 100644 index 0000000..779b8e3 --- /dev/null +++ b/scripts/push-split.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# push-split.sh — push a subdirectory of the monorepo working-copy to its +# matching split repo on Hephaestus, preserving history via git-subtree-split. +# +# Since silentmode/silentmode was deleted and each project lives in its own +# repo on the forge (silentmode/theseus, silentmode/ariadne, silentmode/hephaestus, +# silentmode/sirius, …), cross-cutting commits made in this working copy need to +# be routed to whichever remote corresponds to the touched project. +# +# Usage: +# scripts/push-split.sh [remote-name] +# +# Examples: +# scripts/push-split.sh Hephaestus # → git remote 'hephaestus' +# scripts/push-split.sh TheseusNavigator # → git remote 'theseus' (Navigator suffix stripped) +# scripts/push-split.sh AriadneResolver # → git remote 'ariadne' (Resolver suffix stripped) +# scripts/push-split.sh site-sirius-x sirius # → remote 'sirius' (explicit override) +# +# List of configured remotes: `git remote -v` +# +# Notes: +# - Only ONE prefix per invocation. Cross-cutting changes that touched multiple +# projects need to be run once per touched directory. +# - Uses --branch , pushes, then deletes it. Nothing sticks around. +# - Push target is always :master. Passing --branch was intentional +# over --squash: split history is preserved so file blame on the split repo +# still points at the real commits. +set -euo pipefail + +prefix="${1:?usage: push-split.sh [remote-name]}" + +# Derive a remote name from the directory if not passed. +# Heuristic: lowercase, strip Navigator/Resolver suffix. Otherwise pass explicitly. +default_remote=$(echo "$prefix" | tr '[:upper:]' '[:lower:]' | sed 's/navigator$//; s/resolver$//') +remote="${2:-$default_remote}" + +[ -d "$prefix" ] || { echo "error: no such directory: $prefix" >&2; exit 1; } +git remote get-url "$remote" >/dev/null 2>&1 || { + echo "error: no git remote named '$remote'." >&2 + echo "available remotes: $(git remote | paste -sd ' ' -)" >&2 + echo "pass an explicit remote name as the 2nd arg." >&2 + exit 1 +} + +# Uncommitted changes get carried into the split — usually not what you want. +# Warn (but don't block; sometimes you know what you're doing). +if ! git diff --quiet HEAD -- "$prefix" 2>/dev/null; then + echo "warning: $prefix has uncommitted changes — those will NOT be included in the split." >&2 +fi + +branch="_push_${remote}_$$" +trap 'git branch -D "$branch" >/dev/null 2>&1 || true' EXIT + +echo "→ splitting $prefix/ into ephemeral branch $branch …" +git subtree split --prefix="$prefix" HEAD -b "$branch" >/dev/null + +echo "→ pushing $branch → $remote:master …" +git push "$remote" "$branch:master" + +echo "✓ done — see https://code.silentmode.st/silentmode/$remote"