Archived
Draw diverged commits on the spine as a fork
A tip, checkout or committed pin that has diverged from the pin gets its own lane, which joins the main lane at a "base" node: the merge base of the two, with its SHA and subject. Only one diverged commit is drawn as a fork; with two, or without a merge base, the nodes stay in a line with the "diverged" gap. Add Status.Bases, filled by the git provider with `merge-base` for each diverged commit. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -414,3 +414,13 @@ header keeps the progress and `n failed`. `Repo.FetchedAt` is gone.
|
||||
**Amendment (with D25).** A staged pin shows both pins on the spine: `staged`
|
||||
(the index) and `pin` (the superproject's HEAD, `Status.Committed`), so a
|
||||
bump reads as a distance. Before, only the index pin was shown at all.
|
||||
|
||||
**Amendment (with D25): forks.** A diverged tip, checkout or committed pin is
|
||||
drawn as a second lane that joins the main one at a `base` node (SHA +
|
||||
subject of `git merge-base`), instead of a straight line with
|
||||
`diverged ↑n ↓m`. The base was chosen over a bare join mark: where the split
|
||||
happened is what decides between a merge and a rebase. Cost: one
|
||||
`merge-base` and one `log -1` per diverged commit, only when it is diverged.
|
||||
Only one fork is drawn; with two diverged commits (rare) the old line with
|
||||
the diverged gap remains, since nodes on three lanes would need the
|
||||
merge bases between all of them.
|
||||
|
||||
@@ -64,6 +64,8 @@ commit hashes. It doesn't answer the questions users actually have:
|
||||
**tip** and the checkout (**you**) as one line of history, newest on top:
|
||||
a node per commit (SHA + subject) with its roles, and the number of
|
||||
commits between two nodes. Roles on the same commit share a node. A
|
||||
commit that has diverged from the pin is drawn as a fork that joins at
|
||||
the commit where the histories split (`base`). A
|
||||
checkout that differs from the pin is highlighted.
|
||||
- **F22** *(dropped)* The commits between pin and tip are not listed; only
|
||||
their number is shown (F21).
|
||||
|
||||
+16
-4
@@ -32,6 +32,7 @@ in several at once.
|
||||
| `Pin` | `Ref`, `Source`, `Ahead`, `Behind`, `Pushed` |
|
||||
| `Pinned`, `CheckedOut`, `Tip` | Commits (SHA, subject, author, time) |
|
||||
| `Drift` | Checkout compared with the pin: `Ahead` = commits only the checkout has, `Behind` = commits only the pin has |
|
||||
| `Bases` | `Tip`, `Checkout`, `Committed`: `merge-base <pin> <that commit>` for each commit that is diverged from the pin (ahead and behind); nil otherwise or without a common ancestor |
|
||||
| `Committed`, `CommittedDrift` | With a staged pin: the pin in the superproject's HEAD (nil if it is not on disk or the submodule was only added) and how it compares with the staged pin, like `Drift` |
|
||||
| `Changes` | Changed files of the worktree (nil if clean), see below |
|
||||
| `FetchedAt` | Last fetch of the submodule (`FETCH_HEAD` mtime); zero if never |
|
||||
@@ -174,6 +175,7 @@ are local; `<pin>` is the index gitlink.
|
||||
| `Pin.Ref` | rules above; the remote is `origin`, else the first remote |
|
||||
| `Ahead`, `Behind` | `rev-list --left-right --count <pin>...<ref>` |
|
||||
| `Drift` | `rev-list --left-right --count <head>...<pin>`, only if the checkout differs from the pin |
|
||||
| `Bases` | `merge-base <pin> <ref>` / `<head>` / `<committed>`, only when diverged; then `log -1` of it |
|
||||
| `Committed`, `CommittedDrift` | `ls-tree HEAD` gitlink, if it differs from the pin and exists locally; `rev-list --left-right --count <committed>...<pin>` |
|
||||
|
||||
Details:
|
||||
@@ -212,10 +214,20 @@ roles (`pin`, `tip`, `you`; `HEAD` for the superproject). It uses `Pin.Ahead` /
|
||||
*behind* below it; the `Link` between two nodes counts the commits
|
||||
separating them. The count is the distance, so a tip 4 commits ahead
|
||||
of the pin shows `4 commits`, and an adjacent one `1 commit`.
|
||||
- A diverged tip is placed above the pin, a diverged checkout below it,
|
||||
with a diverged `Link` (`Above` and `Below` count the commits only the
|
||||
upper or lower node has). The link between a diverged node and a node other
|
||||
than the pin is unknown (zero `Link`).
|
||||
- A commit that has **diverged** from the pin (tip, checkout or committed
|
||||
pin) is drawn as a **fork** if it is the only one and its merge base is
|
||||
known (`Status.Bases`): it is the first node (`SpineNode.Fork`), with the
|
||||
number of commits down to the base as its `Below`; the main lane follows
|
||||
(pin and the linear nodes), and a `RoleBase` node where the two histories
|
||||
split. Linear nodes between the pin and the base stay on the main lane
|
||||
above it, older ones continue below it, and one that is the base commit
|
||||
shares its node (`you · base`). The pin-to-base distance is the pin's side
|
||||
of the divergence.
|
||||
- Otherwise (two diverged commits, or no merge base) there is no fork: a
|
||||
diverged tip is placed above the pin, a diverged checkout below it, with a
|
||||
diverged `Link` (`Above` and `Below` count the commits only the upper or
|
||||
lower node has). The link between a diverged node and a node other than the
|
||||
pin is unknown (zero `Link`).
|
||||
- With a staged pin the node of `Pinned` (the index) is labelled `staged`, and
|
||||
the committed pin gets its own `pin` node, placed by `CommittedDrift` like
|
||||
the checkout. Both can share nodes with `tip` and `you`.
|
||||
|
||||
+17
-3
@@ -118,9 +118,23 @@ you ● 48005ac Merge branch 'feat/ethercat…
|
||||
sits below it, and the gap above it says `(staged pin moves back)` (blue).
|
||||
- The checkout (`you`) is yellow (label and SHA) when it is on its own node,
|
||||
i.e. off pin. Everything else is the default text color, the gap muted.
|
||||
- A diverged pair shows `┊ diverged ↑n ↓m` (arrows from the lower node's
|
||||
view, like the tree). A real fork is not drawn yet.
|
||||
- The nodes are `●` (`o` with `SUBMARINE_ASCII`), the gap `┊` (`:`).
|
||||
- A commit that has **diverged** from the pin gets its own lane to the right
|
||||
of the main one. The two lanes join at a `base` node, the commit where the
|
||||
histories split; the counts say how many commits each side has since:
|
||||
|
||||
```
|
||||
tip ● e1f2a3b Drop Go 1.21 support
|
||||
┊ 2 commits
|
||||
pin · you ● ┊ c4d5e6f Experimental HTTP/3
|
||||
┊ ┊ 1 commit
|
||||
base ●─╯ a9b8c7d Release 1.9.0
|
||||
```
|
||||
|
||||
Only one diverged commit is drawn as a fork, and only if the base is known.
|
||||
Otherwise the nodes stay in a line and the gap says `┊ diverged ↑n ↓m`
|
||||
(arrows from the lower node's view, like the tree).
|
||||
- The nodes are `●` (`o` with `SUBMARINE_ASCII`), the gap `┊` (`:`), the
|
||||
join `─╯` (`-/`).
|
||||
- A missing submodule has only the pin node (SHA, no subject).
|
||||
|
||||
#### Change preview
|
||||
|
||||
Reference in New Issue
Block a user