Git interactive rebase: how to move other branches (refs) automatically?

Viewed 29

Sometimes I would like to do a rebase and make sure other refs are updated to the new structure without manual resets or multiple rebases.

Is there a way to do it in one go, so that git rebase would update refs to new commit that are picked and had references before rebase?

One example:

Situation before Rebase:

* abc3... commit3 (branch:a, HEAD) 
* abc2... commit2 
* abc1... commit1 (branch:b)
* abc0... base commmit (branch:master)

Then do a Rebase master -i: pick abc3, abc1, abc2

And the result will look like: (branch:b stays in its own branch of commit)

* abc6... commit2 (branch:a, HEAD) 
* abc5... commit1   
* abc4... commit3
|
| * abc1... commit1 (branch:b)
|/
* abc0... base commmit (branch:master)

What I would like the result to look like: (branch:b is updated to a new commit)

* abc6... commit2 (branch:a, HEAD) 
* abc5... commit1 (branch:b)
* abc4... commit3
* abc0... base commmit (branch:master)
1 Answers

git rebase would update refs to new commit that are picked and had references before rebase?

Before, no.

But while you are rebasing? Maybe.

With Git 2.38 (Q3 2022), "git rebase -i"(man) learns to update branches whose tip appear in the rebased range with --update-refs option.

See commit 7fefa1b (12 Jul 2022) by Junio C Hamano (gitster).
See commit 4611884, commit aa37f3e, commit 3113fed, commit b3b1a21, commit 89fc0b5, commit 900b50c, commit a97d791, commit d7ce9a2, commit f57fd48, commit aa7f2fd, commit 18ea595, commit 1bec4d1 (19 Jul 2022) by Derrick Stolee (derrickstolee).
(Merged by Junio C Hamano -- gitster -- in commit 3d8e3dc, 01 Aug 2022)

rebase: add --update-refs option

Signed-off-by: Derrick Stolee

When working on a large feature, it can be helpful to break that feature into multiple smaller parts that become reviewed in sequence.
During development or during review, a change to one part of the feature could affect multiple of these parts.
An interactive rebase can help adjust the multi-part "story" of the branch.

However, if there are branches tracking the different parts of the feature, then rebasing the entire list of commits can create commits not reachable from those "sub branches".
It can take a manual step to update those branches.

Add a new --update-refs option to 'git rebase -i'(man) that adds 'update-ref ' steps to the todo file whenever a commit that is being rebased is decorated with that .
At the very end, the rebase process updates all of the listed refs to the values stored during the rebase operation.

Be sure to iterate after any squashing or fixups are placed.
Update the branch only after those squashes and fixups are complete.
This allows a --fixup commit at the tip of the feature to apply correctly to the sub branch, even if it is fixing up the most-recent commit in that part.

This change update the documentation and builtin to accept the --update-refs option as well as updating the todo file with the 'update-ref' commands.
Tests are added to ensure that these todo commands are added in the correct locations.

This change does not include the actual behavior of tracking the updated refs and writing the new ref values at the end of the rebase process.
That is deferred to a later change.

git rebase now includes in its man page:

--update-refs

--no-update-refs

Automatically force-update any branches that point to commits that are being rebased.
Any branches that are checked out in a worktree are not updated in this way.

And:

rebase: update refs from 'update-ref' commands

Signed-off-by: Derrick Stolee

The previous change introduced the 'git rebase --update-refs'(man) option which added 'update-ref <ref>' commands to the todo list of an interactive rebase.

Teach Git to record the HEAD position when reaching these 'update-ref' commands.
The ref/before/after triple is stored in the $GIT_DIR/rebase-merge/update-refs file.
A previous change parsed this file to avoid having other processes updating the refs in that file while the rebase is in progress.

Not only do we update the file when the sequencer reaches these 'update-ref' commands, we then update the refs themselves at the end of the rebase sequence.
If the rebase is aborted before this final step, then the refs are not updated.
The 'before' value is used to ensure that we do not accidentally obliterate a ref that was updated concurrently (say, by an older version of Git or a third-party tool).

Result:

sequencer: notify user of --update-refs activity

Reported-by: Elijah Newren
Signed-off-by: Derrick Stolee

When the user runs 'git rebase -i --update-refs'(man), the end message still says only

Successfully rebased and updated <HEAD-ref>.

Update the sequencer to collect the successful (and unsuccessful) ref updates due to the --update-refs option, so the end message now says

Successfully rebased and updated <HEAD-ref>.
Updated the following refs with --update-refs:
efs/heads/first
efs/heads/third
Failed to update the following refs with --update-refs:
efs/heads/second
Related