2

How can I get a list of absolutely everything that can be reached that is ordered by date? Normal commits, stashes, dropped stashes, commits from deleted branches - everything that hasn't been vacuumed yet.

I'm asking because I need to find a particular commit (or stash) and I don't remember much except the date when it must have been added. Since I never run git gc, I assume it should still be available somewhere.

I also need the to see the timestamp for each commit, because I will have to use that to narrow down the search to only commits/stashes that are around the date I have in mind.

Edit: In case it is not clear it is crucial that I search dangling commits and dropped stashes in addition to the normal ones. Questions like How can I make git log order based on author's timestamp? do not address that.

sashoalm
  • 75,001
  • 122
  • 434
  • 781
  • The real problem here is that `git-fsck` is what you'd use to find a dangling commit, but it doesn't order it by date. You'd only get a SHA (or several) of your dangling commits. – Makoto Mar 13 '15 at 15:54
  • @Makoto Hm, if I can get the date in the log, I could at least search for it using a regex. I could try looking around that month. I would prefer ordering by date, but even getting them unordered could help for a start. – sashoalm Mar 13 '15 at 15:58

2 Answers2

3

One thing to try is simply git reflog or git reflog HEAD (which are equivalent, the first is just a shorthand for the second).

The reflog tracks every commit that a particular ref points to; HEAD is the ref that points to what you have currently checked out, so if you ever had the commit in question checked out on this machine, and it hasn't yet been gc'd, it should show up in that list.

Brian Campbell
  • 322,767
  • 57
  • 360
  • 340
  • Thanks for the answer, but `git reflog` didn't show the timestamps, however, and I need those to find my commit. I'll be looking for commits around a particular date. – sashoalm Mar 13 '15 at 16:02
  • 2
    @sashoalm You can pass any of the `git log` pretty formats to `git reflog`, so you could do `git reflog --pretty=fuller` or some custom format that contains the information you want. After reading your clarification, one thing I realize that this won't cover is dropped stashes; stashes are things that have never been committed, so won't show up in a reflog for HEAD, and in fact are stored as just a special reflog, so when they are deleted, they are removed from that special reflog. – Brian Campbell Mar 13 '15 at 16:08
  • Are dropped stashes immediately vacuumed? I mean are they held somewhere at all or deleted for real from git when dropped? – sashoalm Mar 13 '15 at 16:09
  • 1
    I see that in https://stackoverflow.com/questions/89332/recover-dropped-stash-in-git they mention using `git fsck --no-reflog | awk '/dangling commit/ {print $3}'`, I might try doing that. – sashoalm Mar 13 '15 at 16:11
  • 2
    @sashoalm various commands run `git gc --auto`, which will automatically repack commits if there are too many loose objects or too many packfiles, and will automatically prune loose objects that are older than a given date (defaults to 2 weeks). So, if your commits are older than two weeks, and are not actually referenced from anywhere, they have likely been pruned. If they are still referenced from a reflog, or are younger than two weeks old, then you may be able to find them either by looking through the reflogs, or via the method you mention, using `git fsck` to find them. – Brian Campbell Mar 13 '15 at 16:15
  • OK, I'll accept your answer, though the most useful parts are in the comments right now :) – sashoalm Mar 13 '15 at 16:19
0

Dangling commits only:

% git fsck --lost-found | awk '/^dangling commit/ {print $3}' \
| xargs -l1 sh -c $'time=$(git cat-file -p "$1" | awk \'/^committer/ {printf "%s", $(NF-1); exit}\'); printf "%s %s\n" "$1" "$(date -d@"$time" -Is)" ' _ \
| sort -rk2

Output:

c3c00af52dd3efcaaa76ac8a84e008ac0bd5db9e 2023-08-15T22:39:17+07:00
e77099f9ad2c5b1ccd3eb910848b0f35d598d00a 2023-08-15T22:38:50+07:00
983a95b7a12d38bdc2246006bb1e0face1ab6441 2023-08-14T13:53:56+07:00

To get a superset of commits including those reachable via the reflog, replace the first line with:

git fsck --unreachable | awk '/commit/ {print $3}' \
Tom Hale
  • 40,825
  • 36
  • 187
  • 242