Skip to content

Rebasing across an upstream rename silently deletes the renamed files #15499

Description

@AlexanderGH

Version

0.22

Operating System

macOS

Distribution Method

dmg (Mac OS - Apple Silicon)

Describe the issue

Summary

When but pull rebases a branch across an upstream commit that renames files, the
rebased commits end up containing neither the old nor the new path — the files are
silently deleted from every rebased branch and from the working tree. No conflict is
raised, no warning printed, and but status reports a clean workspace.

A plain git rebase / git cherry-pick of the same commits onto the same base keeps
all the files.

Environment

  • but 0.22.0 (latest at time of report)
  • macOS (darwin 25.6.0), APFS
  • Large monorepo, ~14 applied stacks

Reproduction

  1. A branch is based on main@A. None of its commits touch directory D.
  2. Upstream advances main@A → main@B. Among those commits, one renames
    src/test/snapshots/**src/androidHostTest/snapshots/** (232 files, R100).
    The same push contains ~1889 renames in total.
  3. but pull.

Result — for every rebased stack:

$ git ls-tree -r --name-only origin/main -- .../src/androidHostTest/snapshots | wc -l
232
$ git ls-tree -r --name-only ^ -- .../src/androidHostTest/snapshots | wc -l # parent == origin/main
232
$ git ls-tree -r --name-only -- .../src/androidHostTest/snapshots | wc -l
0
$ git ls-tree -r --name-only -- .../src/test/snapshots | wc -l
0

The commit's parent is origin/main and contains the files, yet the commit's own
tree does not — so each rebased commit carries 232 spurious deletions it never made.
They are gone from the working tree too, and but diff shows "No diffs to show".

Plain git on the identical inputs is correct:

$ T=$(git merge-tree --write-tree --merge-base=^ origin/main )
$ git ls-tree -r --name-only $T -- .../src/androidHostTest/snapshots | wc -l
232

Knock-on effect: false "conflicts with existing stack"

Once a stack carries these phantom deletions, but apply starts rejecting unrelated
branches:

Failed to apply branch. 'X' conflicts with existing stack in the workspace:

This happened for a stack that additionally deleted files of its own (a removed Gradle
module plus two .java files). It reported a conflict against all 13 other stacks —
including ones touching entirely disjoint files — while git merge-tree --merge-base=origin/main X Y
exited 0 for every pair. but pull --check failed the same way:

Error: Failed to merge bases while cherry picking commit .
Encountered a conflict while merging the commit's new bases: <18 in-memory oids>.

Rebuilding all branches with plain-git cherry-picks onto the same base (same messages,
same change-id headers, correct trees) made the false conflicts disappear entirely:
all stacks applied, but pull --check clean.

Second false-conflict case: base skew

Two branches that add new files in disjoint paths, both rebased onto a base one commit
ahead
of the workspace base, could not coexist:

Failed to apply branch. 'A' conflicts with existing stack in the workspace: B

Each applied fine alongside the other 14 stacks; only the pair collided, and
git merge-tree --merge-base=origin/main A B exited 0. Running but pull to align every
stack on the same base made both apply cleanly.

Impact

Silent data loss. Any rebase across a rename-heavy upstream range can drop the renamed
files from every applied branch with no conflict, no warning, and a clean-looking
but status. If those commits are pushed, the deletions land in the PR.

Expected

The rebased commit's tree should differ from its parent only by what the original commit
changed — matching git cherry-pick. If the rename cannot be tracked, it should surface
as a conflict, not a silent delete.

How to reproduce (Optional)

No response

Expected behavior (Optional)

No response

Relevant log output (Optional)

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIThe command-line program `but`bugSomething isn't workingos:macThe MacOS platform

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions