gitbutlerapp/gitbutler · warning
No committed changes to discard
Error message
No committed changes to discard
What it means
When discarding committed files (DiscardOperation::CommittedFiles), the code builds DiffSpecs for each (source commit, path) pair via DiffSpecBuilder::push_changes_from_committed_file, then asserts the result is non-empty with anyhow::ensure!. The error means every listed path produced no diff against the source commit — nothing would be reverted, so the (transactional, undo-recorded) discard is refused rather than recorded as a no-op.
Source
Thrown at crates/but/src/command/legacy/discard.rs:428
commits.push(commit);
}
}
commits
};
ExecutableDiscardOperation::Branches { branches, commits }
}
DiscardOperation::Commits(commits) => ExecutableDiscardOperation::Commits(commits),
DiscardOperation::CommittedFiles { source, paths } => {
let changes = {
let context_lines = ctx.settings.context_lines;
let (repo, ..) = ctx.workspace_and_db_mut_with_perm(perm.read_permission())?;
let mut builder = DiffSpecBuilder::new(&repo, context_lines);
for path in &paths {
builder.push_changes_from_committed_file(source.commit_id, path.as_bstr())?;
}
builder.into_diff_specs()
};
anyhow::ensure!(!changes.is_empty(), "No committed changes to discard");
ExecutableDiscardOperation::CommittedFiles {
source,
paths,
changes,
}
}
DiscardOperation::Uncommitted(selection) => {
let changes = {
let context_lines = ctx.settings.context_lines;
let (repo, ..) = ctx.workspace_and_db_mut_with_perm(perm.read_permission())?;
let mut builder = DiffSpecBuilder::new(&repo, context_lines);
match selection {
UncommittedSelection::All => builder.push_changes_from_uncommitted_area()?,
UncommittedSelection::Changes(changes) => {
for change in *changes {
match change {
UncommittedDiscardSource::HunkOrFile(change) => {
builder.push_changes_from_uncommitted(&change)?;View on GitHub (pinned to caf1f223d3)
Solutions
- Verify there is actually something to revert: `git diff <source_commit> -- <paths>` should show output before you discard.
- If files are already restored, no action is needed — this error is the safe no-op guard.
- Check exact path spelling/casing against `git ls-tree <commit>` output.
Example fix
# before $ but discard --files src/main.rs --from <sha> # already reverted earlier Error: No committed changes to discard # after: confirm there is a diff first $ git diff <sha> -- src/main.rs # shows hunks, then retry; empty means nothing to do
Defensive patterns
Strategy: validation
Validate before calling
// Confirm a diff exists before discarding committed files
let has_changes = paths.iter().any(|p| {
repo.diff_tree_to_path(source.commit_id, Some(p)).lines().count() > 0
});
anyhow::ensure!(has_changes, "nothing differs; skip the discard entirely"); Try / catch
if let Err(e) = discard_committed_files(ctx, source, paths) {
if e.to_string().contains("No committed changes to discard") {
// already clean — treat as success
return Ok(());
}
return Err(e);
} Prevention
- Diff-check paths against the source commit before invoking discard.
- Don't re-run discard commands from history; check state first.
When it happens
Trigger: Calling discard-committed-files with paths that are identical in the source commit and the current state (already reverted, or the paths never differed), or with paths misspelled/case-mismatched so each push_changes_from_committed_file contributes nothing.
Common situations: Re-running a discard command from history after the first run already restored the files; path casing on case-insensitive filesystems; passing directory paths expecting recursion when only exact file specs match.
Related errors
- No uncommitted changes to discard
- Failed to communicate with LM Studio server: ${error instanc
- When using LM Studio, you must provide a valid endpoint
- Invalid response: ${JSON.stringify(result)}
- When using OpenAI in a bring your own key configuration, you
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/857eb25cd15bfbeb.
Report an issue: GitHub.