If the same property is defined in the project-root gradle.properties, in GRADLE_USER_HOME, and on the command line, which value wins?
answer
- command line > user-home > project root > defaults
- user-home overrides committed project file
- more local/explicit = higher priority
- per-run flag beats everything
- fallback chain when key absent
basics
~10 sHighest to lowest: command line / system-property / env-var overrides beat GRADLE_USER_HOME/gradle.properties, which beats the project-root gradle.properties. So the command line wins, and user-home beats the committed project file.
solid answer
~40 sWhen the same property key appears in multiple sources, Gradle resolves it by a fixed precedence, from **highest to lowest**: 1. Command-line and environment overrides (`-P`, `-D`, `ORG_GRADLE_PROJECT_*`, `systemProp.*`) — these are sibling mechanics, but they sit at the top. 2. **`GRADLE_USER_HOME/gradle.properties`** (`~/.gradle`). 3. **Project-root `gradle.properties`**. 4. Built-in defaults. The practical takeaway is that **the per-developer user-home file overrides the committed project file**. That's exactly why a developer can drop a value into `~/.gradle/gradle.properties` to locally override a team default without editing the repo. And anything passed at invocation time beats both files, so CI or an ad-hoc command can override everything for a single run. The mental model: the more *local and explicit* the source, the higher it ranks.
code
bash · 5 lines# project root gradle.properties: buildEnv=staging
# ~/.gradle/gradle.properties: buildEnv=local
./gradlew printEnv # -> local (user-home beats project file)
./gradlew printEnv -PbuildEnv=prod # -> prod (command line beats both files)go deeper
Recall the headline: command line beats user-home beats project file.
State the full ladder and explain why user-home outranks the committed project file (personal override of team default).
Connect precedence to operational patterns: CI overriding via invocation flags, developers overriding via user-home, repo file as the shared baseline.
Discuss governance: how to keep team defaults authoritative despite per-user overrides (build-time validation, CI-enforced flags) without fighting Gradle's precedence.
## The precedence ladder When a property key is defined in more than one place, Gradle picks a single winner using a deterministic order. From **highest priority (wins) to lowest**: 1. **Invocation-time overrides** — properties supplied per-run, e.g. `-PmyProp=x` (project property), `ORG_GRADLE_PROJECT_myProp=x` (env var form), and for *system* properties `-DsystemProp` / `systemProp.*`. (The exact `-P` vs `-D` vs `ORG_GRADLE_PROJECT_` mechanics are a sibling topic; here they matter only as the top rung.) 2. **`GRADLE_USER_HOME/gradle.properties`** — the per-machine file (`~/.gradle/gradle.properties`). 3. **Project-root `gradle.properties`** — the committed file at the top of the build. 4. **Gradle built-in defaults** (e.g. defaults for `org.gradle.*` flags). ## Why user-home beats the project file This ordering is deliberate. The committed project file expresses the **team default**; the user-home file expresses a **personal override**. Because user-home sits *above* the project file, a developer can bump, say, `org.gradle.jvmargs` for their beefy laptop without touching shared config. And because invocation-time flags sit above *both*, CI or a one-off command can override everything for a single build without persisting anything. ## A worked example ```properties # <project>/gradle.properties (committed) buildEnv=staging ``` ```properties # ~/.gradle/gradle.properties (this developer only) buildEnv=local ``` ```bash # one-off invocation ./gradlew build -PbuildEnv=prod ``` Resolved value of `buildEnv`: - normal `./gradlew build` → `local` (user-home beats project file) - `./gradlew build -PbuildEnv=prod` → `prod` (command line beats both files) - if the user-home file did *not* define `buildEnv` → `staging` (falls back to project file) ## Mental model *More local and more explicit ⇒ higher priority.* Per-run flag > per-machine file > per-repo file > Gradle default. Knowing this lets you predict exactly which value a build will see and where to put a setting so it sticks (or doesn't).
- A teammate says the committed root file should always win so the team default is enforced. What's wrong with that?It would defeat per-developer overrides. The design intentionally puts user-home above the project file; if you need a hard enforcement, set it at invocation time in CI or validate it in the build, not by inverting precedence.
- If a key is only in the project-root file, what value does the build see?The project-root value — resolution falls down the ladder until it finds the key, then the Gradle default if it's nowhere.
- Does the user-home file override per project, or globally for that machine?Globally for that machine/user — it applies to every build run under that GRADLE_USER_HOME, which is why it's used for personal, cross-project overrides.
Like CSS specificity: an inline style (command line) beats a stylesheet you keep locally (user-home), which beats the shared site-wide stylesheet (project file).
saying these in an interview costs you the question
- Saying the committed project-root file overrides the user-home file (the order is reversed).
- Claiming command-line values are persisted — they apply only to that single invocation.
- Mixing up which is 'higher' by reciting the order backwards.