After running `./gradlew wrapper --gradle-version 9.0`, a colleague notices `gradlew` and `gradle-wrapper.jar` are unchanged in git, only the properties file changed. Is that a problem, and how do you ensure the jar/scripts are updated?
answer
- pass 1 writes distributionUrl only
- scripts/jar emitted by executing version
- run task twice for major upgrade
- minor bumps → no-op diff is fine
- commit whatever changed together
basics
~20 sNot necessarily a problem — the first run only rewrites distributionUrl; it doesn't always regenerate the scripts/jar. Run the wrapper task a second time (now under the new version) so gradlew, gradlew.bat, and gradle-wrapper.jar are regenerated.
solid answer
~40 sWhen you run the `wrapper` task, the old wrapper updates `distributionUrl` in `gradle-wrapper.properties`. The launcher scripts and `gradle-wrapper.jar` are produced by the version that *executes the task*, which on the first run is still the old version — so they may show no diff. To get the jar and scripts that ship with the target version, run the task **again**: the second invocation now runs under Gradle 9.0 (downloaded via the freshly written URL) and regenerates `gradlew`, `gradlew.bat`, and `gradle-wrapper.jar` to match. This two-pass pattern is standard for major upgrades. For most minor bumps the scripts/jar rarely change, so an unchanged diff there is harmless; but for major upgrades or if the jar format/wrapper logic changed, the second run matters.
code
bash · 3 lines./gradlew wrapper --gradle-version 9.0 # updates distributionUrl (still old engine)
./gradlew wrapper --gradle-version 9.0 # re-run under 9.0 -> regenerates scripts + jar
git status # expect gradle-wrapper.properties, possibly gradlew(.bat), gradle-wrapper.jargo deeper
Recognize that the second run regenerates the scripts/jar; one run may only change properties.
Explain that scripts/jar come from the executing version, hence the two-pass pattern.
Distinguish when the second pass matters (major vs minor) and what to commit for a consistent wrapper.
Bake the two-pass upgrade into team runbooks/automation so wrapper artifacts never drift across repos.
## Why only the properties file changed The `wrapper` task does two conceptually different things: 1. **Write `distributionUrl`** into `gradle-wrapper.properties` for the requested `--gradle-version`. 2. **Emit the launcher scripts and bootstrap jar** (`gradlew`, `gradlew.bat`, `gradle-wrapper.jar`). Step 1 reflects the *requested* version. Step 2, however, is produced by the Gradle version **currently executing the task** — and on your first run that's still the *old* version. The old version typically writes byte-identical scripts/jar to what's already committed, so git shows no diff there. Only the properties file changed. That's expected, not a bug. ## How to refresh scripts and jar Run the task a second time: ```bash ./gradlew wrapper --gradle-version 9.0 # pass 1: distributionUrl -> 9.0 ./gradlew wrapper --gradle-version 9.0 # pass 2: now runs under 9.0 ``` On pass 2, the first `./gradlew` reads the new `distributionUrl`, downloads Gradle 9.0, and executes the `wrapper` task **under 9.0**. Now step 2 emits the scripts and jar that ship with 9.0. If anything in the launcher logic or jar changed between versions, you'll see those files update in git on this second pass. ## When it actually matters - **Minor/patch bumps**: scripts and jar are usually stable; a no-op diff is fine, and a single run is often enough in practice. - **Major upgrades**: the wrapper logic or jar can change; the second run ensures you ship the matching artifacts. - **Security/consistency**: regenerating the jar from the target version (rather than carrying an old one) keeps the bootstrap aligned with the distribution it launches. ## What to commit Whatever the two passes changed — `gradle-wrapper.properties` always, plus `gradlew`/`gradlew.bat`/`gradle-wrapper.jar` if they differ. Commit them together so the wrapper is internally consistent.
- Is a single run ever sufficient?Often yes for minor/patch bumps where the scripts and jar are unchanged between versions. The second pass is most important for major upgrades or when the wrapper's own logic changed.
- Why are the scripts/jar produced by the executing version rather than the requested one?The `wrapper` task code that emits them is part of the running Gradle build; on the first pass that's the old installed version, so it emits its own scripts/jar regardless of the requested `--gradle-version`.
saying these in an interview costs you the question
- Calling the unchanged jar/scripts a failure of the upgrade — it's expected on the first pass.
- Hand-replacing `gradle-wrapper.jar` from a download instead of letting the task regenerate it.
- Committing only the properties file for a major upgrade without ever doing the second pass.