Creating a branch in the app fails with "Failed to merge bases while cherry picking commit" because the workspace commit keeps stale extra parents

Open
#17,057 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
git, rust, tauri
Domain
backend, devtools

Research direction

Start with crates/but-api/src/legacy/virtual_branches.rs at the reported create_virtual_branch failure, then trace how workspace commit parents are rebuilt during branch creation and pull. Compare the parent list with applied stacks and the target commit in a case where stale extra parents are present. Done when rebuilding the workspace commit excludes invalid extra parents and the reported branch creation conflict is covered.

Written by the indexing model from the issue text.

Description

bug
Version

GitButler app 0.23.2 and but CLI 0.23.2

Operating System

macOS

Distribution Method

dmg (Mac OS - Apple Silicon)

Describe the issue
What happened

Creating a new branch in the desktop app failed every time with:

ERROR create_virtual_branch: crates/but-api/src/legacy/virtual_branches.rs:43:
error=Failed to merge bases while cherry picking commit <workspace-commit-sha>.
Encountered a conflict while merging the commit's new bases: <stack tip 1>, <stack tip 2>, ..., <old main commit A>, ..., <old main commit B>
Any ids mentioned may be in-memory and inaccessible through the git CLI.

Caused by:
    "path/to/some/build.gradle.kts" was/were conflicted when merging

The commit being cherry-picked is the GitButler Workspace Commit itself. but branch new <name> from the CLI succeeded in the same repo at the same moment. Only the app's legacy create_virtual_branch path failed.

Root cause (as far as I could tell)

The gitbutler/workspace commit had two extra parents that weren't stacks. Both were plain commits on the target branch (origin/main), and both were already ancestors of the current target:

  • git merge-base --is-ancestor <extra parent> <target sha> returned true for both.
  • No ref pointed at either commit, and neither showed up in but status or but status --json (only the 9 real stacks did).
  • Because of them, but status reported the older of the two (2 days old) as the (common base), even though every stack and but config target were on a much newer target commit.

The target branch changed build.gradle.kts twice after that stale base, and one applied stack edits the same file on top of those changes. When the app rebuilt the workspace commit, merging its "new bases" with the stale parent included reintroduced the old version of the file, which conflicted.

Things that did NOT clear the stale parents
  1. but pull, run twice, including with new upstream commits. All stacks rebased cleanly, but the two extra parents were carried into the new workspace commit unchanged, and (common base) stayed stale.
  2. but branch new followed by but branch delete.
  3. Removing a hidden, empty stack I found in metadata. It was in_workspace = true in both virtual_branches.toml and but.sqlite (vb_stacks / vb_stack_heads), its head was an old target-branch commit, it had no commits of its own, and but unapply <name> said Could not find source. Removing it didn't change the workspace parents.
Workaround that fixed it

but teardown --checkout-to main, then but apply <branch> for each of the 9 branches. The rebuilt workspace commit had exactly 9 parents (one per stack), (common base) matched the target, and branch creation worked again.

Expected
  • Rebuilding the workspace commit (on pull, branch create, and so on) should derive its parents from the applied stacks only. It shouldn't carry forward parents that aren't stacks, or at least should drop parents that are already ancestors of the target.
  • (common base) should never be older than the target when every stack is based on the target.
  • A stack that's in_workspace = true but unreachable from the CLI (Could not find source) should be reported, or cleaned up automatically.
How it may have gotten into this state

Unknown. The repo has been in GitButler mode for about a year, has gone through several GitButler upgrades (the metadata moved from virtual_branches.toml to but.sqlite, with 36 DB migrations), and has had many stacks applied, unapplied, and merged upstream over time. Coding agents also drive the CLI in this repo, though they only use but commands.

How to reproduce (Optional)

No response

Expected behavior (Optional)

No response

Relevant log output (Optional)

Dominant language
Rust
Stars
21.9k
Forks
1k
Avg merge
6h 1m
Merged PRs (30d)
657

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from gitbutlerapp/gitbutler

All issues in gitbutlerapp/gitbutler

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.