I have two branches devel
and next
. In devel I have a more or less huge amount of commits. Some of the commits are cherry picked in next
How about
git log next..devel
Result is similar to Byran's answer (different order of commits) but both of our answers will produce commits that are different between the branches, rather just showing what's in one branch and not in the other.
To get the list of commits that were not integrated into the release branch (next) you may use:
git rev-list --reverse --pretty="TO_TEST %h (<%ae>) %s" --cherry-pick --right-only origin/release_branch...origin/development_branch | grep "^TO_TEST " > NotIntegratedYet.txt
Check git-rev-list for more info.
@Mark Longair nailed it in his answer here, but I'd like to add some additional insight.
My situation:
I made a big feature_branch
with 30 commits and opened a Pull Request (PR) on GitHub to merge it into master
. Branch master
changed a ton underneath me, and received 200 commits my feature_branch
didn't have. To resolve conflicts I did git checkout feature_branch
and git merge master
to merge master
's changes into my feature_branch
. I chose to merge
rather than rebase
onto latest master so I would have to resolve conflicts only one single time instead of potentially 30 times (once for each of my commits). I didn't want to squash my 30 commits into 1 first and then rebase onto the latest master
because that might wipe away GitHub review comment history in the PR. So, I merged master into my feature branch and resolved conflicts 1 single time. All was well. My PR, however, was too big for my colleagues to review. I needed to split it up. I went to squash my 30 commits and OH NO! WHERE ARE THEY? THEY ARE ALL INTERMINGLED WITH master
's 200 recent commits now because I merged master
into my feature_branch
! WHAT DO I DO?
git cherry
usage in case you want to try to git cherry-pick
individual commits:git cherry
to the rescue (sort of)!
To see all the commits that are in feature_branch
but NOT in master
I can do:
git checkout feature_branch
git cherry master
OR, I can check commits from ANY branch withOUT ensuring I'm on feature_branch
first by doing git cherry [upstream_branch] [feature_branch]
, like this. Again, this checks to see which commits ARE in feature_branch
but are NOT in upstream_branch
(master
in this case):
git cherry master feature_branch
Adding -v
also shows the commit message subject lines:
git cherry -v master
Piping to "word count" "-lines" (wc -l
) counts how many commits there are:
git cherry master | wc -l
You can compare this count against the commit number shown in your GithHub PR to feel better about knowing git cherry
really is working. You can also compare the git hashes one by one and see they match between git cherry
and GitHub. Note that git cherry
will NOT count any merge commits where you merged master
into feature_branch
, but GitHub WILL. So if you see a small discrepancy in the count, search the GitHub PR commit page for the word "merge" and you'll probably see that's the culprit which is not showing up in git cherry
. Ex: a commit titled "Merge branch 'master' into feature_branch" will show up in the GitHub PR but not when you run git cherry master feature_branch
. This is fine and expected.
So, now I have a means of finding out which diffs I may want to cherry-pick onto a fresh feature branch to split up this diff: I can use git cherry master feature_branch
locally, or look at the commits in the GitHub PR.
An alternative, however, to split up my big diff is to squash all 30 of my commits into one, patch that onto a new feature branch, soft reset the patch commit, then use git gui
to add pieces file by file, chunk by chunk, or line by line. Once I get one sub-feature, I can commit what I've added then check out a new branch, add some more, commit, check out a new branch, etc, until I have my big feature broken out into several sub-features. The problem is that my 30 commits are intermingled with the other 200 commits from other people due to my git merge master
into my feature_branch
, so rebasing is therefore impractical, as I'd have to sift through 230 commits to re-order and squash my 30 commits.
A work-around is to simply obtain a patch file containing a "squash-equivalent" of all 30 of my commits, patch it onto a new fork of master
(a new sub-feature-branch), and work from there, as follows:
git checkout feature_branch
# ensure I have the latest changes from master merged into feature_branch
git merge master
# Obtain a patch file, which is the equivalent of a squash of my 30 commits into 1 commit:
git diff master..feature_branch > ~/mypatch.patch
git checkout master
# Create a new, sub-feature branch
git checkout -b feature_branch2
# Patch the 30 commit patch file onto it:
git apply ~/mypatch.patch
Now I have my 30-commit patch all applied locally, but unstaged and uncommitted.
git gui
to add files, chunks, and/or lines and break up your big PR or "diff":Note that if you don't have git gui
, you can easily install it in Ubuntu with sudo apt install git-gui
.
I can now run git gui
and start adding files, chunks, and/or lines (by right-clicking in the git GUI program), and break up the 30 commit feature branch into sub branches as described just above, repeatedly adding, committing, then forking a new feature branch and repeating this cycle until all changes have been added to a sub-feature-branch and my 30-commit feature is successfully broken up into 3 or 4 sub-features. I can open up a separate PR for each of these sub-features now, and they will be easier for my team to review.
Also, you can use
git log --left-right --graph --cherry-pick --oneline devel...next
to get a nice list of actual different commits not shared between the branches.
The operative word is --cherry-pick
--cherry-pick
Omit any commit that introduces the same change as another commit on the "other side" when the set of commits are limited with symmetric difference. For example, if you have two branches, A and B, a usual way to list all commits on only one side of them is with --left-right, like the example above in the description of that option. It however shows the commits that were cherry-picked from the other branch (for example, "3rd on b" may be cherry-picked from branch A). With this option, such pairs of commits are excluded from the output.
Update As mentioned in a comment, recent versions of git added --cherry-mark
:
--cherry-mark
Like --cherry-pick (see below) but mark equivalent commits with = rather than omitting them, and inequivalent ones with +.
The little-used command git cherry
shows you the commits which haven't yet been cherry-picked. The documentation for git cherry
is here, but, in short, you should just be able to do:
git checkout devel
git cherry next
... and see output a bit like this:
+ 492508acab7b454eee8b805f8ba906056eede0ff
- 5ceb5a9077ddb9e78b1e8f24bfc70e674c627949
+ b4459544c000f4d51d1ec23f279d9cdb19c1d32b
+ b6ce3b78e938644a293b2dd2a15b2fecb1b54cd9
The commits that begin with +
will be the ones that you haven't yet cherry-picked into next
. In this case, I'd only cherry-picked one commit so far. You might want to add the -v
parameter to the git cherry
command, so that it also outputs the subject line of each commit.
You might could try doing git log subsets:
git log --oneline devel ^next