Skip to content

Improve moving commits across branch boundaries in a stack of branches - #6180

Open
stefanhaller wants to merge 8 commits into
masterfrom
improve-moving-commits-across-branch-boundaries-in-stack
Open

stefanhaller wants to merge 8 commits into
masterfrom
improve-moving-commits-across-branch-boundaries-in-stack

Conversation

@stefanhaller

Copy link
Copy Markdown
Collaborator

When moving commits in a stack of branches, it can be unclear whether a moved commit goes before or after a branch head; in other words, whether it goes at the end of one branch or at the beginning of the next. The workaround is to type i to enter an interactive rebase for the whole stack; this will show "update-ref" todos for the branch heads, which gives you control over where exactly a commit goes by moving it before or after those "update-ref" todos.

This PR adds two improvements to doing this outside of a rebase:

  1. When moving commits with <ctrl+j> or <ctrl+k> and you hit a branch boundary, the next keypress moves the commit only across the boundary. The commit's position in the list stays the same, only the branch icon moves. This is the opposite of what Fix moving a commit across a branch boundary in a stack of branches #4096 did, but it was mentioned there as one possible (and probably the preferred) option; we just didn't manage to implement it back then.
  2. When dragging commits with the mouse, we now show the branch boundaries as extra rows during the drag gesture, so that you can drop before or after them; this is similar to those "update-ref" todos in an interactive rebase.

This also fixes a bug: when moving a range selection of commits that spans a branch boundary, this broke the stack because it didn't move the update-ref todos along with the commits.

@stefanhaller stefanhaller added the enhancement New feature or request label Nov 6, 2026
stefanhaller and others added 8 commits November 8, 2026 14:27
When moving commits outside of a rebase, we will need to know where the
branch boundaries of a stack are. These are the heads of the branches
that the commits list marks, so we want to use the same rule there.

Put the rule in the branchstack package. BranchesBelow had its own copy
of it, so use it there too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If a range of selected commits spans the boundary between two branches
of a stack, moving it outside of a rebase moves each of its commits
separately past the next commit. The update-ref todo inside the range
stays behind. In the test, branch2 is left without any commits of its
own after moving the range up, and its commits now belong to branch3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Outside of a rebase, we move commits by a number of rows, skipping the
update-ref todos that we don't show. This can't move a commit past the
update-ref todos only. We will need that for moving a commit to the end
of the branch below it in a stack. It also moves each commit separately,
so the update-ref todos between the moved commits stay behind.

MoveCommitsTo names the commit that the moved commits are to sit on, and
which of the branches that point at that commit are to point at the
moved commits instead. The update-ref todos between the moved commits
move along with them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If a range of selected commits spans the boundary between two branches
of a stack, moving it outside of a rebase leaves the update-ref todo
between them behind. This is because each commit is moved past the next
commit separately. As a result, the lower branch loses its commits to
the one above it.

Move the commits with MoveCommitsTo instead. It moves the update-ref
todos between the commits along with them. It also needs to know which
branches point at the commit that the moved commits go on top of. These
are the branches that the commits list marks, except for those that git
doesn't update in a rebase.

Otherwise, moving commits up or down and dropping dragged commits work
as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moving commits outside of a rebase now names the commit that they go on
top of, so nothing moves them by a number of rows any more. Moving todos
by a number of rows is left only for the rebase todo, where update-ref
and exec todos are rows of their own.

MoveTodosDown and MoveTodosUp of RebaseCommands were unused already;
remove them too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
To add a commit at the end of a lower branch of a stack, the obvious way
is to create it at the top of the stack and move it down. Outside of a
rebase, pressing ctrl+j doesn't get it there. Once the commit is at the
bottom of the second branch, the next ctrl+j moves it past the
update-ref todo of the first branch and past that branch's last commit.

We made it work like this deliberately in #4096. Moving the commit past
the update-ref todo only would have required keeping the selection
where it is, and this was hard to do. Now that the destination of a
move is named explicitly, it is easy.

So if the commit below the selected commits is the head of branches of
the stack, ctrl+j now moves them past the update-ref todos of all these
branches at once, and keeps them selected. The branch marker moves up
to the bottom selected commit. The next ctrl+j moves them further into
the lower branch. ctrl+k does the same the other way round: if the
topmost selected commit is the head of branches, it moves the commits
past their update-ref todos first, to the start of the branch above.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Dragging the first commit above the view, or the last commit below the
end of the list, must not offer to drop them there, because that
wouldn't move them anywhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Outside of a rebase, dragging a commit of a stack down to below the last
commit of the branch above puts it at the start of that branch. There is
no way to drop it at the end of the branch below instead, because the
update-ref todos between the two branches are not shown.

Show a row for each of these update-ref todos while dragging, and let
the drop indicator go between them. The row is a horizontal line across
the hash column, followed by the name of the branch. This also makes it
possible to drop a commit between the rows of two branches that point
at the same commit.

The rows appear only once the pointer has left the pressed row. Rows
that appear above the pressed commit push it down, so a click with a
slight sideways movement could otherwise offer to drop the commit
somewhere else. We don't scroll the view to keep the pressed commit
under the pointer. If the drag is canceled, this would leave the first
commit of the list scrolled out of view, and this is easy to miss.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@stefanhaller
stefanhaller force-pushed the improve-moving-commits-across-branch-boundaries-in-stack branch from 2e76e16 to 53cf6f6 Compare November 8, 2026 13:28

This branch has not been deployed

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant