nikivdev/code · error
Git operation in progress. Run `f git-repair` first.
Error message
Git operation in progress. Run `f git-repair` first.
What it means
ensure_git_not_busy guards destructive/reorganizing operations by checking the git dir for in-progress state: rebase, merge, cherry-pick (CHERRY_PICK_HEAD), revert (REVERT_HEAD), bisect (BISECT_LOG), or unmerged files. If any is present it bails so the wrapper doesn't run jj operations on top of a half-finished git operation.
Source
Thrown at src/jj.rs:3551
.args(["show-ref", "--verify", name])
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.status()
.map(|s| s.success())
.unwrap_or(false)
}
fn ensure_git_not_busy(repo_root: &Path) -> Result<()> {
let git_dir = git_dir(repo_root)?;
let rebase = git_dir.join("rebase-merge").exists() || git_dir.join("rebase-apply").exists();
let merge = git_dir.join("MERGE_HEAD").exists();
let cherry_pick = git_dir.join("CHERRY_PICK_HEAD").exists();
let revert = git_dir.join("REVERT_HEAD").exists();
let bisect = git_dir.join("BISECT_LOG").exists();
let unmerged = git_unmerged_files(repo_root);
if rebase || merge || cherry_pick || revert || bisect || !unmerged.is_empty() {
bail!("Git operation in progress. Run `f git-repair` first.");
}
Ok(())
}
fn git_unmerged_files(repo_root: &Path) -> Vec<String> {
let output = Command::new("git")
.current_dir(repo_root)
.args(["diff", "--name-only", "--diff-filter=U"])
.output();
match output {
Ok(out) => String::from_utf8_lossy(&out.stdout)
.lines()
.filter(|l| !l.trim().is_empty())
.map(|l| l.trim().to_string())
.collect(),
Err(_) => Vec::new(),
}
}View on GitHub (pinned to a747e741ae)
Solutions
- Run `f git-repair` as the message instructs, which aborts/cleans the in-progress operation.
- Alternatively finish or abort manually: `git rebase --abort`, `git merge --abort`, `git cherry-pick --abort`, `git bisect reset`, then resolve unmerged files with `git status`.
- Re-run your flow command once the repo is clean.
Example fix
// before flow sync # blocked: REBASE_HEAD present // after f git-repair flow sync
Defensive patterns
Strategy: validation
Validate before calling
// shell: detect in-progress git state before flow commands
GIT_DIR=$(git rev-parse --git-dir) || exit 1
for f in rebase-merge rebase-apply MERGE_HEAD CHERRY_PICK_HEAD REVERT_HEAD BISECT_LOG; do
[ -e "$GIT_DIR/$f" ] && { echo "git operation in progress: $f — run f git-repair" >&2; exit 1; }
done
[ -z "$(git ls-files -u)" ] || { echo "unmerged files present" >&2; exit 1; } Try / catch
match flow_sync() {
Err(e) if e.contains("Git operation in progress") => {
run("f git-repair");
flow_sync()
}
r => r,
} Prevention
- Finish or abort raw git rebase/merge/cherry-pick sessions immediately; never leave them parked.
- Prefer jj-native operations in colocated repos to avoid mixed state.
- Add a pre-flight check for $GIT_DIR sentinel files in CI and scripts.
When it happens
Trigger: Running a flow command that calls ensure_git_not_busy while .git contains REBASE/MERGE/CHERRY_PICK/REVERT_HEAD or BISECT_LOG, or `git ls-files -u` (git_unmerged_files) returns unresolved conflict entries.
Common situations: A previous `git rebase`/`git merge` was interrupted or left mid-conflict; a cherry-pick stopped on conflicts; bisect still active; someone used raw git alongside the jj colocated repo.
Related errors
- {} exists but is not a git repo: {}
- failed to restore sync auto-stash automatically: {} Run `:sy
- failed to restore sync auto-stash automatically: {} Run `git
- failed to resolve HEAD commit
- jj git export retry loop should always return
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/9c32469cd932eba5.
Report an issue: GitHub.