I’ll try to answer
BTW. Did you read the user guide section on the incremental compilation?
Do as little compilation as possible (i.e. don’t compile what is not affected by the code change). Is this a good explanation?
Yes. The high level goal is to make the dev experience better by offering faster and smarter builds. We want to compile as little classes as possible and ensure as little output class files are ‘changed’ after the compilation.
Does incremental compilation depend on the compiler or the mechanism (e.g. Gradle) calling the compiler and telling it what to do? So basically Gradle could do incremental compilation with every compiler, even javac? Or does Gradle need a special compiler and why?
Gradle uses standard java API for compilation (it’s what javac uses behind the hood). We perform bytecode analysis and select only specific classes for compilation.
Then there are build tools like ANT and Gradle. I always thought Gradle was doing incremental compilation even before 2.1? Is this incorrect?
Gradle’s compilation task was incremental ‘at the level of task’ since always. If you haven’t change any compilation inputs (source code, classpath, etc) and outputs are present/untampered, then the entire compilation task is considered UP-TO-DATE and compilation is skipped. The new 2.1 feature operates on the source class level. If only one class was changed, in theory it might be that only this single class needs to recompiled. This should save time and ensure that little outputs are changed (useful for use cases like jrebel).
Was Gradle always compiling the entire project even if just a single local variable in a private class was modified?
Yes 
Can you give a few major examples where a small change in a single class potentially affects the entire project and therefore demands compiling everything. I already mentioned global variables. What other examples are there?
For example, a class a non-private static constant. Due to compiler optimization we cannot detect all references to this constant from other classes via byte code analysis. So we recompile everything. Don’t do non-private constants 
Finally there is IDEA which seems to be married to Gradle eventually.
At some point yes but it’s not going to change soon (it needs a lot of effort). Currently compilation is separate in both tools and we strongly encourage that the IDE output dirs are kept separate from Gradle’s output dirs (that’s the default).
Hope that helps!