{"record":{"id":"ad1606f1d2193716","repo":"pcottle/learnGitBranching","slug":"git-error-switch-detach","errorCode":null,"errorMessage":"git-error-switch-detach","messagePattern":"git-error-switch-detach","errorType":"exception","errorClass":"GitError","httpStatus":null,"severity":"error","filePath":"src/js/git/commands.js","lineNumber":1201,"sourceCode":"      if (detachOption) {\n        // \"-d\" / \"--detach\" explicitly asks to check out a commit-ish and leave\n        // HEAD detached there. Like \"-t\" above, a ref sitting right after the\n        // flag gets attached to it by the greedy option parser, so fold it back\n        // into the general args before we read it.\n        let args = detachOption.concat(generalArgs);\n        command.validateArgBounds(args, 1, 1, '-d');\n        engine.checkout(engine.crappyUnescape(args[0]));\n        return;\n      }\n\n      command.validateArgBounds(generalArgs, 1, 1);\n\n      // Unlike \"git checkout\", \"git switch\" will not silently leave you on a\n      // detached HEAD. If the target isn't a branch (i.e. it's a commit or a\n      // tag), refuse and point the user at \"--detach\", matching real git.\n      var target = engine.crappyUnescape(generalArgs[0]);\n      if (engine.getType(target) !== 'branch') {\n        throw new GitError({\n          msg: intl.str('git-error-switch-detach', { ref: generalArgs[0] })\n        });\n      }\n\n      engine.checkout(target);\n    }\n  }\n};\n\nvar instantCommands = [\n  // \"git help {command}\" is handled over in the sandbox commands, so only\n  // grab the bare forms here\n  [/^git +help *$|^git *$/, function() {\n    var lines = [\n      intl.str('git-version'),\n      '<br/>',\n      intl.str('git-usage'),\n      escapeString(intl.str('git-usage-command')),","sourceCodeStart":1183,"sourceCodeEnd":1219,"githubUrl":"https://github.com/pcottle/learnGitBranching/blob/5b09d0ff9678cad164f5a7488a279a44f90d7256/src/js/git/commands.js#L1183-L1219","documentation":"Unlike checkout, `git switch` refuses to land on a detached HEAD. If the target resolves to anything other than a branch (a commit SHA or a tag), the simulation throws and points the user at --detach, matching real git behavior.","triggerScenarios":"`git switch <commit-sha>` or `git switch <tag>` where engine.getType(target) !== 'branch'.","commonSituations":"Muscle memory from checkout applied to switch; trying to inspect an old commit via switch.","solutions":["Use `git switch --detach <ref>` to intentionally detach","Switch to a branch name instead of a SHA/tag","Use `git checkout <ref>` if you want the old auto-detach behavior"],"exampleFix":"// before\ngit switch c3\n// after\ngit switch --detach c3","handlingStrategy":"type-guard","validationCode":"var target = engine.crappyUnescape(args[0]);\nif (engine.getType(target) === 'branch') { engine.switch(target); } else { /* use --detach */ }","typeGuard":"function isBranchRef(engine, name){ return engine.getType(engine.crappyUnescape(name)) === 'branch'; }","tryCatchPattern":null,"preventionTips":["Reserve switch for branches; use --detach for commits/tags","Prefer checkout when you want implicit detach behavior"],"tags":["git","switch","detached-head"],"backgroundTag":"git-switch-detach-required","analyzedSha":"5b09d0ff9678cad164f5a7488a279a44f90d7256","analyzedAt":"2026-08-27T13:53:49.057Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}