gitbutlerapp/gitbutler · error
No changes were provided to uncommit
Error message
No changes were provided to uncommit
What it means
uncommit_changes_from_commits requires at least one change source (a commit or reference to changes). After grouping the provided sources by commit id, if the resulting group list is empty there is nothing to uncommit, so the function bails early instead of producing a meaningless outcome.
Solutions
- Check that the source list is non-empty before calling; return early in the caller if nothing is selected
- If the input derives from user selection, prompt the user to select changes first
- Treat the error as a no-op signal in batch flows and continue
Example fix
// before
but.uncommit_changes_from_commits(selection); // panics/bails when selection is empty
// after
if selection.is_empty() { return Ok(()); }
but.uncommit_changes_from_commits(selection); Defensive patterns
Strategy: validation
Validate before calling
if sources.is_empty() { return; } // skip call entirely
but.uncommit_changes_from_commits(editor, sources, context_lines)?; Try / catch
match result {
Err(e) if e.to_string().contains("No changes were provided") => Ok(Default::default()), // treat as no-op
other => other,
} Prevention
- Always check selection emptiness at the UI/CLI boundary
- Fail fast in callers that gather change sources
- Treat empty input as an explicit no-op path
When it happens
Trigger: Calling uncommit_changes_from_commits with an empty iterator of UncommitChangesSource, or with sources that all filter/group down to nothing (e.g. an empty slice passed programmatically).
Common situations: UI/CLI code that collects selected changes and passes an empty selection; automation scripts where an earlier step produced no selections; callers that skip the empty-input check.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Need at least 2 commits to squash
- no commit IDs provided for discard
- No commits were provided to move
- Aborting due to empty branch name
- Aborting due to empty
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/7ae23ce979db4cc6.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-workspace/src/commit/uncommit_changes.rs:98
rebase,
commit_selector,
})
}
/// Removes changes from multiple commits, grouped by commit id and applied in
/// child-to-parent order.
///
/// Invalid or inapplicable grouped sources are collected in `failures`. When at
/// least one source succeeds, all successful replacements are rebased once at
/// the end. When no source succeeds, `rebase` is `None`.
pub fn uncommit_changes_from_commits<'ws, 'meta, M: RefMetadata>(
mut editor: Editor<'ws, 'meta, M>,
sources: impl IntoIterator<Item = UncommitChangesSource>,
context_lines: u32,
) -> Result<UncommitChangesFromCommitsOutcome<'ws, 'meta, M>> {
let groups = group_sources_by_commit(sources);
if groups.is_empty() {
bail!("No changes were provided to uncommit")
}
// Index groups by commit id so the apply loop below is O(n) rather than
// re-scanning `groups` for every ordered commit. Each commit id is unique
// after grouping, so this map is 1:1.
let group_by_commit: HashMap<gix::ObjectId, usize> = groups
.iter()
.enumerate()
.map(|(index, group)| (group.commit_id, index))
.collect();
let mut failures = Vec::new();
let mut valid_commit_ids = Vec::new();
for group in &groups {
match editor.find_selectable_commit(group.commit_id) {
Ok((_selector, commit)) => {
if commit.clone().attach(editor.repo()).is_conflicted() {
failures.push(failure(View on GitHub (pinned to 58e5313667)