The ref of a pin was the closest branch containing it, so a pin on a feature branch looked like a perfect one, and the ref changed with the branch checked out in the submodule. Split it in two: - Pin.Target is the branch the pin should be on: `branch =` of .gitmodules (none if it does not exist locally), else the remote's default branch. - Pin.Ref is shown: the target if the pin is on it, else the branch containing the pin with the fewest commits after it. A tie goes to the upstream of the checked-out branch, then to the first name; no branch is a favorite. A pushed pin that is not on its target is `off target`, a new issue at the new level Info (blue), counted in the header and below collapsed rows. The spine shows the target's tip, labelled with its branch name, so the distance from it is visible; a diverged one is the fork. The role words in a spine label are styled separately and `you` is bold. Add Status.TargetTip, TargetDrift and Bases.Target, Pin.Target and Pin.Branches; drop RefSource.IsTarget. The detail pane's label column is 11 wide for the word `off target`. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
submarine — documentation
submarine is a terminal UI for git repositories with many (recursively nested)
submodules. It shows the submodules, as a collapsible tree (plus the state
of the superproject itself in the header), and
describes each pin as a branch plus distance (origin/main ↓1) instead of a
bare commit hash.
Documents
| Document | Contents |
|---|---|
| requirements.md | What the tool must do: functional and non-functional requirements |
| state-model.md | How a submodule's state is determined, summarized into issues, and how pins are resolved to refs |
| ux-guide.md | Layout, attention hierarchy, colors, wording, navigation and key bindings |
| architecture.md | Package layout, the provider boundary, async loading, testing |
| actions.md | the write actions restore and switch branch (done) and stage pin (draft) |
| decisions.md | Decision log with rationale (ADR style) |
Install
curl -fsSL https://git.simon-franken.de/simonfranken/submarine/raw/branch/main/install.sh | sh
Installs submarine and the alias sub (linux/macOS, amd64/arm64) to
~/.local/bin. Update with submarine update. Maintainers publish with
GITEA_TOKEN=… make release (see architecture).
Status
Prototype. The UI is complete for browsing. It reads real repositories
through a git provider (internal/submodule/git): submarine [dir]. It
fetches only when asked (f) and follows changes made in other shells. submarine --mock shows
the built-in mock data (internal/submodule/mock). ! shows only
submodules with problems. x restores the selection and b switches its
branch (actions.md); stage pin is drafted there.
Next steps, roughly in order:
- Stage pin, see actions.md. (Restore and switch branch are done.)
- (done) "Problems only" (
!) view, reusing the tree's filter.