Reputation: 3155
Using git stash list
shows me the list of stashes with their IDs. Using git stash list --date=local
or git stash list --date=relative
gives me their times, but I have no idea what their corresponding ID is.
I want to acquire a stash at a certain time.
Upvotes: 49
Views: 14178
Reputation: 489678
git stash list
simply runs git log
with a particular set of options:
list_stash () {
have_stash || return 0
git log --format="%gd: %gs" -g --first-parent -m "$@" $ref_stash --
}
The $@
part inserts whatever additional options you've specified (none by default, but --date=relative
in this case).1
When you use --date=relative
this modifies the output from %gd
: instead of a short reflog with an index, you get a short reflog with a relative time stamp:
$ git stash list
stash@{0}: ...
$ git stash list --date=relative
stash@{4 minutes ago}: ...
The solution in this case is to use your own explicit format, rather than just letting --date=relative
modify how %gd
gets displayed. For instance:
$ git stash list --format='%gd (%cr): %gs'
stash@{0} (4 minutes ago): ...
(%cr
inserts the commit's committer time stamp, in relative format—this makes sense once you know that all git stash
does is make a couple of commits for you, with the commits being stored on the special stash
ref instead of on a branch).
1On reviewing this answer, I note that the --first-parent
and -m
arguments (literally present in the git stash
code) seem redundant at first, because of the -g
argument. The -g
argument to git log
tells it to look only at the reflog, rather than the commit history, in which case, --first-parent
means nothing. Meanwhile -m
tells git diff
to split a merge commit, but we're looking at commit logs, not diffs, so what is this doing here?
The answer is that git log
can show a patch, for which it runs git diff
, so if you give -p
as an argument, the --first-parent -m
limits this diff to comparing the commit to which the stash reflog points against its first parent. The stash bag commit to which the reflog entry points is the work-tree commit, whose first parent is the original commit on which the stash-bag hangs. (Its second parent is the index commit and its third parent, if present, is the all or untracked files commit.) So these options are there to make git stash list -p
diff the stash's work-tree commit against the commit that was current when the stash itself was made.
This is clever, but quite obscure! :-)
Upvotes: 61
Reputation: 179687
You can actually use the stash@<date>
syntax directly when referring to a stash:
$ git stash list --date=local
stash@{Sun Dec 21 22:32:14 2014}: WIP on develop: 7142a6e Update data files
stash@{Fri Dec 12 10:02:20 2014}: WIP on develop: c72abda Add initial calibration data
stash@{Wed Dec 10 10:02:05 2014}: WIP on master: 1d27422 Bug fix for gadgeteer
$ git show 'stash@{Fri Dec 12 10:02:20 2014}'
commit a096484501caf14942f01a6500a5d0c3476d3145
Merge: c72abda 861fff6
Author: Robert Xiao <[email protected]>
Date: Fri Dec 12 13:02:20 2014 -0500
WIP on develop: c72abda Add initial calibration data
...
$ git stash pop 'stash@{Fri Dec 12 10:02:20 2014}'
No need to get the ID of the stash at all! This even works with date=relative
as long as the relative dates are unique.
Upvotes: 33