Catching a credential before it reaches a commit is dramatically cheaper than dealing with one afterwards. Once a secret has been pushed it must be rotated, and rewriting history does not change that.
The values worth looking for fall into a few families. Provider API keys usually have recognisable prefixes — a short identifier followed by a long random string — which makes them the easiest category to catch reliably. Private key blocks announce themselves with a BEGIN header. Connection strings embed a password between the username and the host, and are easy to miss because they look like configuration rather than a credential. And then there are unstructured values: something assigned to a variable called token or secret that matches no known format.
The last category is where detection gets uncertain. A high-entropy string assigned to a secret-sounding name is often a credential and often a hash, an identifier or a test fixture. Any tool that flags these will produce false positives, and any tool that does not will miss real secrets. Seeing them separately from confident matches is more useful than having the tool guess.
Placeholders should not be flagged. A value written as ${API_KEY} is a reference, not a secret, and a scanner that reports it teaches you to ignore its output — which is the real failure mode, because a noisy tool gets switched off.
Run the check at the point where it is cheap: before staging, or in a pre-commit hook, or before pasting a configuration file into a chat window. The last of those is worth calling out, since pasting a config into an assistant to ask what is wrong with it is a routine way for credentials to escape.
Treat a clean result as one check rather than a clearance. Pattern matching finds what it recognises. A credential in an unusual format, encoded, or split across lines can pass unnoticed, and no scanner can promise otherwise.