Skip to content

basic head-info #8451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 14, 2025
Merged

basic head-info #8451

merged 7 commits into from
May 14, 2025

Conversation

Byron
Copy link
Collaborator

@Byron Byron commented May 8, 2025

A first implementation of head_info() to provide information about where the user currently is.
It presents the world as a workspace with stacks, even though technically it might not exist.`

Follow-up on #8422.

  • prevent non-workspace cases (or assure that the new system doesn't get to show them)
    • figure out how it knows that one moved away from GitButler workspace
      • operating_mode() is called when the workspace branch changes, which tells the UI it's not on the right branch. So no need to alter the current implementation.
  • heads_info with workspace cases - reflect what's currently possible
    • determine if local commits are integrated
  • research on how to Integrate new heads_info() with current API interface
    • move UI types into ui modules
    • check if current data is sufficient to provide all that's needed to current API
      • get_base_branch_data() (skipped), stacks(), stack_details()
  • implement intermediate V3 versions of these functions
    • stacks_v3()
      • basic test (needs heads-info test setup)
    • branch_details_v3()
    • stack_details_v3()
      • basic test derived from head_info, particularly tests for the push status.
  • make use of stacks_v3 and stack_details_v3() in tauri via feature toggle

Notable changes to the Datamodel

  • Upstream commits can also be integrated. This would happen if the local tracking branch has not caught up to them, and all of them are integrated. This also means that everything local could be unintegrated, but upstream-only commits are integrated, something that can happen if everything is diverged. If both disagree, it's unclear what to do.

Notes for the Reviewer

  • This is a transitory PR that replaces VirtualBranchesToml with the RefMetadata trait to prepare the code to transition to other data stores.
  • The code is clearly transitory while StackId is still a thing - in the new world stacks or stack-segments are referred to by their reference name or by their index in the parent-list of the top-level merge commit (if there is one).
  • Ideally, one the UI will be able to make just one heads_info call, and can consume the data directly (even though it may have been processed to further facilitate consumption).
  • branch_details() already works on references
  • BranchDetails are probably the data structure of choice for the UI, and it's just the question if there is stack information or not.
  • There is no notion of using stacks in branch listings outside of what we are currently looking at, i.e. where HEAD is. Thus, for this we will probably keep using branch details of sort.

Next PR

  • intermediate V3 version of get_base_branch_data().

Follow Up Tasks

  • first non-workspace cases
    • merge commit
    • merge commit stacked
    • stacks and ambiguous stack references (i.e. lots of empty stack segments)

Next PRs

  • head-info, stacks and details API with key scenarios
  • graph-based integration checks with target and remote
  • use hide() in places where merge-commits are used as boundary.
    • This shouldn't be a major problem for simple topologies, but is certainly an issue for more complex ones.
  • integration checking with target
  • integration checking with remote tracking branch

Known Shortcomings (for now)

  • ⚠️ first_parent_only maybe a good simplification for display, but I wonder if there are side-effects like us not seeing commits that could participate in commit-status check.
  • ⚠️ Commit-classification is hacky and undertested right now⚠️
  • One probably wants to show all refs at a position (or indicate there are more)
  • ⚠️ rebase engine needs a way to know which parent to rewrite if there are two parents pointing to the same commit in a starting configuration with two stacks at the same commit. Alternatively, create_commit would have to create a workspace commit, which seems worse than adding a WS commit in the moment there are two stacks.
  • ⚠️ merge conflicts are created from either cherry-picks or normal merges (legacy?), but cherry-pick would need to know that to either choose the auto-resolution. That's OK as long as the 'old' merge-commit isn't run as it would create a semantically different tree-setup in the conflicted commit.
  • ⚠️ commit listing are ambiguous
    • Certain less common but possible branch configuration make ambiguous to assign commits to one branch or another. It won't be super trivial to make this work right.
  • ⚠️Even though Git does not list namespaced references, tig will happily list everything. set reference-format = hide:other fixes this though
  • empty commits aren't specifically highlighted when rebasing, or handled or prevented. The UI could detect that and show them.
  • Moving hunks or files will need multi-branch rebases with merge-commit handling. This can be added to the rebase engine as we know it today. This will also enable worktree-updates.
  • reordering in such a way that only heads a moved and nothing else happens (in terms of commit rewrites) probably wouldn't work yet in but-rebase.
  • Index adjustments (tree to disk index) lack a lot of tests, particularly those for automatic conflict removal.
  • if changes are added to the wrong spot, then they may apply cleanly and yield different results after merging, so the worktree differs from what's in Git. This is where hunk-dependencies/auto-hunk-splitting comes into play.
  • Right now sub-hunks can't be selected as they won't match when it tries to find exact matches. However, that check could be changed to a 'contains' or 'is-included' to allow sub-hunks. Maybe this doesn't naturally work though or do the right thing.
  • Workspace commits with a single branch will get signed if they were signed before. This shouldn't be a real problem, and ideally it will go away soon enough.

For follow-up PRs

In any order (probably)

  • Rebase-engine with insert empty commit (below and above, insert as first parent support)
  • What happens in Git if one rebases non-linear branches? Can it retain the structure?
    • Rebase engine probably has to learn to re-schedule picks (and remember the base, a feature useful for multi-stacks as well, which then wouldn't need a special case anymore)
  • move file out of commit into worktree (uncommit something)
  • per-hunk exclusion if hunk didn't match (right now it rejects the whole file)
  • run hooks on an index created from the tree that would be committed.
  • move hunks from one commit into another

Out of scope

  • hunk-dependencies
    • These should be added once the commit-engine is feature-complete, the idea is that the UI can function well enough without them as a baseline.
  • atomic object writes
    • In theory, new objects should only be written to disk if they actually end up in a tree. For instance, if a change is rejected, the object associated with it shouldn't be in the object database.
    • However, even though implementing this with the in-memory object feature is very possible, it feels like an optimization for another day. In general, I really think only objects that end up in a tree should actually be written, so that the implementation doesn't have to rely on git gc to cleanup.
Archive

Conversion check

Does the new types have enough information to provide what's needed to the UI?

Stack

  • stack_id (deprecated, maybe emulated with workaround to map an index to an id maybe)
  • heads
    • name
    • tip

Stack Details

  • derived_name ✓ (stack name, top-most branch in stack)
  • push_status (enum) (derived)
  • is_conflicted (has a conflicting commit somewhere) (derived)
  • branch details
    • name ✓
    • remote_tracking_branch ✓ (from Stack::upstream, but it's deduced seemingly)
    • description ✓
    • pr_number ✓
    • review_id ✓
    • tip ✓
    • base_commit (derived)
    • push_status: (derived with remote tracking branch)
    • last_updated_at (from RefInfo::updated_at ✓)
    • authors: Vec ✓
    • is_conflicted ✓
    • commits: Vec ✓
    • upstream_commits: Vec ✓
    • is_remote_head ✓

Commit

  • id ✓
  • parent_ids ✓
  • message ✓
  • has_conflicts ✓
  • state: CommitState (derived)
  • created_at ✓
  • author: Author ✓

CommitState

All derived once the commit-analysis is done

  • LocalOnly (derived)
  • LocalAndRemote(id) (derived)
  • Integrated (derived)

UpstreamCommit

  • id ✓
  • message ✓
  • created_at ✓
  • author ✓

Author

  • name ✓
  • email ✓
  • gravatar_url ✓

Copy link

vercel bot commented May 8, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
gitbutler-components ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 14, 2025 5:33pm

Copy link

vercel bot commented May 8, 2025

@Byron is attempting to deploy a commit to the GitButler Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions bot added the rust Pull requests that update Rust code label May 8, 2025
Byron added 5 commits May 14, 2025 10:45
It uses `gitoxide` for most of the operations, and relies on RefMetaData.
That way it's easy to see what the data is, independently of `dbg!()` builds.`
This works because `FromStr` is implemented for `StackId`, and that automatically
works for clap argument parsing.
This is more natural for the `gitoxide` API which explicitly supports such
usecases, just as does `git2`.
That way we can already try out bleeding edge features related
to a new implemenation to interpret workspaces.
@Byron Byron marked this pull request as ready for review May 14, 2025 17:44
@Byron Byron merged commit 3c024c3 into gitbutlerapp:master May 14, 2025
19 of 20 checks passed
@Byron
Copy link
Collaborator Author

Byron commented May 14, 2025

Early merge - typing ws3 will enable the new backend for stacks, stack_details and branch_details. Most of it is pretty untested, there is only a single test after all, even though 'everything' is implemented, in theory.

There is many, many TODOs and things I know should be better, but the idea here is to use these to conceive additional tests to force the implementation into shape.

@Byron Byron deleted the head-info branch May 14, 2025 17:49
@Byron Byron mentioned this pull request May 14, 2025
14 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@gitbutler/desktop rust Pull requests that update Rust code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant