SQL Rebase Edit

FEATURE RELEASE
8 min read

Dolt is the world’s first SQL database that you can fork, clone, branch, merge, and push to remote repositories. As we like to say, MySQL and Git had a baby.

Last week I made the claim that agents working with Dolt should all regularly rebase their work. In that post, I also said that agents should avoid the use of rebase --interactive, because agents probably don’t need to edit their commit history, and that interactive rebase is primarily a tool for humans.

Today, I’m writing for the humans out there. Sorry all you LLM scrapers out there, this text isn’t for you! Interactive Rebase is the type of feature that makes sense for human curators of data. It allows you to clean up your commit history. You can squash commits, reorder them, change commit messages, adjust data, insert new commits, and delete commits. Basically, you can make your commit history look exactly how you want it to look.

People with opinions care about such things. Craftsmen (or women) who take pride in their work want to present their work in the best possible light. Interactive Rebase is a tool for such people.

Introducing edit#

We originally introduced rebase to Dolt in early 2024. At that time, we implemented a subset of the features of interactive rebase. In version 1.84.5 released this week, we’ve added the ability to edit commits during a rebase. With this addition, we support all the primary operations that Git supports during an interactive rebase, with the exception of exec.

The edit operation allows you to pause the rebase at a specific commit, make changes to the data, and then continue the rebase workflow.

This can be useful for a variety of reasons. For example, you might want to fix a piece of data that was mistakenly added in a previous commit. Or, you may have newer more correct data that you want to replace incorrect data with. You may want to update your dolt_tests table, and move that change into an earlier commit. Classic source control use case - make it look like you wrote the tests before the code! Anyway, the edit operation gives you the flexibility to make these kinds of changes during a rebase.

Setup for an Example#

Let’s look at an example of how to use the edit operation during a rebase. I’m going to create a table of Christmas movies, ranked from 1 to 5. I’ll make a few commits to modify the data, and then I’ll use dolt rebase --interactive with the edit operation to fix a mistake I made in one of the commits.

Install Dolt and create a database:

$ mkdir mydb; cd mydb;
mydb$ dolt init
Successfully initialized dolt data repository.
mydb$ dolt sql
# Welcome to the DoltSQL shell.
# Statements must be terminated with ';'.
# "exit" or "quit" (or Ctrl-D) to exit. "\help" for help.
mydb/main>

You are now in the dolt sql shell. Create the xmas_movies table, then commit it:

mydb/main> create table xmas_movies (
  pk int not null auto_increment,
  `rank` int not null,
  movie_name varchar(255) not null,
  blurb varchar(1024) not null,
  primary key (pk)
);

mydb/main*> call dolt_commit('-Am', 'create xmas_movies table');

I’ll seed the table with the following query:

mydb/main> insert into xmas_movies (`rank`, movie_name, blurb) values
  (1, 'Home Alone',             'Peak chaotic holiday classic'),
  (2, 'Elf',                    'Will Ferrell at his finest'),
  (3, 'Die Hard',               'Yippee-ki-eh, mother f&$%er, and yes it counts'),
  (4, 'Fred Claus',             'Underrated, dingbat sounds, the best'),
  (5, 'It''s a Wonderful Life', 'Timeless');

mydb/main*> call dolt_commit('-Am', 'initial xmas_movies data');

Opinions change, and I realize that Home Alone is actually a terrible movie. I want to knock it off the list, move everything else up a rank, and add The Nightmare Before Christmas to the bottom of the list. I’ll add this as a regular commit.

mydb/main> delete from xmas_movies where movie_name = 'Home Alone';
mydb/main*> update xmas_movies set `rank` = `rank` - 1;
mydb/main*> insert into xmas_movies (`rank`, movie_name, blurb) values (5, 'The Nightmare Before Christmas', 'Spooky, festive, oddly sweet');
mydb/main*> call dolt_commit('-Am', 'Home Alone no more, Tim Burton for the win');

With a little more consideration, I realize I want Nightmare Before Christmas to be ranked higher, and It's a Wonderful Life to be lower. I’ll do this with another regular commit.

mydb/main> update xmas_movies set `rank` = 5 where movie_name = "It's a Wonderful Life";
Query OK, 1 row affected (0.01 sec)
mydb/main*> update xmas_movies set `rank` = 4 where movie_name = "The Nightmare Before Christmas";
Query OK, 1 row affected (0.01 sec)
mydb/main*> call dolt_commit('-Am', 'swap ranks 4 and 5');

At this point, my commit history looks like this:

mydb/main> \log
commit ndu4tenqjrmo9qb26f4gegplnllajvfn (HEAD -> main)
Author: root <root@localhost>
Date:  Tue Feb 03 11:01:58 -0800 2026

        swap ranks 4 and 5

commit njgunlhb3d3n8e3q6u301v8e01kbglrh
Author: root <root@localhost>
Date:  Tue Feb 03 11:01:42 -0800 2026

        Home Alone no more, Tim Burton for the win

commit tio1fui012j8l6epa7iqknhuv30on1p7
Author: root <root@localhost>
Date:  Tue Feb 03 11:01:34 -0800 2026

        initial xmas_movies data
[...snip...]

Using edit During a Rebase#

Looking at my history and data, I realize that I’ve made a grave spelling error. I spelled “Yippee-ki-yay” wrong in the blurb for Die Hard. I spelled it like a Canadian would, with “eh” at the end. This is very embarrassing. I want to fix this mistake, and I want to do it in the commit where I originally added the data so no one knows I ever made the mistake.

mydb/main> call dolt_rebase('--interactive','HEAD~3');
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| status | message                                                                                                                                                             |
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 0      | interactive rebase started on branch dolt_rebase_main; adjust the rebase plan in the dolt_rebase table, then continue rebasing by calling dolt_rebase('--continue') |
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+

When you run this command using the dolt sql shell, you’ll see that you are now on a different branch which is dirty:

mydb/dolt_rebase_main*>

This is how rebase works in Dolt. You are now on a temporary branch called dolt_rebase_main. The * indicates that you have uncommitted changes. And if you look at the dolt_rebase table, you’ll see your rebase plan:

mydb/dolt_rebase_main*> select * from dolt_rebase;
+--------------+--------+----------------------------------+--------------------------------------------+
| rebase_order | action | commit_hash                      | commit_message                             |
+--------------+--------+----------------------------------+--------------------------------------------+
| 1.00         | pick   | tio1fui012j8l6epa7iqknhuv30on1p7 | initial xmas_movies data                   |
| 2.00         | pick   | njgunlhb3d3n8e3q6u301v8e01kbglrh | Home Alone no more, Tim Burton for the win |
| 3.00         | pick   | ndu4tenqjrmo9qb26f4gegplnllajvfn | swap ranks 4 and 5                         |
+--------------+--------+----------------------------------+--------------------------------------------+
3 rows in set (0.00 sec)

The dolt_rebase table shows you the commits that will be applied during the rebase, in order. The action column shows what action will be taken for each commit. By default, all commits are set to pick, which means they will be applied as-is. You can edit this table to change the planned actions. I’d like to edit the first commit’s data, and change the commit message on the last commit. To do this, I’ll update the dolt_rebase table like so:

mydb/dolt_rebase_main*> update dolt_rebase set action = 'edit' where rebase_order = 1.0;
Query OK, 1 row affected (0.01 sec)
mydb/dolt_rebase_main*> update dolt_rebase set action = 'reword', commit_message = "Nightmare over Wonderful Life" where rebase_order = 3.0;
Query OK, 1 row affected (0.01 sec)
mydb/dolt_rebase_main*> select * from dolt_rebase;
+--------------+--------+----------------------------------+--------------------------------------------+
| rebase_order | action | commit_hash                      | commit_message                             |
+--------------+--------+----------------------------------+--------------------------------------------+
| 1.00         | edit   | tio1fui012j8l6epa7iqknhuv30on1p7 | initial xmas_movies data                   |
| 2.00         | pick   | njgunlhb3d3n8e3q6u301v8e01kbglrh | Home Alone no more, Tim Burton for the win |
| 3.00         | reword | ndu4tenqjrmo9qb26f4gegplnllajvfn | Nightmare over Wonderful Life              |
+--------------+--------+----------------------------------+--------------------------------------------+
3 rows in set (0.00 sec)

Note that the updated reword action is a little different from Git. You update the commit message directly in the dolt_rebase table, rather than being prompted for it later.

When you have the plan you like, you continue the rebase:

mydb/dolt_rebase_main*> call dolt_rebase('--continue');
+--------+----------------------------------------------------------------------------------------------------------------------------------+
| status | message                                                                                                                          |
+--------+----------------------------------------------------------------------------------------------------------------------------------+
| 0      | edit action paused at commit tio1fui012j8l6epa7iqknhuv30on1p7 (initial xmas_movies data).                                        |
|        |                                                                                                                                  |
|        | You can now modify the working directory and stage changes. When ready, continue the rebase by calling dolt_rebase('--continue') |
+--------+----------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.02 sec)

Now, I can fix my egregious spelling mistake:

mydb/dolt_rebase_main*> update xmas_movies set blurb = "Yippee-ki-yay, mother f&$%er, and yes it counts" where movie_name = 'Die Hard';
Query OK, 1 row affected (0.01 sec)

When performing a rebase with an edit action, the process stops with the commit in question at HEAD. So if you want to edit that particular commit, you must amend the existing commit, not create a new one. Use the --amend flag to do this:

mydb/dolt_rebase_main*> call dolt_commit('-a', '--amend',  '-m', 'initial xmas_movies data');
+----------------------------------+
| hash                             |
+----------------------------------+
| gfanhk875aar3r2t6v88pnjt9rjjfj1m |
+----------------------------------+
1 row in set (0.01 sec)
mydb/dolt_rebase_main*>

Now that I’ve fixed the mistake, I can continue the rebase:

mydb/dolt_rebase_main*> call dolt_rebase('--continue');
+--------+--------------------------------------------------+
| status | message                                          |
+--------+--------------------------------------------------+
| 0      | Successfully rebased and updated refs/heads/main |
+--------+--------------------------------------------------+
1 row in set (0.04 sec)

The shell prompt should indicate that you are back on the main branch, and your workspace is clean. Looking at the log, you can see that all the commit IDs have changed. The commit message for the most recent commit has been updated.

mydb/main> \log
commit 6038q32lo9nc2ni532d1uh9avdqmjlva (HEAD -> main)
Author: root <root@localhost>
Date:  Tue Feb 03 14:56:00 -0800 2026

        Nightmare over Wonderful Life

commit 39vd67bm5s4idqedbfgifdl53hf9s2ji
Author: root <root@localhost>
Date:  Tue Feb 03 14:54:11 -0800 2026

        Home Alone no more, Tim Burton for the win

commit ujem90mkl0smpva6ms1dt616854i9sh7
Author: root <root@localhost>
Date:  Tue Feb 03 15:01:12 -0800 2026

        initial xmas_movies data
[...snip...]

And if we look at the data, we can see that the blurb for Die Hard has been corrected:

mydb/main> select * from xmas_movies order by `rank`;
+----+------+--------------------------------+-------------------------------------------------+
| pk | rank | movie_name                     | blurb                                           |
+----+------+--------------------------------+-------------------------------------------------+
| 2  | 1    | Elf                            | Will Ferrell at his finest                      |
| 3  | 2    | Die Hard                       | Yippee-ki-yay, mother f&$%er, and yes it counts |
| 4  | 3    | Fred Claus                     | Underrated, dingbat sounds, the best            |
| 6  | 4    | The Nightmare Before Christmas | Spooky, festive, oddly sweet                    |
| 5  | 5    | It's a Wonderful Life          | Timeless                                        |
+----+------+--------------------------------+-------------------------------------------------+
5 rows in set (0.00 sec)

Gotchas#

A few things to be aware of with rebase. First, if you have schema changes in your commits, you will need to wait until we support them. You can probably imagine the pitfalls here. You change data on your first commit, then add a column in your second commit. If you reverse the order of those commits, what happens to the data you changed in the first commit? Anyway, there are many edge cases in this space. For now, we simply don’t support schema changes during rebase. If you try to rebase commits with schema changes, you’ll get an error. Running into this? We’d like to hear from you. Create an issue on GitHub or reach out to us on Discord!

Also, when data conflicts occur, you need to set the following variable to prevent Dolt from prematurely aborting the rebase:

set @@dolt_allow_commit_conflicts = 1;

The rebase operation will automatically abort if you have a conflict and this variable isn’t set. The reason for this is mainly because we don’t want to leave your branch in a half-rebased state if you aren’t prepared to deal with it. Setting this variable indicates that you are prepared to handle conflicts during the rebase process.

Conclusion#

Interactive rebase is a powerful tool for curating your commit history. I confess it may be for the data artisans in the audience, but if you care about the presentation of your work, it’s worth learning. With the addition of the edit operation, Dolt now supports most of the key features of interactive rebase. Give it a try, and let us know what you think! As always, if you have questions or feedback, reach out to us on Discord!