When somebody else rebases a stack and force-pushes it, pulling the topmost branch leaves the branches below it diverged. They can be updated with `f`, but pushing the stack offers to push the branches below along with the current one, and pulling should be symmetric. When pulling, find the branches stacked below the current one that can be updated without losing anything. These are those that are behind their upstream branches, and those that diverged from them only because they were rewritten. If there are any, show a menu that lists them and offers to update them in addition to pulling the current branch, or to pull only the current branch. The current branch is pulled as before. The decision is based on the last fetch, not on a new one, so that the menu appears right away. If the remote has changed since then, a branch might not be offered although it could be updated; it then shows as diverged after the pull, and pulling again offers it. The update itself fetches the upstream branches and checks them again, so it never loses commits. Branches that are checked out in another worktree are not offered, since updating them would change the files there. The branches below are updated before the current branch is pulled. If one of them pointed into the commits that a rebasing pull rebases, the pull would move it when rebase.updateRefs is set, and updating it afterwards would fail. If updating them fails, the current branch isn't pulled. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
3.0 KiB
Working with stacked branches
When working on a large branch it can often be useful to break it down into smaller pieces, and it can help to create separate branches for each independent chunk of changes. For example, you could have one branch for preparatory refactorings, one for backend changes, and one for frontend changes. Those branches would then all be stacked onto each other.
Git has support for rebasing such a stack as a whole; you can enable it by
setting the git config rebase.updateRefs to true. If you then rebase the
topmost branch of the stack, the other ones in the stack will follow. This
includes interactive rebases, so for example amending a commit in the first
branch of the stack will "just work" in the sense that it keeps the other
branches properly stacked onto it.
Lazygit visualizes the individual branch heads in the stack by marking them with a cyan asterisk (or a cyan branch symbol if you are using nerd fonts).
When you push the topmost branch of the stack with P, and the branches below
it have commits that haven't been pushed yet, lazygit offers to push them along
with it. After rebasing the stack this saves you from checking out and
force-pushing every branch one by one; you are asked to confirm the force push
once for all of them. Only branches that already have an upstream are included.
Each of them is pushed to where git push would push it if it were checked out,
so your push configuration applies to them as usual.
When somebody else rebases the stack and force-pushes it, all your branches
show up as diverged, for example ↓5↑3, even though the commits they are ahead
by are only the old versions of the ones that are now on the remote. Lazygit
tells this apart from a branch that carries work of your own, and shows the
divergence dimmed for such a branch. Pressing f on it resets it to its
upstream instead of refusing, so you don't have to check the branch out and pull
it. Lazygit only does this when every commit of the branch was on its remote
branch at some point. It finds that out from the reflog of the remote-tracking
branch. Reflogs are enabled by default, except in a bare repository; if you work
in one with linked worktrees, set core.logAllRefUpdates to true there to make
this work.
f works on a range selection too, so you can select the
whole stack and bring all of it back in sync at once. If any of the selected
branches can't be updated, none of them is, so that you don't end up with half
of the stack updated.
Alternatively, check out the topmost branch of the stack and pull it with p.
If branches below it can be updated this way, or are simply behind their
upstream, lazygit offers to update them along with it. Lazygit decides this
from the last fetch, so a branch whose changes on the remote haven't been
fetched yet isn't offered; with auto-fetch turned off, pull a second time after
the first pull has fetched them. Branches that are checked out in another
worktree are left alone. The topmost branch itself is pulled as usual.