2.1.6 Reverse Dependencies & Change Impact
recommended2.1.5 Inspecting the Graph — Query Preview mapped query, cquery, and aquery to three graph layers. The missing DAG question at this point is the reverse one: after 1.1.8 Basic Query taught forward deps() walks, how do you ask "who depends on this target?" Plain bazel query answers that with rdeps(), which walks backward through the declared target graph inside a universe you choose.1,2,3
deps() walks from a requested target to its prerequisites. rdeps() starts from a shared target and asks which dependents or consumers use it.
rdeps() searches only within the supplied universe. //... makes that universe the whole workspace.
rdeps() flips the question
deps(x) asks what target x needs. rdeps(u, x) asks which nodes in universe u depend on x. The first argument is the part beginners usually miss: reverse dependencies are always computed inside a chosen universe, not across some implicit "whole Bazel world". Using //... makes the universe the whole workspace. A narrower scope keeps the answer closer to the change you are about to make.1,2,4
bazel query "rdeps(//..., //lib/logging:logging)"
bazel query "rdeps(//foo, //common, 1)"
The optional third argument is a depth bound. rdeps(//foo, //common, 1) asks for direct reverse dependents only. Omitting the depth asks for the full reverse closure inside the chosen universe.2
Use it before you refactor or delete
This makes rdeps() a change-impact query, not just a graph curiosity: the practical question it answers is what other code you are about to break. A shared logging library is the classic example — before changing it, ask which libraries and binaries depend on it.1,3
bazel query "kind('go_binary', rdeps(//..., //lib/logging:logging))"
Filtering the reverse closure by kind is often enough to turn a noisy answer into an actionable one. If you are touching a shared library, maybe you care about binaries. If you are changing test support code, maybe you care about test targets. The DAG question stays the same: which targets use or transitively depend on this one?1,3
Use the right graph question
rdeps() is about impact radius, not explanation. If the question is "why does A depend on B?", use somepath() or allpaths() from 2.1.4 Common Dependency Issues. If the question is "what does this configured build really choose?", the deeper handoff is 5.2 Query: plain query stays on the declared target graph, while later tools handle configuration-aware and action-level questions.1,2,3
Later, 6.5.1 Affected-Target Service Contract turns the same reverse-dependency idea into affected-target workflows for CI. At Level 2, the mechanic is simpler: pick a universe, walk the graph backward, and narrow the result until it matches the kind of change you are making.3
Check your understanding · 3 questions
1.What does the universe argument in rdeps(universe, target) control?
Select one answer
2.True or false: using rdeps() in practice.
Choose True or False for each sentence
rdeps(//..., //lib:core) answers 'who depends on //lib:core in the entire workspace?'rdeps(//..., //lib:core, 1) returns the full reverse transitive closure limited to one package.3.You are about to refactor //lib/logging:logging. Which query expression best identifies which binaries might break?
Select one answer
Footnotes
-
Query guide —
rdeps()as the answer to "what other code are you about to break?", plus practical reverse-dependency filtering ↩1 ↩2 ↩3 ↩4 ↩5 ↩6 -
The Bazel Query Reference — exact
rdeps(universe, target[, depth])semantics, universe scoping, and optional depth bound ↩1 ↩2 ↩3 ↩4 ↩5 -
A guide to Bazel query — concrete
rdeps()examples for refactors, binaries, and change-impact questions in a monorepo ↩1 ↩2 ↩3 ↩4 ↩5 -
Query quickstart — beginner explanation of reverse dependencies, whole-workspace
//...scope, and whyrdeps()matters before edits ↩