Skip to content

v3 unapply: MVP#10872

Draft
Byron wants to merge 3 commits intogitbutlerapp:masterfrom
Byron:next
Draft

v3 unapply: MVP#10872
Byron wants to merge 3 commits intogitbutlerapp:masterfrom
Byron:next

Conversation

@Byron
Copy link
Copy Markdown
Collaborator

@Byron Byron commented Oct 29, 2025

Get unapply() going, turning the existing tests into small journeys.

Follow-up of #10863.

Tasks

General note: this operates under the assumption that anything that refers to a stack to be unapplied handles that it is unapplied automatically, i.e. it reconciles automatically. We do not create snapshots yet.

  • read-up on notion and update analysis.
  • API sketch
  • unapply non-tips
  • unapply a branch in a workspace without workspace commit
  • unapply in single-branch mode (anything)
  • unapply a branch in an enclosing workspace
  • unapply of unapplied branch, but one that has metadata (also check the metadata)
  • unapply a branch whose tip advanced outside of the workspace
  • unapply a branch whose tip is 'recessed', i.e. it's commit is not merged in the workspace commit, but a descendant is. This is an anon-stack technically, and we specify the segment below the tip.
  • unapply from 3 to 2 may remove the workspace commit if the remaining stacks are virtual
  • should unapply from 2 to 1 always drop the WS-commit? Make it configurable
    • ensure it won't checkout the stack reference if there is conflicts in the remaining stack
    • ensure it won't checkout the stack reference if there is commits on top of the workspace commit
    • ensure it won't checkout the stack if it is not named.
  • go from 2 -> 1 stacks
    • with without loosing the WS commit
    • with and without checkout out the last remaining stack (SBR or not)
    • be sure this fails if worktree changes would conflict (lacking auto-snapshot targets)
  • go from 1 -> 0 stacks - this can't change branches
    • with or without loosing the WS commit
  • all WorkspaceMergeCommit variants are tested
  • all WorkspaceReference variants are tested
  • make use of new unapply() behind new feature toggle

Future Tasks

  • cherry-pick index as well (but only conflicts) - consider skipping but make sure it doesn't get lost
  • make archived more sturdy in the light of applying/unapplying, to consider keeping the original copy of the now integrated part of the stack.
  • proper worktree checkout handling - we must not checkout branches that are already checked out in any worktree (see gix code somewhere)
  • unapply takes care of assignments by creating snapshots (move away from bare WIP commits). Snapshots solve a lot of problems around 'stashing' otherwise conflicting changes.
  • Permutations: base position - shouldn't be needed as unapply doesn't affect any base (it's all computed)

Shortcomings

  • Assignments are ignored completely (for now)
  • Worktree change in a detached HEAD can't be stashed as there is no reference to associated the stash with.
    • But that's OK as we don't currently store stashes anyway for a lack of UI support to try to apply them.

Notes

Kiril's thoughts

yeah, possibly the "tricky" part is that bit about going to a single branch mode (if it's going from 2 branches in the workspace to 1). And I am curious what this new world means when a user wants to go from a 1 branch (single branch mode) to zero... is that a valid operation? Does it mean checking out orgin master? And maybe one final question in my mind - what if there are commits on top of the workspace commit (i.e. user did something outside of the app) - how unapply deals with that

General Rules

  • The workspace is a conflict-free zone
    • nothing that operates on the conflict must write conflicts into the index.
      This is as conflicts are currently hidden from view.
  • Symmetry
    • If apply is doing something, then unapply undoes exactly that, or in other words State + apply + unapply == State
  • There is no single-branch workspace when starting in single-branch mode
    • A workspace consists of at least two branches and a workspace commit
    • The workspace commit is optional if there is only one commit involved, i.e. when it's just a bunch of branches on top of a single commit
    • BUT: we can enforce this, and have single-branch and zero-branch workspaces.
  • Workspace Commit ALWAYS for even for a single branch
    • The workspace backend can deal with anything, but commit() currently can't.
    • Have to add commit() and uncommit() as well to all apply-unapply tests so these can later be re-tested with different behaviour.
    • Implied by the previous rule

Follow-Ups

  • commit with auto-workspace-commit creation: needed if there are multiple applied branches and no workspace commit: Let's try just not to have that
    • At the same time, it needs uncommit() that is symmetric

Thus:

  • snapshots of worktree changes will be made to apply by forcing merge-conflicts to be... auto-resolved.
    This is a problem, but we can't have conflicts as the UI doesn't show them right now, nor does it allow interacting with them.
    • the actual implementation actually fails if there are conflicts I think.

Unapply

  • Conflicting paths are passed added as extra commit at first, without additional special handling in apply just to be able to handle them.
    • This means assignments aren't taken care of in all cases (but we will see how all this interacts with stack-ids)

Research

Unapply: Assignments - with stashing

  • uncommitted but assigned changes should create a snapshot commit
  • when applying the same branch this snapshot is applied

However, the user should be able to interact with these.

Unapply: Assignments - with WIP commit

  • uncommitted but assigned changes should create a WIP commit
    • or just unassign these assignments and they are back in the unassigned changes of the workspace
  • MVP apply: do nothing with the WIP commit
  • final version: apply restores the assignments from the WIP commit (which then is tracked with metadata)

Unapply with worktree changes

  • worktree changes that don't re-apply cleanly

Possible Follow-Ups

  • Find a way to display and handle conflicts in the UI (Gitizen).
    • this would allow us to write conflicts as well and deal with them.

@vercel
Copy link
Copy Markdown

vercel Bot commented Oct 29, 2025

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

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rust Pull requests that update Rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant