Summary
travsr init prints a "a git rebase is in progress" warning on repos where no rebase is in progress. The check tests for .git/REBASE_HEAD, which git leaves behind permanently after a rebase finishes or is aborted. It is not an in-progress signal.
The practical effect is that once a user has ever run a rebase in a repo, every subsequent travsr init tells them their index may contain conflict markers, forever.
Repro
cd any-repo
git rebase <anything> # then finish it, or abort it
./target/release/travsr init
Observed on this repo at d68b4aa8:
$ ./target/release/travsr init --semantic --force --no-connect
travsr: scanning 1,024 files 0s
warning: a git rebase is in progress, consider finishing or aborting it before running `travsr init` to avoid indexing conflict markers
State of the repo at that moment:
$ ls -d .git/rebase-merge .git/rebase-apply
(neither exists)
$ git ls-files -u
(empty, no unmerged paths)
$ git diff --check
(clean, no conflict markers)
$ ls -la .git/REBASE_HEAD
-rw-r--r-- 1 ak staff 41 Aug 23 16:56 .git/REBASE_HEAD # stale, from a rebase weeks earlier
Actual
Warning is printed. The index is fine.
Expected
No warning, because no rebase is in progress.
Root cause
crates/travsr-daemon/src/lib.rs:1426, inside init_repo_with_progress (defined at line 1091):
// L13: warn if a rebase is in progress - init during rebase risks indexing
// conflict-marker noise into graph.db; the user should finish rebasing first.
if repo_root.join(".git").join("REBASE_HEAD").exists() {
eprintln!(
"warning: a git rebase is in progress, consider finishing or aborting it \
before running `travsr init` to avoid indexing conflict markers"
);
}
REBASE_HEAD is written during a rebase and is not removed when the rebase completes or is aborted, so its presence says only "a rebase happened here at some point". The in-progress condition git itself uses is the existence of the state directory .git/rebase-merge/ (interactive and merge backend) or .git/rebase-apply/ (am backend). Both are removed on completion and on --abort.
Introduced in e942ed4 (RFC-018 embedding plugin + UX hardening, #364) as item L13.
Secondary defect in the same line: worktrees
repo_root.join(".git") assumes .git is a directory. In a linked worktree .git is a file containing a gitdir: pointer, so <root>/.git/REBASE_HEAD never exists and the warning can never fire there, even during a genuine rebase. Rebase state for a linked worktree lives under .git/worktrees/<name>/rebase-merge/.
This repo currently has linked worktrees, including agent worktrees under .claude/worktrees/, so the path is reachable in normal use:
$ git worktree list
/Users/ak/Desktop/Proj/travsr d68b4aa8 [fix/travsr-store-778-short-symbol-idf-fallback]
/Users/ak/Desktop/Proj/travsr/.claude/worktrees/agent-... 8162fbdc [worktree-agent-...]
So the current check is wrong in both directions: it false-positives in the main worktree, and false-negatives in linked worktrees.
Suggested fix
Resolve the real git dir rather than assuming .git is a directory, then test for the rebase state directories:
// A rebase is in progress iff git's state directory exists. REBASE_HEAD is left
// behind after a completed or aborted rebase and must not be used as the signal.
let git_dir = /* resolve: .git dir, or follow the `gitdir:` pointer when .git is a file */;
if git_dir.join("rebase-merge").is_dir() || git_dir.join("rebase-apply").is_dir() {
eprintln!("warning: ...");
}
git rev-parse --git-dir gives the correct directory in both the main worktree and linked worktrees, if shelling out is acceptable here.
Impact
Cosmetic but corrosive: it is a warning that tells the user their index may be corrupt when it is not, on a repo that is in a perfectly normal state. It trains users to ignore init warnings. Low priority, not release blocking.
Suggested test
A regression test would create a temp repo, run and abort a rebase so REBASE_HEAD remains, and assert no warning is emitted. A second case would assert the warning is emitted while rebase-merge/ exists.
Found via
Dogfooding during retrieval-agent benchmark work. Located with the project's own tooling:
$ ./target/release/travsr pattern "REBASE_HEAD|rebase-merge|rebase-apply|rebase is in progress" --scope crates/
3 match(es):
crates/travsr-daemon/src/lib.rs:1424:23: // L13: warn if a rebase is in progress
crates/travsr-daemon/src/lib.rs:1426:37: if repo_root.join(".git").join("REBASE_HEAD").exists() {
crates/travsr-daemon/src/lib.rs:1428:29: "warning: a git rebase is in progress, consider finishing or aborting it \
Summary
travsr initprints a "a git rebase is in progress" warning on repos where no rebase is in progress. The check tests for.git/REBASE_HEAD, which git leaves behind permanently after a rebase finishes or is aborted. It is not an in-progress signal.The practical effect is that once a user has ever run a rebase in a repo, every subsequent
travsr inittells them their index may contain conflict markers, forever.Repro
Observed on this repo at
d68b4aa8:State of the repo at that moment:
Actual
Warning is printed. The index is fine.
Expected
No warning, because no rebase is in progress.
Root cause
crates/travsr-daemon/src/lib.rs:1426, insideinit_repo_with_progress(defined at line 1091):REBASE_HEADis written during a rebase and is not removed when the rebase completes or is aborted, so its presence says only "a rebase happened here at some point". The in-progress condition git itself uses is the existence of the state directory.git/rebase-merge/(interactive and merge backend) or.git/rebase-apply/(am backend). Both are removed on completion and on--abort.Introduced in e942ed4 (
RFC-018 embedding plugin + UX hardening, #364) as item L13.Secondary defect in the same line: worktrees
repo_root.join(".git")assumes.gitis a directory. In a linked worktree.gitis a file containing agitdir:pointer, so<root>/.git/REBASE_HEADnever exists and the warning can never fire there, even during a genuine rebase. Rebase state for a linked worktree lives under.git/worktrees/<name>/rebase-merge/.This repo currently has linked worktrees, including agent worktrees under
.claude/worktrees/, so the path is reachable in normal use:So the current check is wrong in both directions: it false-positives in the main worktree, and false-negatives in linked worktrees.
Suggested fix
Resolve the real git dir rather than assuming
.gitis a directory, then test for the rebase state directories:git rev-parse --git-dirgives the correct directory in both the main worktree and linked worktrees, if shelling out is acceptable here.Impact
Cosmetic but corrosive: it is a warning that tells the user their index may be corrupt when it is not, on a repo that is in a perfectly normal state. It trains users to ignore init warnings. Low priority, not release blocking.
Suggested test
A regression test would create a temp repo, run and abort a rebase so
REBASE_HEADremains, and assert no warning is emitted. A second case would assert the warning is emitted whilerebase-merge/exists.Found via
Dogfooding during retrieval-agent benchmark work. Located with the project's own tooling: