For historical reasons, the rules for determination of linkage and when a declaration provides a definition are a bit of a mess.
For your particular example, at file scope
extern int i = 2;
and
int i = 2;
are equivalent external definitions, ie extern is optional if you provide an initializer.
However, if you do not provide an initializer, extern is not optional:
int i;
is a tentative definition with external linkage, which becomes an external definition equivalent to
int i = 0;
if the translation unit doesn't contain another definition with explicit initializer.
This is different from
extern int i;
which is never a definition. If there already is another declaration of the same identifier visible, then the variable will get its linkage from that; if this is the first declaration, the variable will have external linkage.
This means that in your second example, both file1 and file2 provide an external definition of i, which is undefined behaviour, and the linker is free to choose the definition it likes best (it may also try to make demons fly out of your nose). There's a common extension to C (see C99 Annex J.5.11 and this question) which makes this particular case well-defined.