Here is what to know:
A commit is a numbered entity consisting of data (a source snapshot) and metadata (author name and email and date-stamp, committer triple, parent hash IDs, any other internal headers, parent lines, and so on, then a blank line and the commit message subject-and-body).
The data—the source snapshot—is actually stored as a single metadata line, tree hash-id. The source snapshot is therefore indirect, which is how two commits that store the same source snapshot don't actually store the source snapshot twice. For instance, if you make commit C1 with tree T1, then make new commit C2 that has a new tree, then revert commit C2 to make commit C3, the tree in commit C3 is the same tree as in C1.
The hash ID of a commit is a cryptographic checksum of the (entire) metadata, including any commit signature appended to the message body. See How does commit signing work? for some additional details.
Currently, this cryptographic checksum uses SHA-1, which has been broken. However, the existing techniques for breaking SHA-1 are expensive (in both dollars, or whatever your local currency may be, and compute time) and leave obvious traces.
Whenever someone makes a new commit, they control all of the metadata, so there is no way to tell whether that new commit contains accurate metadata ("yes, my name really is Zaphod Beeblebrox, I had it legally changed this morning") or not ("I lied, my legal name is actually Jean Baptiste Emmanuel Zorg"). But if someone were to take an existing commit and try to modify it, what they will get is not a modified commit, but rather another new commit, with a new and different SHA-1 hash ID. The only way to get a new commit that re-uses the old hash ID is to use the SHA-1-breaking technique, which will leave obvious traces.
Commits themselves are the history, and form a kind of Merkle Tree, due to each commit holding the hash ID(s) of its parent commit(s). It's just that we (humans), and Git itself, usually find commits by using a branch name, which is defined as a name1 holding a changeable hash ID. As long as someone has permission to store a new and different hash ID in that name, if we trust the name, we'll see the latest hash ID.
What this in turn means is that if you actually pay attention to / use the hash IDs, rather than simply depending on some changeable branch name, you will notice anyone "fiddling with history", to whatever extent it is physically noticeable (i.e., you have to have had some commit X to see that someone else has come up with some different hash ID Y to use in place of X, and then also changed every subsequent commit due to the Merkle-tree issue).
Git tags can also be signed (using GPG signatures or equivalent). These digital signature methods—whether used on individual commits, or simply on a tag at the end of a series of commits—can use more-secure cryptography than SHA-1. Git itself is also being modified to use SHA-256, which if nothing else at least has more bits in it, making the techniques used in breaking SHA-1 less effective.
1Specifically, a branch name is a name of the form refs/heads/branch. The leading refs/heads/ part makes it a branch name. If the leading part is refs/tags/, the name is a tag name. Other names live in different parts of the refs/ name-space. The special names—HEAD, ORIG_HEAD, MERGE_HEAD, and so on—live outside the otherwise-required top level refs/ qualifier.