gitbutlerapp/gitbutler · error · anyhow::Error
line {line_number}: unknown command '{other}'
Error message
line {line_number}: unknown command '{other}' What it means
Raised by `parse_integration_steps_script` when the first token of a non-empty, non-comment line is not `pick`, `merge`, or `squash`. The integration grammar is deliberately much smaller than git rebase's todo grammar; there is no drop/reword/edit/fixup/exec.
Source
Thrown at crates/but-workspace/src/branch/integrate_branch_upstream/parsing.rs:101
.map(|commit| {
resolve_commit(commit, &allowed_commits).map_err(|err| {
anyhow::anyhow!(
"line {line_number}: invalid squash commit '{commit}': {err}"
)
})
})
.collect::<Result<Vec<_>>>()?;
InteractiveIntegrationStep::Squash {
commits,
message: message_part
.map(parse_message_clause)
.transpose()
.map_err(|err| {
anyhow::anyhow!("line {line_number}: invalid squash message: {err}")
})?,
}
}
other => bail!("line {line_number}: unknown command '{other}'"),
};
steps.push(step);
}
Ok(steps)
}
fn render_step(step: &InteractiveIntegrationStep) -> String {
match step {
InteractiveIntegrationStep::Pick { commit_id } => format!("pick {}", short_id(*commit_id)),
InteractiveIntegrationStep::Merge { commit_id } => {
format!("merge {}", short_id(*commit_id))
}
InteractiveIntegrationStep::Squash { commits, message } => {
let mut rendered = format!(
"squash {}",
commits
.iter()View on GitHub (pinned to caf1f223d3)
Solutions
- Map your intent to the supported verbs: omit lines you don't want (there is no drop — deleting the line drops the commit), use pick/merge/squash only.
- Put explanatory text behind a leading `#` so it is treated as a comment.
- Re-generate the baseline with `render_integration_steps_script(&initial_steps)` and edit from that.
Example fix
# before reword 4f2a9c1 # after # (delete the line to skip the commit, or keep it as:) pick 4f2a9c1
Defensive patterns
Strategy: validation
Validate before calling
fn is_known_command(cmd: &str) -> bool { matches!(cmd, "pick" | "merge" | "squash") }
// lint pass before parse:
for (i, line) in script.lines().enumerate() {
let t = line.trim();
if t.is_empty() || t.starts_with('#') { continue; }
if let Some(cmd) = t.split_whitespace().next() {
if !is_known_command(cmd) { warn_user_line(i + 1, cmd); }
}
} Try / catch
if let Err(err) = parse_integration_steps_script(&script, &divergence) {
// 'line {n}: unknown command ...' — offer mapping hints (drop -> delete line, reword -> squash message)
} Prevention
- Show the supported verbs (pick/merge/squash) in the editor; comments start with '#'.
- Warn when pasted content looks like a git-rebase todo (contains drop/reword/edit/fixup/exec).
When it happens
Trigger: Lines like `drop 4f2a9c1`, `reword 4f2a9c1`, `edit 4f2a9c1`, `fixup 4f2a9c1`, `exec make`, or a stray non-comment sentence. Empty lines and lines starting with `#` are skipped, so comments are the only annotation allowed.
Common situations: Pasting a `git rebase -i` todo into the integration editor; muscle-memory rebase commands; tools that emit rebase todos reused for this script.
Related errors
- line {line_number}: pick does not accept a message clause
- line {line_number}: pick requires exactly one commit
- line {line_number}: merge does not accept a message clause
- line {line_number}: merge requires exactly one commit
- line {line_number}: squash requires at least two commits
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/c10cace7e859c538.
Report an issue: GitHub.