How to get a list of different commits between two git branches?
Asked Answered
D

3

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...

Diskson answered 1/11, 2018 at 18:13 Comment(0)
P
19

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.

Pawpaw answered 1/11, 2018 at 18:47 Comment(1)
And add some hard-core ANSI escaping and coloring https://mcmap.net/q/13969/-how-to-change-git-log-date-formatsDiskson
I
6

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).

Irradiance answered 1/11, 2018 at 20:56 Comment(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.Diskson
C
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

Cassiterite answered 1/11, 2018 at 18:25 Comment(5)
OOoooOooh! I like that. Do you know of any way that I can get the dates output too?Diskson
P.S. I'm didn't accept this (yet) because I want to see what other answers come up.Diskson
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 datesCassiterite
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 <limit> parameter adds ^<limit> to the git rev-list, but git cherry is generally more convenient as well.)Irradiance
The TL;DR summary of the above is: git cherry is very useful, but doesn't quite do what @CoolAJ86 was asking for.Irradiance

© 2022 - 2024 — McMap. All rights reserved.