0

Using git only, how do I list commits that were on a branch that are no longer on that branch?

Here I have to use comm/diff

comm -23 <(git reflog @{0} --pretty='%h' | sort -u) <(git log @{0} --pretty='%h' | sort -u)

To test, you can create a couple of commits and hard reset the branch back to its original state. Now the reflog will have commits that were on the branch that are no longer on the branch.

caduceus
  • 1,542
  • 2
  • 16
  • 21
  • 5
    What is your use case? What do you need that information for? – knittl Feb 19 '22 at 11:58
  • Can you use `git reflog show branch-name` to get all commits that have been on the branch, and then filter those further to discard those still on the branch? – TTT Feb 19 '22 at 16:02
  • `git show-branch` could also be useful (but still needs applying some custom filter) – knittl Feb 19 '22 at 20:17
  • @knittl the use case of the reflog is to recover from messing up a branch. I can answer the question what commits have been on the branch with git log --reflog – caduceus Feb 20 '22 at 07:58

2 Answers2

1
git reflog --pretty=%H $thatbranch | git rev-list --stdin --not $thatbranch

and you can sub in git log for git rev-list to get more than just a list.

jthill
  • 55,082
  • 5
  • 77
  • 137
  • This works. But can you say why this doesn't `git reflog --pretty=%h master --not --branches=master` – caduceus Feb 20 '22 at 06:17
  • Reflog's job is to list reflog entries, I'd guess git log's additional commit-selection options get ignored or stripped depending on how it operates internally. – jthill Feb 20 '22 at 08:05
  • yeah it seems when --walk-reflogs is in effect git log will not walk the commit graph. Thanks https://stackoverflow.com/a/61558962/2746335 – caduceus Feb 21 '22 at 09:25
0

You can use a symmetric difference between two references (... operator):

git log --pretty='%h' HEAD@{1}...HEAD

which is an equivalent of:

git log --pretty='%h' HEAD@{1}...<reset_branch>

both will show the commits no longer reachable from your branch but reachable from HEAD@{1}.

bloody
  • 1,131
  • 11
  • 17
  • Firstly the reflog of HEAD is very different to the reflog of a branch. And then master@{1} is not a range of commits reaching back to beginning of the master reflog – caduceus Feb 21 '22 at 09:29
  • @caduceus Sorry, I don't know what you're saying. I didn't use any branch reflog nor *master@{1}*, just a branch name. What I know is my solution passes your test *"you can create a couple of commits and hard reset the branch back to its original state. Now the reflog will have commits that were on the branch that are no longer on the branch"* So either you misused my example (`` is just a branch name after the `reset` operation) or your question is confusing. – bloody Feb 21 '22 at 15:13
  • HEAD is a pointer to the current branch. It has its own reflog, and you're using it when you say HEAD@{1}. So it contains commits from potentially every branch you've worked on in the last 90 days or whatever the reflog expiration time is set to. You've picked HEAD@{1} but what about commits that were on the branch before then? Create more commits, reset them, and you'll see the command has forgotten about those older lost commits – caduceus Feb 22 '22 at 09:13
  • @caduceus Yes, I have figured out what you meant in the meantime. This is just your question wasn't comprehensive enough (no mention on possible intermediate HEAD jumps in the use case / ancestry-oriented reflog). Anyway, I already get it, thanks for rephrasing. Btw. in a spare time I'll think about joining that use case with `...` operator. – bloody Feb 22 '22 at 10:30