Using Git, show all commits that exist * only * on one particular branch, and not * any * others

Given the branch, I would like to see a list of commits that exist only on this branch. In this question, we will discuss ways to determine which commits are on the same branch, but not one or more of the other specified branches.

This is a little different. I would like to see which commits are on one branch, but not on any other branches.

A use case is in a branching strategy where some branches should be merged and never executed directly. This will be used to check if any commits have been made directly in the merge branch.

EDIT: The following are the steps for setting up a dummy git repository for testing:

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" git checkout merge-only git merge master 

Only the message with the message "bad commit on on merge-only" should appear, which was done directly in the merge branch.

+74
git
Apr 19 2018-11-11T00:
source share
7 answers

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 name for the remote merge name. If you work in a local git repository, replace refs/remotes/origin with refs/heads and replace the name of the remote branch origin/merge-only with the name of the local branch 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) 
+26
Apr 19 2018-11-17T00:
source share

We just found this elegant solution.

 git log --first-parent --no-merges 

In your example, of course, the initial commit is still showing up.

this answer does not quite answer the question, because the initial commit still appears. On the other hand, many who come here seem to find the answer they are looking for.

+68
Sep 14 2018-11-11T00:
source share
 git log origin/dev..HEAD 

This will show you all the commit made in your branch.

+16
Apr 29 '16 at 14:32
source share

Perhaps this could help:

  git show-branch 
+12
Apr 19 2018-11-11T00:
source share

@ Answer Prakash works. Just for clarity ...

 git checkout feature-branch git log master..HEAD 

lists commits on the function branch, but not the upstream branch (usually this is your master).

+9
May 19 '17 at 15:15
source share

Try the following:

 git rev-list --all --not $(git rev-list --all ^branch) 

Basically git rev-list --all ^branch gets all revisions not in the branch, and then you all revisions in the repo and subtract the previous list, which is revisions only in the branch.

After @Brian comments:

From the git rev-list 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, displays the commits available from A, including A.

With that in mind, something like

git rev-list --all ^A

will list commits not available from A

So git rev-list --all ^branch list all the commits that are inaccessible from the tip of the branch. Which will delete all commits in the branch, or, in other words, commits that are only in other branches.

Now let's move on to git rev-list --all --not $(git rev-list --all ^branch)

It will be like git rev-list --all --not {commits only in other branches}

So, we want to list all that are not available from all commits only in other branches

This is a set of commits that are only in a branch . Take a simple example:

  master | A------------B \ \ C--------D--------E | branch 

Here the goal is to get D and E, commit is not in any other branch.

git rev-list --all ^branch give only B

Now git rev-list --all --not B is what we are reducing to. Which is also git rev-list -all ^B - we want all commits not to be reached from B. In our case, these are D and E. This is what we want.

Hope this explains how the team 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 git rev-list --all --not $(git rev-list --all ^merge-only) , you will get the command you were looking for - "bad commit directly on merge-only" .

But as soon as you take the last step in the steps of git merge master , the command will not give the expected result. Since there is currently no commit that is not in the merge, only after one additional commit in master has also been merged with the merge. So git rev-list --all ^branch gives an empty result and therefore git rev-list -all --not $(git rev-list --all ^branch) will give everything commits only for merging.

+7
Apr 20 2018-11-11T00:
source share

Another variation of accepted answers for use with master

git log origin/master --not $(git branch -a | grep -Fv master)

Filter out all commits that occur in any branch other than the main one.

+2
Apr 16 '12 at 15:05
source share



All Articles