Mini-git class performance issue
Hash code collisions

There's a problem with Commit: matching hash codes do not mean that two objects are equal ('pigeonhole principle'). For example, both [1, 0] and [0, 31] have hash code 31. You can only be sure that objects are not equal when their hash codes don't match - the inverse is not true.

Also, are you sure that reusing arrays is worth the effort? If filesCount is small, then the savings are small as well, and if filesCount is large, then the likelyhood that a specific state has occurred before is probably very small.

Multiple smaller arrays

One alternative is to divide the state into multiple smaller arrays. This limits the impact of individual changes: you only need to copy a 'sub-array' (and create a new 'array-of-arrays'), instead of copying the full state. This also increases the likelyhood that a particular sub-array has occurred before, although I do not think that is something you need to be concerned about.

In Git terms, this is similar to using multiple files instead of a single large file. Committing changes to a single file only creates a new blob for the modified file and a new tree object that references the new blob (and older blobs for unmodified files).

Change-sets

Another alternative is to store a change-set for each value, using a binary search to find the value for a particular commit number. This can save a lot of space, but it'll make checkouts slower. Whether that trade-off is worth it depends on the intended use of this class.

Other notes


Instead of Clone() as int[], you can use Linq's ToArray() method.
I'd put the last 4 lines of Commit inside an else statement, to make it clearer that these are two mutually exclusive paths.
On the other hand, I would not use an else statement in Checkout - the if check is an 'early-out' guard clause, not a full-blown separate path.
In Checkout, an ArgumentOutOfRangeException might be better suited. You may also want to guard against negative values. And why not check for invalid file numbers as well?