gitbutlerapp/gitbutler · error
Cannot merge : merging into / resulted in conflicts. Rebase…
Error message
Cannot merge {branch_name}: merging into {fetch_remote_name}/{target_branch_name} resulted in conflicts.{detail} Rebase {branch_name} onto the target and resolve, then re-run `but merge {branch_name}`. What it means
When landing, the library performs a trial merge of the branch into the remote target branch. If that merge produces conflicts, it cannot complete the landing automatically and refuses, listing conflicting paths and instructing the user to rebase first.
Solutions
- Rebase the branch onto the latest target branch and resolve conflicts manually (`but pull --branch` / `git rebase origin/main`), then re-run `but merge <branch>`
- Fetch first to make sure the conflict isn't against a stale view of the target, then retry
- If conflicts are unwanted local edits, drop or rework the offending commits in the branch before landing
Example fix
# before but merge feature-x # error: merging into origin/main resulted in conflicts. Conflicting paths: src/app.rs. # after but pull --branch feature-x git rebase origin/main # resolve conflicts but merge feature-x
Defensive patterns
Strategy: retry
Validate before calling
// dry-run merge check
git fetch origin
let merge_ok = std::process::Command::new("git")
.args(["merge-tree", &feature_oid.to_string(), &target_oid.to_string()])
.output()?.status.success();
if !merge_ok { println!("rebase branch onto target first"); } Try / catch
match land_result {
Err(e) if e.to_string().contains("resulted in conflicts") => {
let detail = e.to_string();
rebase_and_resolve(extract_conflict_paths(detail));
retry_land();
}
other => other?,
} Prevention
- Rebase frequently to keep branches close to the target
- Fetch immediately before landing so conflicts are detected against fresh remote state
- Keep branches short-lived and land them promptly to minimize drift
When it happens
Trigger: Calling `but merge <branch>` where the branch's changes overlap/conflict with changes already on `{fetch_remote}/{target_branch}` — the internal `merge` tree operation returns conflicts with non-empty conflicting paths.
Common situations: A teammate merged competing changes to the same files after your branch diverged; long-lived branch that drifted far from the target; refactoring on both sides touching identical lines.
Understand the failure class
Background: "git command failed": what it means when a tool shells out to git and git exits non-zero — this error's family across 21 libraries.
Related errors
- Encountered conflict when merging tree
- Base commit must exist if provided
- `but merge` does not yet support triangular remotes
- Cannot merge : it shares no history with /
- Cannot squash commits that would result in merge conflicts
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/d0538b161b5389ec.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-api/src/land/merge.rs:102
let mut merge = repo.merge_trees(
base_tree,
our_tree,
their_tree,
repo.default_merge_labels(),
merge_options,
)?;
if merge.has_unresolved_conflicts(unresolved) {
let paths: Vec<String> = merge
.conflicts
.iter()
.filter_map(|c| c.ours.location().to_str().ok().map(ToOwned::to_owned))
.collect();
let detail = if paths.is_empty() {
String::new()
} else {
format!(" Conflicting paths: {}.", paths.join(", "))
};
bail!(
"Cannot merge {branch_name}: merging into {fetch_remote_name}/{target_branch_name} \
resulted in conflicts.{detail} Rebase {branch_name} onto the target and resolve, then \
re-run `but merge {branch_name}`."
);
}
let merged_tree = merge.tree.write()?.detach();
// Build the 2-parent merge commit. Parent order is `[target, feature]` so `--first-parent`
// mainline walks stay correct. `commit_signatures()` honors `gitbutler.gitbutlerCommitter`.
let (author, committer) = repo.commit_signatures()?;
let mut commit = gix::objs::Commit {
tree: merged_tree,
parents: [target_oid, feature_oid].into_iter().collect(),
author,
committer,
encoding: None,
message: format!("Merge branch '{branch_name}'").into(),
extra_headers: Vec::new(),View on GitHub (pinned to 58e5313667)