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

后端 未结 8 1486
小蘑菇
小蘑菇 2020-12-07 08:17

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

相关标签:
8条回答
  • 2020-12-07 08:44

    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.

    0 讨论(0)
  • 2020-12-07 08:46

    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)
    
    0 讨论(0)
  • 2020-12-07 08:51
    git log origin/dev..HEAD
    

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

    0 讨论(0)
  • 2020-12-07 08:51

    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.

    0 讨论(0)
  • 2020-12-07 08:54

    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.

    0 讨论(0)
  • 2020-12-07 08:57

    Maybe this could help:

    git show-branch

    0 讨论(0)
提交回复
热议问题