pcottle/learnGitBranching · error · GitError
git-error-switch-detach
Error message
git-error-switch-detach
What it means
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.
Source
Thrown at src/js/git/commands.js:1201
if (detachOption) {
// "-d" / "--detach" explicitly asks to check out a commit-ish and leave
// HEAD detached there. Like "-t" above, a ref sitting right after the
// flag gets attached to it by the greedy option parser, so fold it back
// into the general args before we read it.
let args = detachOption.concat(generalArgs);
command.validateArgBounds(args, 1, 1, '-d');
engine.checkout(engine.crappyUnescape(args[0]));
return;
}
command.validateArgBounds(generalArgs, 1, 1);
// Unlike "git checkout", "git switch" will not silently leave you on a
// detached HEAD. If the target isn't a branch (i.e. it's a commit or a
// tag), refuse and point the user at "--detach", matching real git.
var target = engine.crappyUnescape(generalArgs[0]);
if (engine.getType(target) !== 'branch') {
throw new GitError({
msg: intl.str('git-error-switch-detach', { ref: generalArgs[0] })
});
}
engine.checkout(target);
}
}
};
var instantCommands = [
// "git help {command}" is handled over in the sandbox commands, so only
// grab the bare forms here
[/^git +help *$|^git *$/, function() {
var lines = [
intl.str('git-version'),
'<br/>',
intl.str('git-usage'),
escapeString(intl.str('git-usage-command')),View on GitHub (pinned to 5b09d0ff96)
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
Example fix
// before git switch c3 // after git switch --detach c3
Defensive patterns
Strategy: type-guard
Validate before calling
var target = engine.crappyUnescape(args[0]);
if (engine.getType(target) === 'branch') { engine.switch(target); } else { /* use --detach */ } Type guard
function isBranchRef(engine, name){ return engine.getType(engine.crappyUnescape(name)) === 'branch'; } Prevention
- Reserve switch for branches; use --detach for commits/tags
- Prefer checkout when you want implicit detach behavior
When it happens
Trigger: `git switch <commit-sha>` or `git switch <tag>` where engine.getType(target) !== 'branch'.
Common situations: Muscle memory from checkout applied to switch; trying to inspect an old commit via switch.
Related errors
- Git pull can not be executed in detached HEAD mode if no rem
- fatal: HEAD does not point to a branch
- git-error-reset-detached
- git-error-exist
- cannot fetch to ' + ref + ' when checked out on ' + ref
AI-assisted analysis of pcottle/learnGitBranching@5b09d0ff96 (2026-08-27).
Data as JSON: /api/errors/ad1606f1d2193716.
Report an issue: GitHub.