xai-org/grok-build · error · anyhow::Error
local '{target_branch}' has diverged from origin; resolve be
Error message
local '{target_branch}' has diverged from origin; resolve before publishing: {} What it means
During publish, after fetching origin, a `git merge --ff-only FETCH_HEAD` is attempted to sync the local target branch; if it is not a fast-forward, the local branch has diverged from origin, and the code checks out the session branch and bails so a human resolves the divergence before publishing.
Source
Thrown at crates/codegen/xai-grok-workspace/src/session/git.rs:3263
);
let (fetched, _) = git_cli_raw(
git_root,
&["fetch", "origin", "--end-of-options", target_branch],
)
.await?;
checkout_branch(git_root, target_branch, false).await?;
if fetched
&& !git_cli_raw(
git_root,
&["merge-base", "--is-ancestor", "FETCH_HEAD", "HEAD"],
)
.await?
.0
{
let (ff, ff_out) = git_cli_raw(git_root, &["merge", "--ff-only", "FETCH_HEAD"]).await?;
if !ff {
let _ = checkout_branch(git_root, conv_branch, false).await;
anyhow::bail!(
"local '{target_branch}' has diverged from origin; resolve before publishing: {}",
scrub_git_output(&ff_out)
);
}
}
if git_cli_raw(
git_root,
&["merge-base", "--is-ancestor", conv_branch, "HEAD"],
)
.await?
.0
{
let sha = git_cli(git_root, &["rev-parse", "HEAD"]).await?;
let push_res = push_merged_target_if_requested(git_root, target_branch, push).await;
checkout_branch(git_root, conv_branch, false).await?;
push_res?;
return Ok(GitMergeToMainResult {
outcome: GitMergeToMainOutcome::UpToDate { sha },View on GitHub (pinned to bc7f02eddd)
Solutions
- Rebase or merge origin/target_branch into the local target branch and resolve conflicts, then re-run publish
- Reset local target to origin if local-only commits are unwanted: `git branch -f target origin/target` (after confirming)
- Coordinate with whoever pushed the divergent commits
- Re-run the flow after syncing so the merge becomes a fast-forward
Example fix
// before publish(git_root, push=true).await?; // diverged -> bail // after git fetch origin git rebase origin/main # or merge, resolving conflicts publish(git_root, push=true).await?;
Defensive patterns
Strategy: validation
Validate before calling
std::process::Command::new("git").arg("-C").arg(git_root).args(["fetch","origin"]).output()?;
let behind = std::process::Command::new("git").arg("-C").arg(git_root)
.args(["rev-list","--count",&format!("{}..origin/{}","main","main")]).output()?;
if behind.stdout.trim() != "0" { anyhow::bail!("local main is behind/diverged; sync first"); } Type guard
fn ff_possible(local: &str, remote: &str) -> bool {
// merge-base(local, remote) == local rev-parse implies fast-forward
true // compute via git merge-base in practice
} Try / catch
match merge_to_main(git_root, session_branch, push).await {
Err(e) if e.to_string().contains("has diverged from origin") => {
// rebase/merge origin/<target> locally, resolve, then re-run
git_cli(git_root, &["fetch","origin"]).await?;
return Err(e.context("resolve divergence then retry publish"));
}
other => other,
} Prevention
- Fetch and check rev-list counts before publishing
- Avoid force-pushes to shared target branches
- Rebase session work onto target regularly to keep ff possible
- Coordinate direct pushes to the target branch with the team
When it happens
Trigger: Calling the merge-to-main/publish flow when origin's target branch has commits that the local target branch does not have (e.g. someone else pushed, or the branch was force-updated on the remote).
Common situations: Teammate merged directly to main while a session was in progress; remote branch rebased/force-pushed; local publish ran against a stale fetch.
Related errors
- merge of base ref '{base}' failed: {merge_out}
- merge of '{conv_branch}' into '{target_branch}' failed: {}
- git reset --hard {} failed: {}
- git clean {} failed: {}
- git checkout {} failed: {}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/b02ed7cce699bd12.
Report an issue: GitHub.