git reset Command: Move HEAD in CI
git reset repositions the current branch and, depending on the mode, the index and working tree.
reset is how scripts undo commits or discard changes to reach a known-clean state. The mode flag decides how much it touches, so picking the right one is critical in CI.
Common flags
--soft <ref>- move HEAD only, keeping changes staged--mixed <ref>- move HEAD and reset the index, keeping the working tree (the default)--hard <ref>- move HEAD and discard all index and working-tree changes--keep <ref>- reset but keep local changes that do not conflict-- <path>- unstage a specific path (reset that path in the index)
Example
# Force the working tree to match a known commit
git reset --hard origin/main
# Squash the last 3 commits into staged changes for a re-commit
git reset --soft HEAD~3In CI
git reset --hard origin/main is a blunt, reliable way to discard everything and match a remote ref before a deterministic build. Reserve --hard for ephemeral runners; it permanently drops uncommitted work. Use --soft when rewriting commits into a single re-commit.
Using this in CI
CI checkouts are shallow and detached by default, which changes the answer this command gives you. Commands that read history, branch names, or tags need the checkout configured for it.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # history, tags, and git describe all need this
- run: |
git rev-parse --is-shallow-repository # expect false
git rev-parse --abbrev-ref HEAD # prints HEAD when detachedKey takeaways
- git reset --hard discards all local changes to reach a known state, ideal on throwaway runners.
- --soft keeps changes staged, useful for squashing before a re-commit.
- The default --mixed unstages changes but leaves the working tree intact.