{"record":{"id":"787ad62f1a097252","repo":"jdx/mise","slug":"global-configuration-has-uncommitted-changes","errorCode":null,"errorMessage":"global configuration has uncommitted changes","messagePattern":"global configuration has uncommitted changes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/remote_repository.rs","lineNumber":257,"sourceCode":"        }\n    }\n    git(&checkout, &[\"remote\", \"set-url\", \"origin\", origin])?;\n    let branch = git(&checkout, &[\"symbolic-ref\", \"--short\", \"HEAD\"])?;\n    git(\n        &checkout,\n        &[\"-c\", \"core.hooksPath=/dev/null\", \"checkout\", &branch],\n    )?;\n    if destination.join(\".git\").exists() {\n        if git(destination, &[\"remote\", \"get-url\", \"origin\"])? != origin {\n            bail!(\"global configuration origin does not match\");\n        }\n        if !git(\n            destination,\n            &[\"status\", \"--porcelain\", \"--untracked-files=no\"],\n        )?\n        .is_empty()\n        {\n            bail!(\"global configuration has uncommitted changes\");\n        }\n        if update {\n            if git(destination, &[\"symbolic-ref\", \"--short\", \"HEAD\"])? != branch {\n                bail!(\"global configuration branch differs from the transferred branch\");\n            }\n            if dry_run {\n                // the bundle holds the history from the checkout's commit on,\n                // so the fast-forward is checked there without fetching into\n                // the destination\n                let head = git(destination, &[\"rev-parse\", \"HEAD\"])?;\n                if head == revision {\n                    miseprintln!(\n                        \"Would keep {shown} at {revision}, already the transferred revision\"\n                    );\n                } else if git(&checkout, &[\"merge-base\", \"--is-ancestor\", &head, revision]).is_ok()\n                {\n                    miseprintln!(\"Would fast-forward {shown} from {head} to {revision}\");\n                } else {","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/remote_repository.rs#L239-L275","documentation":"Before updating or adopting an existing global-configuration checkout, mise requires a clean working tree. `git status --porcelain --untracked-files=no` is run in the destination; any output means tracked files have uncommitted modifications, and mise aborts rather than merging or overwriting user changes.","triggerScenarios":"install/install_source/preview_source (install_at) against a destination with a `.git` directory where any tracked file is modified or staged (untracked files are ignored by the check).","commonSituations":"Hand-edited config files that were never committed; a partially finished `git add`/merge left staged changes; an editor or tool rewrote files (line endings, formatting) since the last commit.","solutions":["Review and commit the pending changes: `git -C <destination> add -A && git -C <destination> commit -m 'local changes'`.","If the edits are unwanted, discard them: `git -C <destination> restore .` (and `git restore --staged .` for staged entries).","Stash them if you want to keep them temporarily: `git -C <destination> stash`.","Re-run the install once `git status --porcelain --untracked-files=no` prints nothing."],"exampleFix":"// before\n$ git -C ~/.config/mise status --porcelain --untracked-files=no\n M settings.toml\n\n// after\n$ git -C ~/.config/mise add settings.toml && git -C ~/.config/mise commit -m 'update settings'\n$ git -C ~/.config/mise status --porcelain --untracked-files=no\n# (empty)","handlingStrategy":"validation","validationCode":"const out = execSync(`git -C ${dest} status --porcelain --untracked-files=no`).toString();\nif (out.trim()) throw new Error('commit or discard changes in ' + dest + ' before installing');","typeGuard":null,"tryCatchPattern":"try {\n  await installSource(bundle, origin, { update: true });\n} catch (e) {\n  if (/uncommitted changes/.test(String(e.cause ?? e))) {\n    execSync(`git -C ${dest} stash`); // or commit\n    return installSource(bundle, origin, { update: true });\n  }\n  throw e;\n}","preventionTips":["Commit or stash edits to global config immediately instead of leaving them dirty","Check `git status --porcelain --untracked-files=no` is empty before running updates","Disable editors/tools that rewrite config files (formatters, line-ending conversion) in the checkout"],"tags":["git","dirty-worktree","uncommitted-changes","configuration"],"backgroundTag":"git-command-failed","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}