Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I list all branches that are ancestors of a commit?

Tags:

git

I want to see all branches that are ancestors of commit abcdef1234.

This is sort of the inverse of:

git branch --contains abcdef1234

The above command would list all branches that are descendants of abcdef1234. I want to see a list of all branches that are ancestors of abcdef1234.

I am also interested the equivalent for tags.

UPDATE

To be extra clear, I mean I want to see a list of all commits that meet 2 criteria:

  1. They are ancestors of abcdef1234
  2. They are currently pointed to by (local or remote) branches.

Obviously most commits at some point had a branch pointing to them when they were brand new. I am only interested in whether they are branches at this particular moment.

like image 725
Isaac Betesh Avatar asked May 13 '16 18:05

Isaac Betesh


People also ask

How do you find which branch a commit belongs to?

It is based on "Find merge commit which include a specific commit". Find when a commit was merged into one or more branches. Find the merge commit that brought COMMIT into the specified BRANCH(es). Specifically, look for the oldest commit on the first-parent history of BRANCH that contains the COMMIT as an ancestor.

How can I see which branches are created on github?

If you add --sort=authorname to the above command you can get your branches grouped together.

What does git log show?

The git log command shows a list of all the commits made to a repository. You can see the hash of each Git commit, the message associated with each commit, and more metadata. This command is useful for displaying the history of a repository.

How does git find merge base?

git merge-base finds best common ancestor(s) between two commits to use in a three-way merge. One common ancestor is better than another common ancestor if the latter is an ancestor of the former. A common ancestor that does not have any better common ancestor is a best common ancestor, i.e. a merge base.


3 Answers

git branch --merged abcdef1234 should do what you want. It lists all branches that are merged into the named commit (and thus are ancestors of it), i.e. those whose tip commits are reachable from the named commit.

like image 132
sschuberth Avatar answered Oct 02 '22 16:10

sschuberth


Here's what I suggested as a comment, in expanded form. (I think this is what you're asking for.)

We set K to your chosen commit (abcdefg1234 in your example). Then, we want to iterate through all labels L where L has the form refs/heads/* or refs/remotes/* (all branches and remote-tracking branches). Each label L points to some specific commit C. If C is an ancestor of K, print label L.

[Edit: as sschuberth answered, this is just git branch --merged; the new feature I was thinking of is that git for-each-ref also now implements --merged, which means you can script things more easily, but if all you want is the names, git branch does it. If you do want tags, see git tag --merged, if available. If your version of Git is too old, read on to the script. :-) ]

Here is a shell script (untested!) that implements this. Note that git for-each-ref has new capabilities in later versions of Git that would simplify this, but this should work all the way back to 1.6-ish—maybe 1.7-ish; I forget when git merge-base acquired --is-ancestor.

#! /bin/sh

# find branches and remote-tracking branches that targt
# ancestors of $1.
showthem() {
    local tgt label lbltgt
    tgt=$(git rev-parse "$1") || return $?
    git for-each-ref --format='%(refname:short) %(objectname)' \
            refs/heads refs/remotes |
        while read label lbltgt; do
            if git merge-base --is-ancestor $lbltgt $tgt; then
                echo "$label"
            fi
        done
    return 0
}

case $# in
0) usage 1>&2; exit 1;;
1) showthem "$1";;
*) for i do "echo ${i}:"; showthem "$i" || exit; done
esac

(You may want to tweak this slightly, e.g., to discard symbolic refs like origin/HEAD.)

like image 26
torek Avatar answered Oct 02 '22 15:10

torek


comm -23 <(git branch -a | sort) <(git branch -a --contains abcdefg1234 | sort)

This will give you all the branches that do not have commit abcdefg1234; it's the output of git branch -a minus the output of git branch -a --contains abcdefg1234.

like image 39
Dan Fischer Avatar answered Oct 02 '22 14:10

Dan Fischer