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
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
Run with
DOLTLITE=build/doltlite(andSQLITE3=/DOLT=where used). Found at6eea51a619; still reproduces on master.Cause: commit timestamps are whole seconds (
src/doltlite_core.c:640,(i64)time(0)) while Dolt uses milliseconds, andrebaseHeapLess(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