git-loom 0.18.0

A Git CLI tool that weaves together multiple feature branches into integration branches
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

git-loom is a Git CLI tool written in Rust (edition 2024) that weaves your branches together. Inspired by tools like jujutsu and Git Butler, it focuses on making integration branches seamless by weaving together multiple feature branches.

### Core Concepts

- **Integration branch**: A branch that merges multiple feature branches together, allowing you to work on and test several features simultaneously.
- **Feature branches**: Independent branches that are combined into the integration branch and can be managed (reordered, amended, split) without leaving the integration context.

### Key Features (planned/in progress)

- **Enhanced git log**: A nicer, more readable log output showing the relationship between integration and feature branches.
- **Easy amending**: Amend any commit in your branch stack, not just the latest one.
- **Commit mobility**: Move commits between branches or reorder them within a branch.
- **Branch creation**: Quickly create and manage feature branches from the integration branch.
- **Branch weaving**: Merge/unmerge feature branches into/from the integration branch.

### Architecture

- Entry point: `src/main.rs` — CLI parsing via `clap`, dispatches to subcommands.
- `src/status.rs` — Branch-aware commit graph display.
- `src/shortid.rs` — Compact human-friendly identifiers for branches, commits, and files.
- `src/show.rs` — Show commit details (like `git show`) using short IDs.
- `src/reword.rs` — Commit message editing / branch renaming via short IDs.
- `src/init.rs` — Initialize a new integration branch tracking a remote upstream.
- `src/branch/` — Branch management (subcommands: new, merge, unmerge).
- `src/commit.rs` — Commit to feature branches from the integration branch.
- `src/drop.rs` — Drop commits or branches from history, with automatic unweaving.
- `src/fold.rs` — Fold: amend files into commits, fixup commits, move commits between branches.
- `src/absorb.rs` — Absorb: auto-distribute working tree changes into the commits that last touched the affected lines.
- `src/push.rs` — Push a feature branch to remote (plain, GitHub, Gerrit auto-detection).
- `src/weave.rs` — Weave: structured graph model for integration topology, rebase todo generation, and execution.
- `src/update.rs` — Pull-rebase the integration branch and update submodules.
- `src/graph.rs` — Graph rendering logic for the status output.
- `src/git.rs` — Git abstraction layer (uses `git2` crate).
- `src/git_commands/` — Lower-level Git operations split by domain:
  - `git_branch.rs`, `git_commit.rs`, `git_merge.rs`, `git_rebase.rs`
- `src/test_helpers.rs` — Shared test utilities (temp repos, etc.).
- Tests live alongside their modules as `*_test.rs` sibling files.

### Specs

The `specs/` directory contains detailed design documents that describe each feature's behavior, edge cases, and expected output. **Always consult the relevant spec before implementing or modifying a feature.**

| Spec | Feature |
|------|---------|
| `specs/001-status.md` | Branch-aware status / commit graph display |
| `specs/002-shortid.md` | Short ID generation and collision resolution |
| `specs/003-reword.md` | Commit reword / branch rename via short IDs |
| `specs/004-weave.md` | Weave: structured graph model for topology-aware rebase |
| `specs/005-branch.md` | Branch creation and weaving into integration branches |
| `specs/006-commit.md` | Commit to feature branches from the integration branch |
| `specs/007-fold.md` | Fold: amend files, fixup commits, move commits between branches; hunk-level fold with `-p` |
| `specs/008-drop.md` | Drop commits or branches from history |
| `specs/009-init.md` | Initialize a new integration branch tracking a remote |
| `specs/010-update.md` | Pull-rebase integration branch and update submodules |
| `specs/011-push.md` | Push a feature branch to remote (plain, GitHub, Gerrit) |
| `specs/012-absorb.md` | Absorb: auto-distribute changes into originating commits |
| `specs/013-split.md` | Split a commit into two commits by file or by hunk (`-p`) |
| `specs/014-continue-abort.md` | Continue or abort a paused loom operation |
| `specs/015-swap.md` | Swap two commits or two branch sections |
| `specs/016-diff.md` | Diff: short-ID–aware wrapper around git diff |
| `specs/017-switch.md` | Switch to any branch for testing without weaving |

## Build & Run Commands

- **Build:** `cargo build`
- **Run:** `cargo run`
- **Test:** `cargo test`
- **Run single test:** `cargo test <test_name>`
- **Lint:** `cargo clippy`
- **Format:** `cargo fmt`
- **Check (fast compile check):** `cargo check`

## Non-Negotiable: Never Lose User Data

git-loom must never discard user data — staged changes, working tree changes, or uncommitted work — as a side effect of any operation, including conflict resolution, abort, or continue flows.

**The abort architecture:** `loom abort` calls `git rebase --abort`, which already restores HEAD, all branch refs (via `--update-refs`), and any autostashed working-tree changes. Extra cleanup beyond that is driven entirely by the `Rollback` struct saved in `LoomState` — `Rollback::apply_abort()` acts on whichever fields are populated:

- `reset_mixed_to``reset --mixed` to undo a pre-rebase commit (used by `commit`)
- `reset_hard_to``reset --hard` to undo pre-rebase commits (used by `absorb`: `git rebase --abort` restores HEAD to after the fixup commits, not to the original pre-absorb HEAD)
- `delete_branches` → delete temp branches (used by `commit` and `fold FilesIntoCommit`/`CommitIntoCommit`)
- `saved_staged_patch` → re-stage changes that were saved aside (used by `commit`, `absorb`, `fold FilesIntoCommit`)
- `saved_worktree_patch` → re-apply working-tree changes (used by `absorb`)

**Required pattern** for any new resumable command (one that calls `weave::run_rebase`):

1. Populate the appropriate `Rollback` fields before saving `LoomState`
2. Register the command name in `transaction::dispatch_after_continue`
3. There is no `dispatch_after_abort` — abort is handled automatically by `Rollback::apply_abort()`

## Error Reporting Convention

Git command failures (via `run_git`/`run_git_stdout`) log stderr to the trace only — do **not** include stderr in the `bail!` error message. The top-level error handler in `main.rs` already appends a hint to run `loom trace`. Never add stderr to user-facing error messages from git subprocess wrappers.

## Non-Negotiable: After Every Code Change

After editing any code, you **must** run the following before considering the task done:

1. `cargo fmt` — format all code
2. `cargo test` — all tests must pass