Given a branch, I\'d like to see a list of commits that exist only on that branch. In this question we discuss ways to see which commits are on one branch
Try this:
git rev-list --all --not $(git rev-list --all ^branch)
Basically git rev-list --all ^branch
gets all revisions not in branch and then you all the revisions in the repo and subtract the previous list which is the revisions only in the branch.
After @Brian's comments:
From git rev-list's documentation:
List commits that are reachable by following the parent links from the given commit(s)
So a command like git rev-list A
where A is a commit will list commits that are reachable from A inclusive of A.
With that in mind, something like
git rev-list --all ^A
will list commits not reachable from A
So git rev-list --all ^branch
will list all commits not reachable from the tip of branch. Which will remove all the commits in the branch, or in other words commits that are only in other branches.
Now let's come to git rev-list --all --not $(git rev-list --all ^branch)
This will be like git rev-list --all --not {commits only in other branches}
So we want to list all
that are not reachable from all commits only in other branches
Which is the set of commits that are only in branch. Let's take a simple example:
master
|
A------------B
\
\
C--------D--------E
|
branch
Here the goal is to get D and E, the commits not in any other branch.
git rev-list --all ^branch
give only B
Now, git rev-list --all --not B
is what we come down to. Which is also git rev-list -all ^B
- we want all commits not reachable from B. In our case it's is D and E. Which is what we want.
Hope this explains how the command works correctly.
Edit after comment:
git init
echo foo1 >> foo.txt
git add foo.txt
git commit -am "initial valid commit"
git checkout -b merge-only
echo bar >> bar.txt
git add bar.txt
git commit -am "bad commit directly on merge-only"
git checkout master
echo foo2 >> foo.txt
git commit -am "2nd valid commit on master"
After the above steps, if you do a git rev-list --all --not $(git rev-list --all ^merge-only)
you will get the commit you were looking for - the "bad commit directly on merge-only"
one.
But once you do the final step in your steps git merge master
the command will not give the expected output. Because as of now there is no commit that is not there in merge-only since the one extra commit in master also has been merged to merge-only. So git rev-list --all ^branch
gives empty result and hence git rev-list -all --not $(git rev-list --all ^branch)
will give all the commits in merge-only.
Courtesy of my dear friend Redmumba:
git log --no-merges origin/merge-only \
--not $(git for-each-ref --format="%(refname)" refs/remotes/origin |
grep -Fv refs/remotes/origin/merge-only)
...where origin/merge-only
is your remote merge-only branch name. If working on a local-only git repo, substitute refs/remotes/origin
with refs/heads
, and substitute remote branch name origin/merge-only
with local branch name merge-only
, i.e.:
git log --no-merges merge-only \
--not $(git for-each-ref --format="%(refname)" refs/heads |
grep -Fv refs/heads/merge-only)
git log origin/dev..HEAD
This will show you all the commits made in your branch.
Another variation of the accepted answers, to use with master
git log origin/master --not $(git branch -a | grep -Fv master)
Filter all commits that happen in any branch other than master.
We just found this elegant solution
git log --first-parent --no-merges
In your example of course the initial commit still shows up.
this answer does not exactly answer the question, because the initial commit still shows up. On the other hand many people coming here seem to find the answer they are looking for.
Maybe this could help:
git show-branch