In order to understand what a HMAC does for you, you need to know what a HMAC is. A HMAC is basically a hash function, that works a secret key "into" the hash. So instead of
Digest = Hash(Data)
Digest = HMAC(Data, SecretKey)
So how does this guarantee integrity? Similarly to a "regular" hash, data and the HMAC are transmitted together. The recipient, who also knows the secret key, can then calculate the HMAC again, and if the result is identical, it is guaranteed that the file has not been tampered with.
How is this any different from a regular hash?
The difference is that an attacker can't modify the data and simply calculate a new hash. For example, imagine you transmit the message
Security.SE is the best Stack Exchange site, with the SHA-256 hash
71d90574502edd87ea8ef969dc5a28dc13a0c4ce1e9e9664600ea275f1b364e4. Now an evil hacker from Crypto.SE intercepted that message, changed it to
Crypto.SE is the best Stack Exchange site and changes the hash to
The recipient wouldn't know that the data has been modified. If I were to use a HMAC, however, the attacker would not have access to the secret key, and thus is not able to generate their own HMAC.
But isn't a hash enough to guarantee integrity?
Yes, because a HMAC can do everything a regular hash function can do. However, a HMAC can, aside from integrity, also guarantee authenticity, assuming that the key has not been compromised.