If the same property is defined in the root gradle.properties, ~/.gradle/gradle.properties, and on the command line with -P, which value wins?
answer
- closest-to-invocation wins
- CLI -P > user home > project file
- ORG_GRADLE_PROJECT_x env injection
- user home overrides committed defaults
- system props are a separate chain
basics
~10 sCommand line wins. From highest to lowest precedence: -P (and -D for system props) on the CLI, then ~/.gradle/gradle.properties (Gradle user home), then the project root gradle.properties. The most specific/closest-to-invocation source overrides the rest.
solid answer
~40 sFor a project property, Gradle merges several sources and the **closest to the invocation wins**. Effective order, highest first: a value passed on the command line (`-Pkey=value`); then the **Gradle user home** file `~/.gradle/gradle.properties`; then the **project root** `gradle.properties`. (Environment variables of the form `ORG_GRADLE_PROJECT_key` and system properties `org.gradle.project.key` also feed in, ranking near the command line.) The intuition: the user-home file is more specific to *who/where* is running than the committed project file, and an explicit `-P` is more specific still. So you commit sane defaults in the root file, let a developer or CI machine override them in user home, and override per-run with `-P`. Note `-D` system properties are a separate namespace with their own resolution; the question above is specifically about project properties.
code
bash · 4 lines# root gradle.properties: appVersion=1.0.0
# ~/.gradle/gradle.properties: appVersion=1.0.0-dev
export ORG_GRADLE_PROJECT_appVersion=1.5.0 # CI injection
./gradlew printVersion -PappVersion=2.0.0 # -> prints 2.0.0 (CLI wins)go deeper
Remember the command line beats the files.
State the full chain CLI > user home > project file and why user-home overrides committed defaults.
Add the ORG_GRADLE_PROJECT_* env and org.gradle.project.* system-property injection paths used by CI.
Design org-wide conventions: committed defaults, machine overrides in user home, CI via env injection — documented so teams don't fight precedence.
## The merge model Gradle assembles the final set of project properties from multiple sources before your script runs. When the same key appears in more than one source, a fixed precedence decides the winner. **More specific / closer-to-invocation beats more general / committed.** ## Precedence for project properties (high → low) 1. **Command line `-Pkey=value`** — explicit, per-invocation; wins over everything. 2. **`ORG_GRADLE_PROJECT_key` environment variable** — CI systems use this to inject without touching files. 3. **`-Dorg.gradle.project.key=value` system property** — the system-property path to a project property. 4. **`~/.gradle/gradle.properties`** (Gradle user home) — per-machine / per-user. 5. **`<rootDir>/gradle.properties`** (committed) — shared default. (2)–(3) sit logically alongside the command line as invocation-time overrides; the key takeaway interviewers want is **CLI > user-home file > project file**. ## Why this ordering is useful ``` root gradle.properties -> appVersion=1.0.0 (committed default) ~/.gradle/gradle.properties -> appVersion=1.0.0-dev (a dev's local pref) ./gradlew build -PappVersion=2.0.0 (CI release run) ``` The CI run publishes `2.0.0`; an untouched dev box builds `1.0.0-dev`; a fresh checkout with a clean home builds `1.0.0`. Same script, three behaviors, no edits. ## Two namespaces, don't conflate them - **Project properties** — the chain above; read with `providers.gradleProperty`. - **System properties** (`-Dfoo=bar`, `systemProp.foo=bar` in gradle.properties) — read with `providers.systemProperty`. They have their own (parallel) resolution and do **not** override project properties. ## Practical caution Don't rely on subtle differences between (2) and (3) in an answer; rely on the robust top/bottom: explicit CLI override on top, committed project file at the bottom, user-home in between. That ordering is what makes secrets-in-user-home and CI-injected overrides work.
- How can a CI system override a project property without editing any file or passing -P?By exporting an environment variable named ORG_GRADLE_PROJECT_<key>, e.g. ORG_GRADLE_PROJECT_appVersion=1.5.0. Gradle maps it to the project property appVersion at near-CLI precedence.
- Does ~/.gradle/gradle.properties override the project's root gradle.properties?Yes for the same key — the Gradle user home file is more specific to the machine/user than the committed project file, so it wins between the two (but -P still beats both).
saying these in an interview costs you the question
- Saying the project root file wins over -P (it's the opposite).
- Claiming system properties (-D) override project properties — they are a separate namespace.
- Forgetting that ~/.gradle overrides the committed root file.