pcottle/learnGitBranching · error · GitError

-m and -d are incompatible

Error message

-m and -d are incompatible

What it means

`hg branch` in mercurial mode maps its options onto git's branch machinery, but -m (rename/move) and -d (delete) are mutually exclusive operations on a branch. If the parsed options map contains both, a GitError with intl.todo('-m and -d are incompatible') is thrown before any delegation.

Source

Thrown at src/js/mercurial/commands.js:108

  },

  bookmark: {
    regex: /^hg (bookmarks|bookmark|book)($|\s)/,
    options: [
      '-r',
      '-f',
      '-d'
    ],
    delegate: function(engine, command) {
      var options = command.getOptionsMap();
      var generalArgs = command.getGeneralArgs();
      var branchName;
      var rev;

      var delegate = {vcs: 'git'};

      if (options['-m'] && options['-d']) {
        throw new GitError({
          msg: intl.todo('-m and -d are incompatible')
        });
      }
      if (options['-d'] && options['-r']) {
        throw new GitError({
          msg: intl.todo('-r is incompatible with -d')
        });
      }
      if (options['-m'] && options['-r']) {
        throw new GitError({
          msg: intl.todo('-r is incompatible with -m')
        });
      }
      if (generalArgs.length + (options['-r'] ? options['-r'].length : 0) +
          (options['-d'] ? options['-d'].length : 0) === 0) {
        delegate.name = 'branch';
        return delegate;
      }

View on GitHub (pinned to 5b09d0ff96)

Solutions

  1. Use only one of -m or -d per command
  2. If building commands programmatically, validate that -m and -d are not both set before dispatching
  3. Split the operation into two sequential commands

Example fix

// before
hg branch -m old -d
// after
hg branch -m old newname
hg branch -d oldname
Defensive patterns

Strategy: validation

Validate before calling

function validBranchOpts(o) { return !(o['-m'] && o['-d']); }
if (!validBranchOpts(command.getOptionsMap())) { reject('pick -m or -d, not both'); }

Type guard

function hasExclusiveOpts(o, a, b) {
  return !(Boolean(o[a]) && Boolean(o[b]));
}

Try / catch

try { exec(cmd); } catch (e) { if (e instanceof GitError && /incompatible/.test(e.msg)) { showUsage(); } else throw e; }

Prevention

When it happens

Trigger: Executing `hg branch` with both -m and -d options in the options map, e.g. `hg branch -m foo -d`.

Common situations: Typos or copy-pasted command strings combining flags; automated command builders that concatenate user-chosen options without validating mutual exclusion.

Related errors


AI-assisted analysis of pcottle/learnGitBranching@5b09d0ff96 (2026-08-27). Data as JSON: /api/errors/859162d70f24346c. Report an issue: GitHub.