When you write uses: actions/checkout@v4 in a GitHub Actions workflow, you are not pinning anything. You are trusting a promise.

A tag is a movable pointer. Whoever owns that repository can repoint v4 at a different commit tomorrow, after you reviewed it, and every run of your pipeline will silently pull the new code. In a job that holds a registry login, a PyPI token, or a signing key, that is exactly the place you do not want a mutable reference.

I recently went through a project's workflows and pinned the remaining actions to commit SHAs. Here is what I actually learned doing it — beyond "just use the SHA".

A tag is a promise; a SHA is a fact

Compare these two lines: