I need to know in my script whether a given commit is a standard commit or a stash entry.
The method should work also for dropped stashes that are not garbage collected yet, so it cannot rely on checking sha of existing stash entries (like git rev-parse stash@{X}
).
A stash commit has 2 parents. Say parent1
and parent2
. parent1
is also the only parent of parent2
. The graph is like this,
* 9129d71 WIP on master: d2b25fd hello world
|\
| * f38c1f8 index on master: d2b25fd hello world
|/
* d2b25fd hello world
Update:
As @jthill points out, with git stash -u
which also stashes untracked files, the head has a 3rd parent, parent3
. parent3
is a root commit.
*-. 5ec4337 WIP on (no branch): d2b25fd hello world
|\ \
| | * b4b28c3 untracked files on (no branch): d2b25fd hello world
| * ca727e1 index on (no branch): d2b25fd hello world
|/
* d2b25fd hello world
The commit messages of them match certain patterns. The message of the stash entry starts with either WIP on $branch:
(by git stash
) or On $branch:
(by git stash push -m $msg
), followed by the short sha1sum and the subject of parent1
. The message of parent2
startswith index on $branch:
, followed by the short sha1sum and the subject of parent1
. The message of parent3
also matches a pattern untracked files on $branch
. On a detached HEAD, $branch
is literal (no branch)
.
We can forge 3 or 4 commits with the same graph and messages on a normal branch, and the head can also be consumed by git stash apply $commit
. But it's not common in real logs. So, if the 3 or 4 commits match the graph and their commit messages match these patterns, the head can be considered as a stash entry.