{"record":{"id":"a1151ca9cf78ae42","repo":"elastic/elasticsearch","slug":"changelog-directory-contains-changes-that-will-be","errorCode":null,"errorMessage":"Changelog directory contains changes that will be wiped out by this task:\n{changelogDirectory}\n{output}","messagePattern":"Changelog directory contains changes that will be wiped out by this task:\n(.+?)\n(.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/BundleChangelogsTask.java","lineNumber":225,"sourceCode":"            entries.sort(changelogEntryComparator());\n\n            ChangelogBundle bundle = new ChangelogBundle(version, finalize, Instant.now().toString(), entries);\n\n            yamlMapper.writeValue(new File(\"docs/release-notes/changelog-bundles/\" + version + \".yml\"), bundle);\n        } finally {\n            if (didCheckoutChangelogs) {\n                gitWrapper.runCommand(\"git\", \"restore\", \"-s@\", \"-SW\", \"--\", changelogDirectory.get().toString());\n            }\n        }\n    }\n\n    private void checkoutChangelogs(GitWrapper gitWrapper, String upstream, String ref) {\n        gitWrapper.updateRemote(upstream);\n\n        // If the changelog directory contains modified/new files, we should error out instead of wiping them out silently\n        var output = gitWrapper.runCommand(\"git\", \"status\", \"--porcelain\", changelogDirectory.get().toString()).trim();\n        if (output.isEmpty() == false) {\n            throw new IllegalStateException(\n                \"Changelog directory contains changes that will be wiped out by this task:\\n\" + changelogDirectory.get() + \"\\n\" + output\n            );\n        }\n\n        gitWrapper.runCommand(\"rm\", \"-rf\", changelogDirectory.get().toString());\n        var refSpec = upstream + \"/\" + ref;\n        if (ref.contains(\"upstream/\")) {\n            refSpec = ref.replace(\"upstream/\", upstream + \"/\");\n        } else if (ref.matches(\"^[0-9a-f]+$\")) {\n            refSpec = ref;\n        }\n        gitWrapper.runCommand(\"git\", \"checkout\", refSpec, \"--\", changelogDirectory.get().toString());\n    }\n\n    private void addChangelogsFromRef(GitWrapper gitWrapper, String upstream, String ref) {\n        var refSpec = upstream + \"/\" + ref;\n        if (ref.contains(\"upstream/\")) {\n            refSpec = ref.replace(\"upstream/\", upstream + \"/\");","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/BundleChangelogsTask.java#L207-L243","documentation":"Thrown by BundleChangelogsTask.checkoutChangelogs before running `git rm -rf` on the changelog directory. It runs `git status --porcelain <changelogDir>`; if any output is produced (modified, staged, or untracked files exist), the task aborts to avoid silently destroying uncommitted changelog work during the checkout/restore sequence.","triggerScenarios":"The task is about to checkout changelog YAMLs from a ref into the local changelog directory, which involves `git rm -rf <dir>` followed by `git checkout <ref> -- <dir>`. If the directory currently has uncommitted changes, those would be wiped, so the porcelain check fails fast.","commonSituations":"A developer has local in-progress changelog edits when running the bundling task; an untracked new changelog file was added but not committed; a previous bundling run left the directory dirty; merge conflict resolution left changelog files modified.","solutions":["Commit, stash, or revert local changes in the changelog directory before running bundleChangelogs (git stash or git checkout -- <changelogDir>).","If the changes are intentional and should be preserved, move them out of the directory or commit to a branch first.","Re-run the task once `git status --porcelain <changelogDir>` is empty.","If the dirty state is from a prior failed run, inspect and clean it deliberately rather than letting the task wipe it."],"exampleFix":"// before: dirty changelog dir\n$ git status --porcelain changelogs/\n?? changelogs/heads-up/foo.yaml\n$ ./gradlew bundleChangelogs --branch 8.x  // throws\n// after: stash or commit first\n$ git stash push -- changelogs/\n$ ./gradlew bundleChangelogs --branch 8.x","handlingStrategy":"validation","validationCode":"String dirty = gitRun(\"status\", \"--porcelain\", changelogDir.toString()).trim();\nif (dirty.isEmpty() == false) {\n    throw new IllegalStateException(\"Commit or stash changelog changes first:\\n\" + dirty);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always commit or stash changelog work before running bundleChangelogs.","Run `git status` in the changelog dir as a preflight check in release scripts.","Treat the bundling task as destructive — never run it over uncommitted work."],"tags":["build","gradle","release","changelog","git","data-loss"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}