Skip to content

dolt_rebase plan order differs from Dolt when commits share a timestamp second #3158

Description

@timsehn

Summary

feat = f1, f2, and a merge of side (s1, s2), all created within one second. DoltLite plan: f1,s1,f2,s2; Dolt: f1,f2,s1,s2. With more than 1 s between commits DoltLite matches Dolt. Both orders are valid topological orders, so replay results are identical; only the plan and replayed commit order differ. Low severity, but every fast test fixture hits the tie.

Repro

#!/bin/bash
# C4: with merge commits in the range, equal-height commits created within the same second are
# ordered by heap push order instead of by timestamp (commit timestamps are whole seconds), so the
# plan differs from Dolt's; with >1s between commits the order matches Dolt.
DL=${DOLTLITE:-build/doltlite}
DOLT=${DOLT:-dolt}
W=$(mktemp -d)
SQL='CREATE TABLE t(pk INT PRIMARY KEY, v INT);
INSERT INTO t VALUES (1,1);
SELECT dolt_add(".");
SELECT dolt_commit("-m", "base");
SELECT dolt_branch("feat");
INSERT INTO t VALUES (2,2);
SELECT dolt_commit("-am", "main2");
SELECT dolt_checkout("feat");
INSERT INTO t VALUES (10,10);
SELECT dolt_commit("-am", "f1");
SELECT dolt_branch("side");
INSERT INTO t VALUES (11,11);
SELECT dolt_commit("-am", "f2");
SELECT dolt_checkout("side");
INSERT INTO t VALUES (20,20);
SELECT dolt_commit("-am", "s1");
INSERT INTO t VALUES (21,21);
SELECT dolt_commit("-am", "s2");
SELECT dolt_checkout("feat");
SELECT dolt_merge("side", "--no-ff", "-m", "merge side");
SELECT dolt_rebase("-i", "main");
SELECT CONCAT("plan=", group_concat(commit_message, ",")) FROM (SELECT commit_message FROM dolt_rebase ORDER BY rebase_order);
SELECT dolt_rebase("--abort");'
echo "== DoltLite"; printf '%s\n' "$SQL" | "$DL" "$W/dl.db" 2>&1 | grep '^plan='
echo "== Dolt"; mkdir -p "$W/dt"; ( cd "$W/dt" && "$DOLT" init --name oracle --email oracle@test >/dev/null 2>&1
printf '%s\n' "$SQL" | sed -E 's/SELECT[[:space:]]+(dolt_[a-z_]+\()/CALL \1/g; s/"/'"'"'/g' | "$DOLT" sql -c -r csv 2>&1 | grep '^plan=' )
echo
echo "EXPECTED (Dolt, ms timestamps): plan=f1,f2,s1,s2"
echo "GOT (DoltLite, second-granularity timestamps tie -> push order): plan=f1,s1,f2,s2"

Run with DOLTLITE=build/doltlite (and SQLITE3=/DOLT= where used). Found at 6eea51a619; still reproduces on master.

Cause: commit timestamps are whole seconds (src/doltlite_core.c:640, (i64)time(0)) while Dolt uses milliseconds, and rebaseHeapLess (src/doltlite_rebase.c ~150) falls back to heap push order on a tie. Breaking ties the way Dolt's walk does (or storing ms timestamps) would fix it.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdeferredDeferred until a later milestone (e.g. the v13 storage-format upgrade)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions