10

I want to see a list of only non-common commits between two branches.

How can I get output like this?

Basically a git diff -y master new-feature summary between two branches:

              master                               new-feature
-------------------------------------|--------------------------------------
xxx - Jan 1st 2018 - initial commit  | xxx - Jan 1st 2018 - initial commit
xxx - Feb 1st 2018 - fix a bug       | xxx - Feb 1st 2018 - fix a bug
                                     > xxx - Mar 1st 2018 - WIP almost done
xxx - Apr 1st 2018 - fix another bug | xxx - Apr 1st 2018 - fix another bug
xxx - May 1st 2018 - fix more bugs   | xxx - May 1st 2018 - fix more bugs
                                     > xxx - Jun 1st 2018 - Ready to merge!
xxx - Jul 1st 2018 - latest patches  < 

Solution: I don't know how to make heads or tails of it, but I think git log --graph accomplishes this, just with a very confusing visual style:

git log --left-right --graph --cherry-pick --oneline master





Or this?

Better yet, git diff -y --suppress-common-lines master new-feature is what I really want:

              master                               new-feature
-------------------------------------|--------------------------------------
                                     > xxx - Mar 1st 2018 - WIP almost done
                                     > xxx - Jun 1st 2018 - Ready to merge!
xxx - Jul 1st 2018 - latest patches  <

Solution: You probably can't with git alone but, as per @torek's answer, you can get mostly there with git rev-list:

git rev-list --left-right master...new-feature

>eb57618eed654685a7999da847628dc5eb27313f
>0da0196ab24542a1a1697b1c0c5efeef6d09e027
>9452f57d97e5fc86e773e7a9fca488b7a0d44a0c
<4fc12fe25a127f8f0dfddf7625c22656c7b2c7c1
<9c0058dcabacfc6560f4fbaf73ea55dd70d27036
>5117fcd041793898683f9469aac00337e9fadd8b





Or even just this?

And more critical than that, a git diff --right-only master new-feature style view would get the job done:

     commits only in new-feature
-------------------------------------
xxx - Mar 1st 2018 - WIP almost done
xxx - Jun 1st 2018 - Ready to merge!

Which, of course, could be reversed to get the opposite view git diff --right-only new-feature master

       commits only in master               
-------------------------------------
xxx - Jul 1st 2018 - latest patches 

Solution: As @brentjanderson points out, git log main..new-feature and git cherry -v main both do this:

git cherry -v main

+ c00335cd93898683f9469aafad8a8476227b117f WIP do things
+ f5c86e777d97e5f3e7a9fca488b79a0d44ac9452 WIP do more
+ 0ef6ddda576180196ab7b1c0c57eefe009e027dc Finished!

as well as

git log master..new-feature --format="%h - %ad - %s" --date=format:'%b %d %Y'

c00335cd - Jan 01 2018 - WIP do things
f5c86e77 - Feb 01 2018 - WIP do more
0ef6ddda - Mar 01 2018 - Finished!


P.S. I have tried git checkout new-feature; git log --left-right --graph --cherry-pick --oneline master before, but I can't make heads or tales (or tails) of the output. Actually, on second thought, I bet taking the output, turning it sideways, and playing it as excitebike map would make a good tale of it. Hmm...

coolaj86
  • 74,004
  • 20
  • 105
  • 125

3 Answers3

18

Here is a basic variant without fancy formatting:

git log master..new-feature

You can get "left side" or "right side" data by swapping the order of the branches:

git log left-side-branch..right-side-branch

This works with other refs (commit hashes, remote branches, tags) too.

To get the full date formatting you want:

git log master..new-feature --format="%h - %ad - %s" --date=format:'%b %d %Y'

This doesn't do ordinal dates (Mar 1st 2018 is Mar 01 2018) because strftime does not support that. If that's a hard requirement, I suggest writing a batch script.

brentjanderson
  • 316
  • 2
  • 4
5

I want to see a list of only non-common commits between two branches.

This is, in set theory, the symmetric difference of the set of commits reachable from branches X and Y.

This particular set grouping is so useful that it is built into the Git revisions parser, using a syntax described in the gitrevisions documentation, using three dots: X...Y.

How can I get them [formatted in some particular way]

Start with git rev-list --left-right master...new-feature. When using the symmetric difference notation, and adding --left-right, Git will list the commits along with a marker: < if the commits are reachable from the name on the left but not from the name on the right, or > if the commits are reachable from the name on the right but not from the name on the left. Hence:

git rev-list --left-right master...new-feature

will give you:

<aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd
>eeeeeeeeeeffffffffff00000000001111111111

for instance, if commit aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd exists in master but not in new-feature while commit eeeeeeeeeeffffffffff00000000001111111111 exists in new-feature but not in master.

(Options like cherry-mark and --left-only and so on modify or replace the markers to indicate which commits are patch-equivalent, if any, or omit the left or right side, or both. For this case you do not want these.)

Having gotten the list from git rev-list, you can reformat it however you like. You can use these same options with git log but it's generally better to collect the hash IDs first, then deal with the formatting, unless git log's --pretty=format:... directives happen to match up with what you need (to find out, see the PRETTY FORMATS section of the git log documentation).

torek
  • 448,244
  • 59
  • 642
  • 775
  • 1
    Thank you so much. I wish I could mark multiple answers as correct because each answer answered a part of the question and I think that between the 3 I have all the knowledge that I need. – coolaj86 Nov 01 '18 at 23:26
2

I think running git cherry -v master on your new-feature branch should work for the right side. then do the reverse on master for the left side of your list

Tom Pridham
  • 114
  • 1
  • 4
  • OOoooOooh! I like that. Do you know of any way that I can get the dates output too? – coolaj86 Nov 01 '18 at 18:28
  • P.S. I'm didn't accept this (yet) because I want to see what other answers come up. – coolaj86 Nov 01 '18 at 18:29
  • I'm not sure how to get the dates. you might be able to combine `git log` and `git cherry` with a script or something, but i don't think `git cherry` has a built in option to output the dates – Tom Pridham Nov 01 '18 at 18:32
  • 1
    `git cherry` is specifically for finding commits that are reachable from your current branch that are or are not *patch-equivalent* to commits in some other range. It's essentially the same set as `git rev-list --right-only --cherry-mark A...B` or `git rev-list --left-only --cherry-mark A...B`, depending on which name you list for A and B, and defaulting to using `HEAD` for one of the two names. (Adding a `` parameter adds `^` to the `git rev-list`, but `git cherry` is generally more convenient as well.) – torek Nov 01 '18 at 21:01
  • The TL;DR summary of the above is: `git cherry` is very useful, but doesn't *quite* do what @CoolAJ86 was asking for. – torek Nov 01 '18 at 21:03