Skip to content

Feature: Interactive Rebase#7183

Merged
fulghum merged 74 commits intomainfrom
fulghum/rebase-prototype
Jan 2, 2024
Merged

Feature: Interactive Rebase#7183
fulghum merged 74 commits intomainfrom
fulghum/rebase-prototype

Conversation

@fulghum
Copy link
Copy Markdown
Contributor

@fulghum fulghum commented Dec 18, 2023

Adds support for an interactive rebase workflow with Dolt. This allows users to edit their commit history, including rewording commit messages, reordering commits, dropping commits, and squashing multiple commits together. At the end of an interactive rebase, the current branch points to a new commit history created by executing the rebase plan the user specified.

-- we start on a dev branch named myDevBranch
select commit_hash, message from dolt_log;
+----------------------------------+----------------------------+
| commit_hash                      | message                    |
+----------------------------------+----------------------------+
| fjq1sd7t8nbqn0ddvcor1i455i0i5ken | inserting row 3            |
| v8g3ic9j4euf68t7tfnj7je8e1j6vt9m | inserting row 2            |
| q909vda7hc7ithb2fcgcfghuvt8epsrj | inserting row 1            |
| 0djr0smhr9ucdjivsnabu7ls419p0f37 | creating table t           |
| d0lte08fpl5hpcmqj90d6jqrb6i17lfi | Іnitiаlіzе dаtа repоsіtory |
+----------------------------------+----------------------------+

-- the interactive rebase is started by calling the dolt_rebase stored procedure
call dolt_rebase('-i', 'main');

-- once an interactive rebase is started, the session is placed on a temporary working
-- branch and a dolt_rebase table is populated with the default rebase plan
select * from dolt_rebase;
+--------------+--------+----------------------------------+-----------------+
| rebase_order | action | commit_hash                      | commit_message  |
+--------------+--------+----------------------------------+-----------------+
| 1.00         | pick   | q909vda7hc7ithb2fcgcfghuvt8epsrj | inserting row 1 |
| 2.00         | pick   | v8g3ic9j4euf68t7tfnj7je8e1j6vt9m | inserting row 2 |
| 3.00         | pick   | fjq1sd7t8nbqn0ddvcor1i455i0i5ken | inserting row 3 |
+--------------+--------+----------------------------------+-----------------+

-- users can adjust the plan to reorder commits, drop commits, change commit messages or squash commits together
update dolt_rebase set action='reword', commit_message='inserting rows 1, 2, 3' where rebase_order=1;
update dolt_rebase set action='fixup' where rebase_order > 1;

-- execute the adjusted plan
call dolt_rebase('--continue');

-- see that the Dolt commit history has been rewritten
select commit_hash, message from dolt_log;
+----------------------------------+----------------------------+
| commit_hash                      | message                    |
+----------------------------------+----------------------------+
| 2mggja4n903gdo5fmbvcbj9vsvgdjd8q | inserting rows 1, 2, 3     |
| 0djr0smhr9ucdjivsnabu7ls419p0f37 | creating table t           |
| d0lte08fpl5hpcmqj90d6jqrb6i17lfi | Іnitiаlіzе dаtа repоsіtory |
+----------------------------------+----------------------------+

Resolves #3467

…ed, and tracking working set rebase metadata.
… them to the branch HEAD, and not to the ontoCommit yet
…till messy, but moving in the good direction
Copy link
Copy Markdown
Member

@zachmu zachmu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty great, nice implementation

Just a couple comments and suggestions about testing and stuff.

return err
}

err = copyABranch(ctx, dbData, rebaseWorkingBranch, rebaseBranch, true, nil)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You didn't create this problem, but this is a race because the underlying operation (doltdb.NewBranchAtCommit) is not atomic. It sets the branch head, then updates the working set head with whatever it finds there, in two separate optimistic locking noms transactions. So concurrent users of e.g. call dolt_branch(-f) and this procedure could overwrite each other's change as well as end up with an inconsistent working set (doesn't match the branch head).

Probably worth adding a TODO that we need to clean that up at some point, the entire model needs to be overhauled to update more than a single head atomically. We could do part of this now, by changing the NewBranchAtCommit call to use database.CommitWithWorkingSet instead of two separate atomic operations.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out. I've added a TODO and dug into the code to see where the race condition is. It looks like database.CommitWithWorkingSet creates a new commit though, which seems different from what we want here. I'm happy to follow up in another PR and dig in deeper and see if we can get this spot fixed.

Assertions: []queries.ScriptTestAssertion{
{
Query: "call dolt_rebase('-i', 'main');",
ExpectedErrStr: "fatal: A branch named 'dolt_rebase_branch1' already exists.",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't great, these are supposed to be strictly temporary identifiers to get around us not supporting a detached head operation. Would be better to just choose a branch name at random, put a number on the end, something else. No reason to ever make the customer care about our branch namespace choice here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on the fence about this. It's an easy change to use a different working branch name, but I liked that the pattern was predictable, i.e. "dolt_rebase_" + rebaseBranchName. The main reason I thought a predictable pattern would be useful was if a user needed to reconnect in a different session and would have to check out this working branch to continue the rebase.

We don't want to allow multiple active rebases to the same branch at the same time, and the "dolt_" branch namespace shouldn't be used by customers, so I don't think the naming restriction causes a problem.

@fulghum fulghum merged commit 52bae64 into main Jan 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support dolt rebase

2 participants