pcottle/learnGitBranching · error · GitError

git-error-already-exists

Error message

git-error-already-exists

What it means

Cherry-pick refuses a commit that is already an ancestor of HEAD (in Graph.getUpstreamSet of HEAD). Mirrors git's 'The previous cherry-pick is now empty' / already-applied behavior; the msg key is git-error-already-exists.

Source

Thrown at src/js/git/commands.js:227

  },

  cherrypick: {
    displayName: 'cherry-pick',
    regex: /^git +cherry-pick($|\s)/,
    description: 'Apply changes from existing commits',
    execute: function(engine, command) {
      var commandOptions = command.getOptionsMap();
      var generalArgs = command.getGeneralArgs();

      command.validateArgBounds(generalArgs, 1, Number.MAX_VALUE);

      var set = Graph.getUpstreamSet(engine, 'HEAD');
      // first resolve all the refs (as an error check)
      var toCherrypick = generalArgs.map(function (arg) {
        var commit = engine.getCommitFromRef(arg);
        // and check that its not upstream
        if (set[commit.get('id')]) {
          throw new GitError({
            msg: intl.str(
              'git-error-already-exists',
              { commit: commit.get('id') }
            )
          });
        }
        return commit;
      }, this);

      engine.setupCherrypickChain(toCherrypick);
    }
  },

  gc: {
    displayName: 'gc',
    regex: /^git +gc($|\s)/,
    description: 'Cleanup unnecessary files and optimize the repository',
    execute: function(engine, command) {

View on GitHub (pinned to 5b09d0ff96)

Solutions

  1. Verify the commit isn't upstream: git log / check Graph.getUpstreamSet before cherry-picking
  2. Skip that commit — it's already applied
  3. If you want a duplicate commit, the simulator deliberately disallows it

Example fix

// before
git checkout main; git cherry-pick C2  // C2 already in main
// after
git log --graph  # confirm, then cherry-pick only missing commits like C3
Defensive patterns

Strategy: validation

Validate before calling

var upstream = Graph.getUpstreamSet(engine, 'HEAD'); var c = engine.getCommitFromRef(arg); if (upstream[c.get('id')]) skip(arg);

Type guard

function isAlreadyApplied(engine, sha) { return !!Graph.getUpstreamSet(engine, 'HEAD')[sha]; }

Prevention

When it happens

Trigger: git cherry-pick <sha> where <sha> is reachable from HEAD — e.g. cherry-picking C2 while sitting on a branch that already contains C2.

Common situations: Re-applying a commit after a rebase already incorporated it; copy-pasting an old SHA.

Related errors


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