HEAD~1 means the first parent of the commit currently named by HEAD; it does not mean “the previous commit on the feature branch.” A squash merge changes how a pull request’s commits appear on the base branch, so a later command or comparison can refer to a commit different from the one you expected. To identify the cause, inspect the commit graph and the exact diff before blaming a particular Git command or repository state.
What does HEAD~1 mean?
Git defines ~ as first-parent traversal: HEAD~1 is the first parent of HEAD, and HEAD~2 follows that first-parent link twice. It is not a synonym for “the last commit I made” or “the last commit on the branch I merged.” See Git’s revision syntax documentation.
As an Amazon Associate I earn from qualifying purchases.
For an ordinary, non-merge commit, there is only one parent, so HEAD~1 is that parent. A merge commit has multiple parents. Its first parent is typically the commit that was checked out when the merge was created; the merged branch is typically the second parent. Thus, on a merge commit, HEAD~1 follows the base-side history rather than selecting the merged branch’s tip. The exact parent order depends on the commit being examined.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Why can a squash merge change what you expect to see?
With GitHub’s squash-and-merge method, the pull request’s commits are combined into one commit on the base branch. The original feature-branch commits are not added to the base branch as that same sequence of individual commits. The resulting base-branch history therefore has a different shape from the feature branch’s history.
#1 Best Overall
This matters especially if work continues on the original head branch. GitHub warns that a later pull request from that reused branch can include commits already represented by the earlier squash commit. That is a branch-history and comparison problem; it does not, by itself, prove that HEAD~1 selected unrelated code. GitHub documents this caveat in its overview of merge methods.
How to find what actually happened
- Record the current commit and its parents. Run
git show --no-patch --pretty=raw HEAD. Check the commit ID and every listedparentline. This establishes whatHEADnames and the parent order Git will follow. - Resolve the two refs in the comparison. Inspect the actual command, script, or CI configuration that used
HEAD~1. Identify the other ref it compared against, then resolve both refs rather than assuming one is the intended base or feature tip. - Review the resulting diff. For example,
git diff HEAD~1...HEADuses a three-dot comparison whose meaning differs from a direct two-commit comparison. Confirm what each endpoint resolves to and review the file changes. The command that produced the unexpected result matters: the title alone does not establish whetherHEAD~1was used as a commit, a range endpoint, a checkout target, or something else. - If CI is involved, inspect its checkout target. In GitHub Actions, the default
pull_requestevent workflow checks out a generated merge ref and tests the merged result. Checking outgithub.event.pull_request.head.shainstead tests the pull request’s head commit. Verify which target the workflow actually used in the GitHub Actions event documentation and in the workflow configuration. - Check whether a post-squash pull request reused the old branch. Compare the later pull request’s commits and diff with the squash commit on the base branch. A reused head branch can make already-squashed work appear again, as GitHub notes in its merge-method guidance.
For a postmortem, preserve the exact command, the value of HEAD, its parent list, the intended base and head refs, and the diff that exposed the problem. Without those details, it is not possible to attribute a specific incident to a particular Git behavior.
Rank #2
How should you fix a follow-up branch?
Choose a repair based on the graph and the intended comparison, not on the phrase “unrelated code.” If the follow-up work should start cleanly from the current base, create a fresh branch from that base and bring over only the intended changes. If the existing branch should continue, rebase it onto the current base when that fits your team’s workflow. Either way, inspect the resulting diff before opening or merging the pull request. These are options, not mandatory repairs for every squash merge.
Recommended Free Tools
When should a team choose squash, merge, or rebase?
GitHub offers three merge methods with different history results. Choose based on how your team wants history represented and whether branches will continue after a pull request is merged.
| Method | History on the base branch | Practical consideration |
|---|---|---|
| Merge commit | Preserves the pull request’s individual commits and adds an explicit merge point. | Keeps the branch relationship visible; the base history is not linear. |
| Squash and merge | Combines the pull request’s commits into one commit. | Can make a pull request’s history more compact, but reusing its head branch can complicate a later pull request. |
| Rebase and merge | Replays the individual commits onto the base without a merge commit. | Preserves individual commits while producing a linear history. |
These descriptions reflect GitHub’s pull-request merge documentation and its merge-method documentation. A compact history is not automatically a simpler workflow if a team relies on long-lived head branches; branch reuse and later comparisons should be part of the decision.
Quick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




