Skip to content

Show branch topology in revision history graph#10

Open
JohnRDOrazio wants to merge 6 commits intomainfrom
feature/branch-topology-graph
Open

Show branch topology in revision history graph#10
JohnRDOrazio wants to merge 6 commits intomainfrom
feature/branch-topology-graph

Conversation

@JohnRDOrazio
Copy link
Member

@JohnRDOrazio JohnRDOrazio commented Mar 10, 2026

Summary

  • Use backend refs map to assign feature branch commits to separate lanes in the git graph, with branch name badges (blue, with GitBranch icon)
  • Fix lane assignment so hints from refs take priority over child continuation, ensuring branching is visible even when a feature branch is ahead of main with no divergence
  • Refresh branch data (commits ahead/behind counts) after every commit operation and when the history panel opens, fixing stale BranchBadge/BranchSelector counts

Test plan

  • Open a project on a feature branch, click History — feature branch commits appear on a separate lane with branch labels; main commits on lane 0 with a "main" badge
  • Make a commit on a feature branch — BranchBadge and BranchSelector immediately show updated "+N" count without needing to reload
  • Open History panel — branch selector refreshes to show current ahead/behind counts
  • Verify npm run type-check and npm run lint pass cleanly

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Branch references shown in revision history as per-commit badges.
    • Git graph now uses branch-aware layout and respects the default branch.
    • Revision API responses include branch refs so the UI displays up-to-date branch info.
  • Refactor

    • Branch data now refreshes automatically after saves, updates, and deletes for more immediate consistency.

Closes #8

@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

Adds branch-ref support across the revision stack: API responses may include refs, BranchContext exposes an imperative refresh handle, the graph builder assigns lanes using branch hints and vertices carry refs, and UI components load, refresh, and render branch badges and updated graphs.

Changes

Cohort / File(s) Summary
Branch context & provider
lib/context/BranchContext.tsx
Exported BranchProviderHandle type; BranchProviderProps now accepts refreshRef?: Ref<BranchProviderHandle>; uses useImperativeHandle to expose refreshBranches() which delegates to internal loadBranches.
Editor wiring
app/projects/[id]/editor/page.tsx
Adds branchRef (ref to BranchProviderHandle), passes refreshRef={branchRef} into BranchProvider, and invokes branchRef.current?.refreshBranches() after save/delete/update flows.
API & types
lib/api/revisions.ts, lib/git-graph/types.ts
RevisionHistoryResponse optionally includes refs?: Record<string,string[]>; GraphVertex gains refs: string[].
Graph builder logic
lib/git-graph/graph-builder.ts
buildGraphLayout signature extended to (commits, refs?, defaultBranch?); vertices initialized with refs; added computeBranchHints and updated lane/color assignment to prefer branch hints while preserving fallback logic.
Graph component
components/revision/GitGraph.tsx
GitGraphProps extended with refs? and defaultBranch?; buildGraphLayout invocation and useMemo now include refs and defaultBranch.
Revision history UI
components/revision/RevisionHistoryPanel.tsx
Loads/stores branch refs from API and useBranch().loadBranches() into local refs state; passes refs/defaultBranch to GitGraph and renders per-commit branch badges.
Manifest / package
manifest_file, package.json
Minor manifest/package adjustments (lines changed: +1/-0).

Sequence Diagram(s)

sequenceDiagram
    participant Editor as Editor Page
    participant BranchProv as BranchProvider
    participant API as API Layer
    participant UI as RevisionHistoryPanel

    Editor->>BranchProv: mount with refreshRef
    BranchProv->>BranchProv: expose refreshBranches via useImperativeHandle
    Editor->>API: save / delete / update project
    API-->>Editor: operation response
    Editor->>BranchProv: refreshRef.current?.refreshBranches()
    BranchProv->>API: loadBranches()
    API-->>BranchProv: branches data
    BranchProv-->>UI: context updates (branch data)
Loading
sequenceDiagram
    participant UI as RevisionHistoryPanel
    participant API as API Layer
    participant Context as BranchContext
    participant GraphBuilder as GitGraph Builder
    participant Graph as GitGraph Component

    UI->>API: loadHistory() (commits + optional refs)
    UI->>Context: loadBranches()
    Context->>API: fetch branches
    API-->>Context: branches array
    UI->>GraphBuilder: buildGraphLayout(commits, refs, defaultBranch)
    GraphBuilder->>GraphBuilder: computeBranchHints(refs, defaultBranch)
    GraphBuilder->>GraphBuilder: assign lanes/colors using hints
    GraphBuilder-->>UI: GraphLayout with branch-aware positions
    UI->>Graph: render commits with branch badges (refs, defaultBranch)
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through refs and lane-lined tracks,

Branch names tucked into every hash and crack.
I nudged the provider, a twitch, a cheer,
Refresh returned branches — the graph reappeared! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately summarizes the main objective: displaying branch topology in the revision history graph.
Linked Issues check ✅ Passed All PR changes address the core objectives of issue #8: restoring visual branch topology by adding refs support throughout the stack, updating graph layout computation, and displaying branch badges in the revision history panel.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the stated objective: adding branch topology visualization. No unrelated modifications to unrelated components or features are present.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/branch-topology-graph

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@JohnRDOrazio
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/revision/RevisionHistoryPanel.tsx`:
- Around line 196-205: The badge strip is wrapping and pushing the text column
out of sync; when rendering refs?.[commit.hash]?.map((ref) => ...) around the
GitBranch badge, make the badge row single-line and truncated by adding no-wrap
and overflow truncation classes to the span (e.g. add whitespace-nowrap,
overflow-hidden, text-ellipsis/truncate and a sensible max-width or max-w-[...]
class) so long branch names don’t wrap; keep the GitBranch icon and ref text but
ensure each badge is constrained (or alternatively constrain the parent
container for all badges) so the row stays fixed-height and aligns with the
graph cell.

In `@lib/context/BranchContext.tsx`:
- Around line 61-70: The BranchProvider currently exposes an imperative
refreshRef (BranchProviderHandle.refreshBranches) and uses loadBranches; replace
this with a React Query-backed query for branches keyed by projectId and remove
refreshRef/refreshBranches from BranchProviderProps/BranchProviderHandle,
switching consumers to the query's data and refetch functions; implement any
write operations as React Query mutations that call
queryClient.invalidateQueries or mutation.onSuccess to refresh the branches
cache, and update callers (the editor and history panel) to either read the
branches from useQuery or call queryClient.refetchQueries/useQueryClient instead
of calling loadBranches or branchRef.current?.refreshBranches().

In `@lib/git-graph/graph-builder.ts`:
- Around line 183-185: The color assignment incorrectly allows the first side
branch to receive color 0 because nextColor is initialized to 0; update the
logic in graph-builder.ts (around the assignedColor/hintedLane handling and the
nextColor initialization) to reserve color 0 for lane 0 — either initialize
nextColor to 1 where it’s declared or ensure the branch that sets assignedColor
for hintedLane !== 0 uses nextColor starting at 1 (and then increments nextColor
afterwards); refer to the variables assignedColor, hintedLane, and nextColor
when making the change.
- Around line 167-171: The forEach callbacks are returning the Set via the
implicit-expression form (triggering useIterableCallbackReturn); change the
callbacks that iterate activeLanes and the other forEach at the later location
to use block bodies and call usedLanes.add(lane); (and the analogous add call)
as statements. Locate the forEach that reads activeLanes and the second forEach
around the code referencing hintedLane and replace the arrow expressions with
block-bodied arrow functions so Set.add(...) is a statement rather than an
implicit return.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 11f84d96-c734-4cba-b909-a989ba5cf677

📥 Commits

Reviewing files that changed from the base of the PR and between d258636 and d3fb68f.

📒 Files selected for processing (7)
  • app/projects/[id]/editor/page.tsx
  • components/revision/GitGraph.tsx
  • components/revision/RevisionHistoryPanel.tsx
  • lib/api/revisions.ts
  • lib/context/BranchContext.tsx
  • lib/git-graph/graph-builder.ts
  • lib/git-graph/types.ts

Comment on lines +61 to 70
export interface BranchProviderHandle {
refreshBranches: () => Promise<void>;
}

interface BranchProviderProps {
projectId: string;
accessToken?: string;
initialBranch?: string;
refreshRef?: Ref<BranchProviderHandle>;
children: ReactNode;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Expect either an existing branch-focused query/invalidation path,
# or confirmation that branch state is still fetched imperatively.
rg -n -g '*.ts' -g '*.tsx' 'branchesApi\.list|loadBranches\(' app components lib
rg -n -g '*.ts' -g '*.tsx' 'useQuery|useMutation|invalidateQueries|queryClient' app components lib

Repository: CatholicOS/ontokit-web

Length of output: 1345


🏁 Script executed:

#!/bin/bash
# Read the BranchContext.tsx file to verify the implementation
cat -n lib/context/BranchContext.tsx | head -250

Repository: CatholicOS/ontokit-web

Length of output: 8873


🏁 Script executed:

#!/bin/bash
# Find where refreshRef/branchRef is used
rg -n 'refreshRef|branchRef' app components lib --type ts --type tsx -A 2 -B 2

Repository: CatholicOS/ontokit-web

Length of output: 93


🏁 Script executed:

#!/bin/bash
# Find where refreshRef/branchRef is used
rg -n 'refreshRef|branchRef' -g '*.ts' -g '*.tsx' app components lib -A 2 -B 2

Repository: CatholicOS/ontokit-web

Length of output: 3715


🏁 Script executed:

#!/bin/bash
# Check RevisionHistoryPanel.tsx for loadBranches usage
cat -n components/revision/RevisionHistoryPanel.tsx | sed -n '60,80p'

Repository: CatholicOS/ontokit-web

Length of output: 676


Migrate branch state to React Query instead of using imperative refreshRef.

The editor calls branchRef.current?.refreshBranches() after writes while the history panel separately calls loadBranches() on open. This duplicates server-state management logic. Using a React Query query with mutation invalidation would handle deduping, cancellation, and cache freshness automatically, aligning with the project guideline to use React Query for server state management.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/context/BranchContext.tsx` around lines 61 - 70, The BranchProvider
currently exposes an imperative refreshRef
(BranchProviderHandle.refreshBranches) and uses loadBranches; replace this with
a React Query-backed query for branches keyed by projectId and remove
refreshRef/refreshBranches from BranchProviderProps/BranchProviderHandle,
switching consumers to the query's data and refetch functions; implement any
write operations as React Query mutations that call
queryClient.invalidateQueries or mutation.onSuccess to refresh the branches
cache, and update callers (the editor and history panel) to either read the
branches from useQuery or call queryClient.refetchQueries/useQueryClient instead
of calling loadBranches or branchRef.current?.refreshBranches().

…nts after commits

Use the refs map from the backend to visually separate branches onto different
lanes in the git graph. Feature branch commits now appear on a separate lane
with branch name badges, while main commits stay on lane 0.

Also fix stale branch data (commits ahead/behind) by refreshing branch info
after every commit operation and when the history panel opens.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@JohnRDOrazio JohnRDOrazio force-pushed the feature/branch-topology-graph branch from d3fb68f to 3bdf914 Compare March 10, 2026 16:43
@JohnRDOrazio JohnRDOrazio changed the base branch from feature/explicit-save-button to main March 10, 2026 16:43
JohnRDOrazio and others added 2 commits March 10, 2026 17:49
Wrap branch ref badges in a non-wrapping container with overflow hidden
to prevent long branch names from breaking row alignment in the git graph.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use block bodies in forEach callbacks to avoid returning Set.add() values
(lint: useIterableCallbackReturn). Initialize nextColor to 1 so the main
lane always gets color 0 and side branches start at color 1.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (3)
lib/git-graph/graph-builder.ts (2)

155-156: ⚠️ Potential issue | 🟡 Minor

Keep color 0 exclusive to lane 0.

nextColor still starts at 0, so the first hinted side branch on Line 184 renders with the same color as the main lane. The fallback path on Line 216 has the same problem when it allocates lane 0.

Proposed fix
-  let nextColor = 0;
+  let nextColor = 1;
@@
-          assignedColor = hintedLane === 0 ? 0 : nextColor++;
+          assignedColor = hintedLane === 0 ? 0 : nextColor++;
@@
-      assignedColor = nextColor++;
+      assignedColor = assignedLane === 0 ? 0 : nextColor++;

Also applies to: 183-185, 212-216

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/git-graph/graph-builder.ts` around lines 155 - 156, nextColor is
initialized to 0 so the first allocated side branch can get color 0 (same as
main lane); change the allocation logic to keep color 0 reserved for lane 0 by
initializing nextColor = 1 and update any increment/wrap logic that assigns
lanes (places that do nextColor++ / nextColor = (nextColor + 1) % N or fallback
lane search) to skip 0 (e.g., if nextColor becomes 0, advance to 1) so no
allocation ever returns color 0 for hinted/fallback branches.

167-171: ⚠️ Potential issue | 🟠 Major

Fix the forEach callbacks before linting.

Line 171 and Line 210 still use expression-bodied callbacks, so Biome treats them as returning the Set from usedLanes.add(...) and fails useIterableCallbackReturn.

Proposed fix
-      activeLanes.forEach(({ lane }) => usedLanes.add(lane));
+      activeLanes.forEach(({ lane }) => {
+        usedLanes.add(lane);
+      });
@@
-      activeLanes.forEach(({ lane }) => usedLanes.add(lane));
+      activeLanes.forEach(({ lane }) => {
+        usedLanes.add(lane);
+      });

Also applies to: 209-210

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/git-graph/graph-builder.ts` around lines 167 - 171, The forEach callbacks
that call usedLanes.add(...) are using expression-bodied arrows which return the
Set value and trigger the useIterableCallbackReturn lint; change those to
block-bodied callbacks so they don't return a value. Specifically, update
activeLanes.forEach(({ lane }) => usedLanes.add(lane)) to activeLanes.forEach(({
lane }) => { usedLanes.add(lane); }) and make the analogous change to the other
forEach near the hintedLane logic (the second occurrence that also calls
usedLanes.add) so both callbacks use { ... } and no implicit return.
components/revision/RevisionHistoryPanel.tsx (1)

196-205: ⚠️ Potential issue | 🟡 Minor

Constrain the ref badges to one line.

These rows are fixed to ROW_HEIGHT, so long or multiple refs can still wrap here and push the text column out of sync with the graph. Keep the badge strip single-line/truncated, or raise both the row height and graph cell height together.

Proposed fix
-                          {refs?.[commit.hash]?.map((ref) => (
-                            <span
-                              key={ref}
-                              className="inline-flex items-center gap-1 rounded-full bg-blue-100 px-1.5 py-0.5 text-xs font-medium text-blue-700 dark:bg-blue-900/30 dark:text-blue-300"
-                            >
-                              <GitBranch className="h-2.5 w-2.5" />
-                              {ref}
-                            </span>
-                          ))}
+                          {(refs?.[commit.hash] ?? []).length > 0 && (
+                            <div className="mt-0.5 flex min-w-0 items-center gap-1 overflow-hidden whitespace-nowrap">
+                              {(refs?.[commit.hash] ?? []).map((ref) => (
+                                <span
+                                  key={ref}
+                                  title={ref}
+                                  className="inline-flex max-w-[160px] items-center gap-1 rounded-full bg-blue-100 px-1.5 py-0.5 text-xs font-medium text-blue-700 dark:bg-blue-900/30 dark:text-blue-300"
+                                >
+                                  <GitBranch className="h-2.5 w-2.5 shrink-0" />
+                                  <span className="truncate">{ref}</span>
+                                </span>
+                              ))}
+                            </div>
+                          )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/revision/RevisionHistoryPanel.tsx` around lines 196 - 205, The ref
badges can wrap and change row height; wrap the map output in a single-line,
non-wrapping container and make each badge non-shrinking so badges are clipped
instead of wrapping: update the block that renders refs?.[commit.hash]?.map(...)
(the span elements using GitBranch and ref) to be inside a wrapper with CSS
classes enforcing overflow-hidden, whitespace-nowrap, and
text-overflow/ellipses; ensure each badge gets a flex-shrink-0 (or equivalent)
so they stay on one line and excess badges are truncated rather than wrapping.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@components/revision/RevisionHistoryPanel.tsx`:
- Around line 196-205: The ref badges can wrap and change row height; wrap the
map output in a single-line, non-wrapping container and make each badge
non-shrinking so badges are clipped instead of wrapping: update the block that
renders refs?.[commit.hash]?.map(...) (the span elements using GitBranch and
ref) to be inside a wrapper with CSS classes enforcing overflow-hidden,
whitespace-nowrap, and text-overflow/ellipses; ensure each badge gets a
flex-shrink-0 (or equivalent) so they stay on one line and excess badges are
truncated rather than wrapping.

In `@lib/git-graph/graph-builder.ts`:
- Around line 155-156: nextColor is initialized to 0 so the first allocated side
branch can get color 0 (same as main lane); change the allocation logic to keep
color 0 reserved for lane 0 by initializing nextColor = 1 and update any
increment/wrap logic that assigns lanes (places that do nextColor++ / nextColor
= (nextColor + 1) % N or fallback lane search) to skip 0 (e.g., if nextColor
becomes 0, advance to 1) so no allocation ever returns color 0 for
hinted/fallback branches.
- Around line 167-171: The forEach callbacks that call usedLanes.add(...) are
using expression-bodied arrows which return the Set value and trigger the
useIterableCallbackReturn lint; change those to block-bodied callbacks so they
don't return a value. Specifically, update activeLanes.forEach(({ lane }) =>
usedLanes.add(lane)) to activeLanes.forEach(({ lane }) => { usedLanes.add(lane);
}) and make the analogous change to the other forEach near the hintedLane logic
(the second occurrence that also calls usedLanes.add) so both callbacks use {
... } and no implicit return.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 91d32c2b-fe7a-4f33-97dd-d456384614b3

📥 Commits

Reviewing files that changed from the base of the PR and between d3fb68f and 3bdf914.

📒 Files selected for processing (7)
  • app/projects/[id]/editor/page.tsx
  • components/revision/GitGraph.tsx
  • components/revision/RevisionHistoryPanel.tsx
  • lib/api/revisions.ts
  • lib/context/BranchContext.tsx
  • lib/git-graph/graph-builder.ts
  • lib/git-graph/types.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/api/revisions.ts
  • lib/context/BranchContext.tsx

When the fallback lane assignment happens to pick lane 0, use color 0
instead of allocating the next color, keeping main-line commits visually
consistent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/revision/RevisionHistoryPanel.tsx (1)

39-71: 🛠️ Refactor suggestion | 🟠 Major

Move the history/branch loading onto React Query.

This change adds more remote state (refs plus a branch refresh trigger) behind local useState/useEffect, which keeps cache and refetch behavior split across component state and context. Please model the history request as a query and drive refreshes through query invalidation/refetch instead.

As per coding guidelines, "Use React Query (@tanstack/react-query) for server state management".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/revision/RevisionHistoryPanel.tsx` around lines 39 - 71, The
component is managing remote history/refs with local useState and loadHistory;
replace that with a React Query useQuery that calls revisionsApi.getHistory and
returns {commits, refs} keyed by ['revisions', projectId] (remove loadHistory,
setCommits/setRefs, setIsLoading/setError and selected state updates tied to
them), enable the query only when isOpen and projectId are present, and surface
query status/error instead of local flags; keep calling loadBranches() but when
branches refreshes complete (or when defaultBranch changes) trigger the history
refresh by calling useQueryClient().invalidateQueries(['revisions', projectId])
or query.refetch so branch updates drive refetches rather than local effects.
Ensure you reference the existing symbols revisionsApi.getHistory, loadBranches,
loadHistory (remove), commits and refs state (replace), and the query key
['revisions', projectId].
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/git-graph/graph-builder.ts`:
- Around line 130-137: The loop that assigns lane hints (using nextLane, hints,
walk, GraphVertex, vertices, mainLine, and v.id) currently overwrites existing
hints and steals commits from earlier stacked branches; change the walk so it
stops when it encounters a commit that already has a hint instead of rewriting
it (i.e., break the walk if hints.has(walk) is true) — ensure you check hints
before calling hints.set and update the loop condition or add an early-break so
earlier lane assignments are preserved.

---

Outside diff comments:
In `@components/revision/RevisionHistoryPanel.tsx`:
- Around line 39-71: The component is managing remote history/refs with local
useState and loadHistory; replace that with a React Query useQuery that calls
revisionsApi.getHistory and returns {commits, refs} keyed by ['revisions',
projectId] (remove loadHistory, setCommits/setRefs, setIsLoading/setError and
selected state updates tied to them), enable the query only when isOpen and
projectId are present, and surface query status/error instead of local flags;
keep calling loadBranches() but when branches refreshes complete (or when
defaultBranch changes) trigger the history refresh by calling
useQueryClient().invalidateQueries(['revisions', projectId]) or query.refetch so
branch updates drive refetches rather than local effects. Ensure you reference
the existing symbols revisionsApi.getHistory, loadBranches, loadHistory
(remove), commits and refs state (replace), and the query key ['revisions',
projectId].

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eddff8d5-2c95-49a5-96bb-fa643180da3c

📥 Commits

Reviewing files that changed from the base of the PR and between 3bdf914 and 670e9b9.

📒 Files selected for processing (2)
  • components/revision/RevisionHistoryPanel.tsx
  • lib/git-graph/graph-builder.ts

Comment on lines +130 to +137
// Walk first-parents backward until hitting a main-line commit
const lane = nextLane++;
let walk: number | null = v.id;
while (walk !== null && !mainLine.has(walk)) {
hints.set(walk, lane);
const wv: GraphVertex = vertices[walk];
walk =
wv.parentIndices.length > 0 ? wv.parentIndices[0] : null;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Preserve earlier lane hints for stacked branches.

Line 134 overwrites any existing hint on the walked ancestry. If feature/b is branched from feature/a, the later walk steals feature/a's commits and collapses the older branch onto the newer lane. Stop once a commit already has a hint instead of rewriting it.

Proposed fix
-    while (walk !== null && !mainLine.has(walk)) {
+    while (walk !== null && !mainLine.has(walk) && !hints.has(walk)) {
       hints.set(walk, lane);
       const wv: GraphVertex = vertices[walk];
       walk =
         wv.parentIndices.length > 0 ? wv.parentIndices[0] : null;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/git-graph/graph-builder.ts` around lines 130 - 137, The loop that assigns
lane hints (using nextLane, hints, walk, GraphVertex, vertices, mainLine, and
v.id) currently overwrites existing hints and steals commits from earlier
stacked branches; change the walk so it stops when it encounters a commit that
already has a hint instead of rewriting it (i.e., break the walk if
hints.has(walk) is true) — ensure you check hints before calling hints.set and
update the loop condition or add an early-break so earlier lane assignments are
preserved.

@JohnRDOrazio JohnRDOrazio added this to the v0.3.0 milestone Mar 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Git history graph does not show branches since bare repo migration

1 participant