Search code examples
gitintellij-ideagit-cherry-pick

How to Handle Cherry-Picked Commits When Comparing Branches in IntelliJ?


I'm using IntelliJ's "Compare Branches" feature to compare branch_A with branch_B. Some commits from branch_A were cherry-picked into branch_B, but when I compare the branches, these cherry-picked commits show up as differences. IntelliJ lists them as "commit X doesn't exist in branch B," even though the changes are actually present in branch_B. The issue seems to arise because cherry-picking creates a new commit with a different hash.

This is making it difficult to get an accurate comparison of what has or hasn't been merged between the branches.

How can I compare branches in IntelliJ while accounting for cherry-picked commits? Are there any IntelliJ settings, plugins, or workflows that can handle this scenario better? Alternatively, are there Git-based command-line solutions that could help? I’m open to suggestions on improving my workflow or using external tools to address this issue.

Thanks in advance for your help!


Solution

  • Note: The answer to your question requires 2 parts. Part 1 is the Git portion of the answer, and part 2 is the IntelliJ portion of the answer. If you only care about part 2, skip to the bottom.

    From Git's point of view, it matters what "compare" means. If you are comparing the "commits", then the list of commits you'll see is going to be either:

    git log A..B # list all commits only reachable by B
    

    or

    git log A...B # list all commits only reachable by A or B
    

    When you cherry-pick between branches, then you are creating new commit IDs, and so they will always show up as differences when comparing "commits", but most of the time they will not show as differences when using a specific type of comparing "state".

    To compare "state" you can use either:

    git diff A...B # show me changes only on B (includes cherry-picked changes)
    

    or

    git diff A..B # show me changes only on A or B (excludes cherry-picked changes)
    

    Note the subtle difference between 2 and 3 dots in each of the above commands. As an example of how they are used in the context of most Pull/Merge Request tools, the view you see when merging source into target is typically defined by:

    • List of commits to be merged in: git log target..source
    • Changes to merged in: git diff target...source

    In the case where some commits were cherry-picked between source and target those changes will show up in most PR views even though the merge won't actually make those changes.1

    How to accomplish the git diff in IntelliJ

    To exclude changes that are cherry-picked, you need to use the 2 dot diff instead of the log. Note that the 2 dot diff between two branches is syntactically the same as no dots, e.g. git diff A B. Here's how to "compare" using the 2 dot diff in IntelliJ.


    1 The fact that cherry-picked changes show up in most PR/MR tools often annoys (or even enrages) people who see changes that they know will not actually happen. For this reason some tools offer an option in the UI to view the temporary merge commit that it used to determine whether there are conflicts or not. At the moment that temporary merge commit (TMC) was created behind the scenes, diffing it with it's first parent will show the exact changes that would occur if the PR is completed. For example: git diff TMC~1 TMC