But I didn't define it on a.c or a.h, Only on b.h
That's not how it works. All code from all included headers is put together by the preprocessor and passed to the compiler, which then compiles it into an object file. This code is called a "translation unit." If the same variable is defined in another translation unit, it will also be present in the generated object file. When you then link these object files together, both will have the same variable defined, and thus the linker will complain about the duplicate symbol.
What you should do instead is define the variable in one *.c file, and only declare it extern
in the *.h file. That way, the other translation units will know about the variable but will not try to define it themselves. It will only be defined in the translation unit that includes the *.c file where it's actually defined.