Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions docs/src/commands/status.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ The status displays a branch-aware commit graph using UTF-8 box-drawing characte
│ ⁕ untracked.txt
│╭─ fb [feature-b] ✓
│● mqt Fix bug in feature B d0472f9
│● pkz Start feature B 7a067a9
│● mqt d0472f9 Fix bug in feature B
│● pkz 7a067a9 Start feature B
├╯
│╭─ fa [feature-a] ↑
│● rsv Add feature A 2ee61e1
│● rsv 2ee61e1 Add feature A
├╯
● ff1b247 (upstream) [origin/main] Initial commit
Expand Down Expand Up @@ -81,7 +81,7 @@ The graph is rendered top-to-bottom with these sections:

Each branch, commit, and file in the output is assigned a short ID — a compact identifier you can use with other *git-loom* commands. What you see in the status is what you type.

A commit's short ID comes first on its line, in a fixed column, with the abbreviated hash at the end of the line. Commits that carry a `Change-Id` trailer (every commit loom creates, see [`loom.changeId`](../configuration.md#loomchangeid)) get a **persistent** ID made of the letters `k`–`z`, such as `mqt`: it is derived from the Change-Id, not from the hash, so it survives `update`, `fold`, `swap`, `split`, and every other rewrite. Any longer prefix of the ID also works, and so does the full `Change-Id` value. A commit without a Change-Id — made with plain `git commit`, or cherry-picked from elsewhere — falls back to a hex prefix of its hash, such as `3a`, which changes whenever the commit is rewritten.
A commit's short ID comes first on its line, in a fixed column, followed by the abbreviated hash, so ID and hash sit together at the head of the line. Commits that carry a `Change-Id` trailer (every commit loom creates, see [`loom.changeId`](../configuration.md#loomchangeid)) get a **persistent** ID made of the letters `k`–`z`, such as `mqt`: it is derived from the Change-Id, not from the hash, so it survives `update`, `fold`, `swap`, `split`, and every other rewrite. Any longer prefix of the ID also works, and so does the full `Change-Id` value. A commit without a Change-Id — made with plain `git commit`, or cherry-picked from elsewhere — falls back to a hex prefix of its hash, such as `3a`, which changes whenever the commit is rewritten.

IDs are the shortest prefix that tells commits apart. When a new commit happens to share the first letters of an existing one, both IDs grow by a letter and the old shorter form stops resolving, so a stale ID can never point at the wrong commit.

Expand All @@ -95,7 +95,7 @@ git loom status -f

```
│╭─ fa [feature-a]
│● mqt Add feature A 2ee61e1
│● mqt 2ee61e1 Add feature A
│┊ mqt:0 M src/feature.rs
│┊ mqt:1 A tests/feature_test.rs
├╯
Expand All @@ -119,11 +119,11 @@ Each feature branch forks from the integration line independently:

```
│╭─ fb [feature-b]
│● mqt Fix bug in feature B d0472f9
│● mqt d0472f9 Fix bug in feature B
├╯
│╭─ fa [feature-a]
│● rsv Add feature A 2ee61e1
│● rsv 2ee61e1 Add feature A
├╯
```

Expand All @@ -133,12 +133,12 @@ Feature-b is stacked on top of feature-a:

```
│╭─ fb [feature-b]
│● mqt Second commit on feature-b 4e046ab
│● pkz First commit on feature-b 0b85ca7
│● mqt 4e046ab Second commit on feature-b
│● pkz 0b85ca7 First commit on feature-b
││
│├─ fa [feature-a]
│● rsv Second commit on feature-a caa87a9
│● tqn First commit on feature-a 18faee8
│● rsv caa87a9 Second commit on feature-a
│● tqn 18faee8 First commit on feature-a
├╯
```

Expand All @@ -149,7 +149,7 @@ Multiple branches pointing to the same commit:
```
│╭─ fv [feature-a-v2]
│├─ fa [feature-a]
│● rsv Add feature A 2ee61e1
│● rsv 2ee61e1 Add feature A
├╯
```

Expand All @@ -158,7 +158,7 @@ Multiple branches pointing to the same commit:
When upstream has new commits beyond the common base:

```
● mqt Fix typo abc1234
● mqt abc1234 Fix typo
│● [origin/main] ⏫ 3 new commits
├╯ 204e309 (common base) 2025-07-06 Merge pull request #10
Expand Down
4 changes: 2 additions & 2 deletions docs/src/guides/amending.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ You realize the login form is missing a CSRF token. You fix `src/auth.rs` and ch
│ M src/auth.rs
│╭─ fa [feature-auth]
│● pkz add password validation 81356bf
│● mqt add login form a337eda
│● pkz 81356bf add password validation
│● mqt a337eda add login form
├╯
● a1b2c3d (upstream) [origin/main] Latest upstream commit
Expand Down
6 changes: 3 additions & 3 deletions docs/src/guides/fixup.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ You have two commits on `feature-auth` and realize that `pkz` ("add password val

```
│╭─ fa [feature-auth]
│● pkz add password validation 2b48f49
│● mqt add login form bf7e5af
│● pkz 2b48f49 add password validation
│● mqt bf7e5af add login form
├╯
● a1b2c3d (upstream) [origin/main] Latest upstream commit
Expand All @@ -21,7 +21,7 @@ Commit `pkz` disappears from history and its changes are absorbed into `mqt`:

```
│╭─ fa [feature-auth]
│● mqt add login form 9dff7bd
│● mqt 9dff7bd add login form
├╯
● a1b2c3d (upstream) [origin/main] Latest upstream commit
Expand Down
12 changes: 6 additions & 6 deletions docs/src/guides/moving-commits.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ You committed a logging helper to `feature-auth` by mistake — it belongs in `f

```
│╭─ fd [feature-dashboard]
│● rsv add dashboard layout 24a86e6
│● rsv 24a86e6 add dashboard layout
├╯
│╭─ fa [feature-auth]
│● tqn add logging helper 6395f01
│● mqt add login form 64518a4
│● tqn 6395f01 add logging helper
│● mqt 64518a4 add login form
├╯
● a1b2c3d (upstream) [origin/main] Latest upstream commit
Expand All @@ -25,12 +25,12 @@ Commit `tqn` is removed from `feature-auth` and appended to `feature-dashboard`:

```
│╭─ fd [feature-dashboard]
│● tqn add logging helper db04256
│● rsv add dashboard layout 24a86e6
│● tqn db04256 add logging helper
│● rsv 24a86e6 add dashboard layout
├╯
│╭─ fa [feature-auth]
│● mqt add login form 64518a4
│● mqt 64518a4 add login form
├╯
● a1b2c3d (upstream) [origin/main] Latest upstream commit
Expand Down
8 changes: 4 additions & 4 deletions docs/src/guides/moving-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ $ git loom status -f

```
│╭─ fd [feature-dashboard]
│● rsv add dashboard layout 147aa31
│● rsv 147aa31 add dashboard layout
│┊ rsv:0 A src/dashboard.rs
│┊ rsv:1 A templates/dashboard.html
├╯
│╭─ fa [feature-auth]
│● mqt add login form c32bc09
│● mqt c32bc09 add login form
│┊ mqt:0 M src/auth.rs
│┊ mqt:1 A templates/login.html
├╯
Expand All @@ -37,14 +37,14 @@ The file's changes are removed from `mqt` and applied to `rsv`:

```
│╭─ fd [feature-dashboard]
│● rsv add dashboard layout a3b2ef8
│● rsv a3b2ef8 add dashboard layout
│┊ rsv:0 A src/dashboard.rs
│┊ rsv:1 A templates/dashboard.html
│┊ rsv:2 A templates/login.html
├╯
│╭─ fa [feature-auth]
│● mqt add login form cb15064
│● mqt cb15064 add login form
│┊ mqt:0 M src/auth.rs
├╯
Expand Down
6 changes: 3 additions & 3 deletions docs/src/guides/splitting.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ git loom status -f mqt

```
│╭─ fa [feature-auth]
│● mqt add login form 291658f
│● mqt 291658f add login form
│┊ mqt:0 A src/auth.rs
│┊ mqt:1 A src/validation.rs
│┊ mqt:2 A templates/login.html
Expand All @@ -31,8 +31,8 @@ Select the files for the **first** commit — the remaining files stay in the **

```
│╭─ fa [feature-auth]
│● mqt add login form 5e1a9c2
│● wsl add validation helpers 8c2b2fa
│● mqt 5e1a9c2 add login form
│● wsl 8c2b2fa add validation helpers
├╯
● a1b2c3d (upstream) [origin/main] Latest upstream commit
Expand Down
22 changes: 11 additions & 11 deletions docs/src/guides/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Check the status:

```
│╭─ fa [feature-auth]
│● mqt add login form 711d082
│● mqt 711d082 add login form
├╯
● a1b2c3d (upstream) [origin/main] Latest upstream commit
Expand All @@ -68,8 +68,8 @@ Notice you can use the short ID `fa` instead of the full branch name. The status

```
│╭─ fa [feature-auth]
│● pkz add password validation 4f825d2
│● mqt add login form 711d082
│● pkz 4f825d2 add password validation
│● mqt 711d082 add login form
├╯
● a1b2c3d (upstream) [origin/main] Latest upstream commit
Expand All @@ -85,8 +85,8 @@ While `feature-auth` is in progress, you want to start on a dashboard. You creat
│ ⁕ templates/dashboard.html
│╭─ fa [feature-auth]
│● pkz add password validation 4f825d2
│● mqt add login form 711d082
│● pkz 4f825d2 add password validation
│● mqt 711d082 add login form
├╯
● a1b2c3d (upstream) [origin/main] Latest upstream commit
Expand All @@ -100,12 +100,12 @@ git loom commit -b feature-dashboard -m "add dashboard layout" zz

```
│╭─ fd [feature-dashboard]
│● rsv add dashboard layout 7a5bb0b
│● rsv 7a5bb0b add dashboard layout
├╯
│╭─ fa [feature-auth]
│● pkz add password validation 4f825d2
│● mqt add login form 711d082
│● pkz 4f825d2 add password validation
│● mqt 711d082 add login form
├╯
● a1b2c3d (upstream) [origin/main] Latest upstream commit
Expand All @@ -125,12 +125,12 @@ This fetches upstream changes, rebases your integration branch (including all wo

```
│╭─ fd [feature-dashboard]
│● rsv add dashboard layout 8f74d1c
│● rsv 8f74d1c add dashboard layout
├╯
│╭─ fa [feature-auth]
│● pkz add password validation 660e970
│● mqt add login form 885cc0c
│● pkz 660e970 add password validation
│● mqt 885cc0c add login form
├╯
● b2c3d4e (upstream) [origin/main] Teammate's latest commit
Expand Down
10 changes: 5 additions & 5 deletions docs/src/guides/uncommitting.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ $ git loom status -f

```
│╭─ fa [feature-auth]
│● pkz add password validation 92b8427
│● pkz 92b8427 add password validation
│┊ pkz:0 M src/auth.rs
│● mqt add login form bae0b72
│● mqt bae0b72 add login form
│┊ mqt:0 A src/auth.rs
│┊ mqt:1 A templates/login.html
├╯
Expand All @@ -33,7 +33,7 @@ The commit is removed from history and its changes appear as unstaged modificati
│ M src/auth.rs
│╭─ fa [feature-auth]
│● mqt add login form bae0b72
│● mqt bae0b72 add login form
│┊ mqt:0 A src/auth.rs
│┊ mqt:1 A templates/login.html
├╯
Expand All @@ -56,9 +56,9 @@ The file is removed from the commit and appears as an untracked file in the work
│ ⁕ templates/login.html
│╭─ fa [feature-auth]
│● pkz add password validation 2a660a7
│● pkz 2a660a7 add password validation
│┊ pkz:0 M src/auth.rs
│● mqt add login form 4afdd0c
│● mqt 4afdd0c add login form
│┊ mqt:0 A src/auth.rs
├╯
Expand Down
8 changes: 4 additions & 4 deletions specs/001-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Output runs top-to-bottom in this order:
4. Upstream or common-base marker.
5. Optional context commits.

Commits use `<short-id> <commit-message-first-line> <short-hash>`: the commit's short ID (Spec 002) in the fixed column defined by Spec 002, then the subject, then the abbreviated hash at the end of the line. Hashes are unique abbreviations respecting `core.abbrev`. Merge commits have no special treatment.
Commits use `<short-id> <short-hash> <commit-message-first-line>`: the commit's short ID (Spec 002) in the fixed column defined by Spec 002, then the abbreviated hash, then the subject. Hashes are unique abbreviations respecting `core.abbrev`. Merge commits have no special treatment.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

| Symbol | Normative meaning |
| --- | --- |
Expand Down Expand Up @@ -81,9 +81,9 @@ Minimal topology examples:

```text
│╭─ [feature-b] │╭─ [feature-a-v2] │╭─ [feature-stale]
│● pkz B bbbbbbb │├─ [feature-a] ├╯
│├─ [feature-a] │● mqt A aaaaaaa │
│● mqt A aaaaaaa ├╯ ● base (upstream) [origin/main]
│● pkz bbbbbbb B │├─ [feature-a] ├╯
│├─ [feature-a] │● mqt aaaaaaa A
│● mqt aaaaaaa A ├╯ ● base (upstream) [origin/main]
├╯
```

Expand Down
8 changes: 4 additions & 4 deletions specs/002-shortid.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ IDs use blue underline (`COLOR_SHORTID`). Placement is:
│ ma M src/main.rs
│╭─ fa [feature-a]
│● mqt Fix bug d072f9a
│● 3a Cherry-picked 3a6f21c
│● mqt d072f9a Fix bug
│● 3a 3a6f21c Cherry-picked
├╯
```

A commit line is `<id> <subject> <abbreviated hash>`: the ID first, then the subject, then the dimmed abbreviated hash at the end of the line. ANSI-stripped output still contains the full abbreviated hash. The upstream/common-base marker gets no ID.
A commit line is `<id> <abbreviated hash> <subject>`: the ID first, then the dimmed abbreviated hash, then the subject, so ID and hash sit together where both are easy to copy. ANSI-stripped output still contains the full abbreviated hash. The upstream/common-base marker gets no ID.

The ID occupies a fixed four-column field followed by one space, so the subject column does not move between invocations when a new commit lengthens an ID. An ID wider than the field (five letters, or a numeric-suffix fallback) keeps its single trailing space and shifts only its own line. The interactive TUI uses the same column but shows no hash.
The ID occupies a fixed four-column field followed by one space, so the hash and subject columns do not move between invocations when a new commit lengthens an ID. An ID wider than the field (five letters, or a numeric-suffix fallback) keeps its single trailing space and shifts only its own line. The interactive TUI uses the same column but shows no hash.

## Persistent commit identity

Expand Down
7 changes: 4 additions & 3 deletions src/core/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,8 @@ pub(crate) fn is_stacked_with_next(sections: &[Section], idx: usize) -> bool {
/// right rather than the whole tree.
const COMMIT_ID_SLOT: usize = 4;

/// Spaces between a commit short ID and the subject: always at least one.
/// Spaces between a commit short ID and the hash that follows it: always at
/// least one.
pub(crate) fn id_pad(sid: &str) -> String {
" ".repeat(COMMIT_ID_SLOT.saturating_sub(sid.chars().count()) + 1)
}
Expand Down Expand Up @@ -726,8 +727,8 @@ fn render_branch(
"●".color(dot_color),
sid.color(theme.shortid).underline(),
id_pad(sid),
commit.short_id.color(theme.dim),
commit.message,
commit.short_id.color(theme.dim)
)
.unwrap();
for (i, file) in commit.files.iter().enumerate() {
Expand Down Expand Up @@ -771,8 +772,8 @@ fn render_loose(
"●".color(theme.graph),
sid.color(theme.shortid).underline(),
id_pad(sid),
commit.short_id.color(theme.dim),
commit.message,
commit.short_id.color(theme.dim)
)
.unwrap();
for (i, file) in commit.files.iter().enumerate() {
Expand Down
Loading
Loading