Skip to content

Atomic updates #1

@abhinav

Description

@abhinav

Currently, if a rebase fails after a few branches have been updated, you're
left in an inconsistent state where half the branches have been updated and
the other ones are still pointing to the old tree.

For example, in,

pick A
pick B
exec git branch -f feature1

pick C
pick D
exec git branch -f feature2

If pick C fails and you git rebase --abort, feature1 has still been
moved to a new position.

An alternative method is to use update-ref to place markers for where
branches will go if everything succeeds and commit these changes only if
everything was successful.

pick A
pick B
exec git update-ref refs/restack/feature1 HEAD

pick C
pick D
exec git update-ref refs/restack/feature2 HEAD

Then, if the rebase succeeds, we'll want to run branch -f with these refs.
Something equivalent to the following should suffice,

git for-each-ref --shell \
    --format='git branch -f %(refname:lstrip=3) %(objectname) && \
    git update-ref -d %(refname)' refs/restack/ | sh

This would be pretty unreadable to users but I think we can provide a nicer UI
on top.

Instead of adding exec git branch -f or exec git update-ref instructions,
the git-rebase-todo that the user sees will contain a custom mark
instruction. The main instruction set will be followed by a lone restack
command which indicates the point at which the branches will be updated. The
opt-in push will follow the restack.

pick A
pick B
mark feature1

pick C
pick D
mark feature2

restack

# Uncomment this section to push the changes.
# exec git push -f origin feature1
# exec git push -f origin feature2

Caveat: This introduces custom language to git-rebase-todo. We can
technically avoid this by calling back into restack from the instruction
list without too much loss in readability. I'm undecided on this.

exec restack mark feature1
exec restack commit-marks

CC @kriskowal

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions