Steve Hollasch
Steve Hollasch

Reputation: 2123

With Git, how can I show the tree of commits that all share a common ancestor?

Suppose I have a 'master' branch, a branch for reviewed & approved changes for my team (call it 'stage'), and a bunch of feature branches all based on the stage branch. (The idea is to group changes into a common pull request from stage into master.)

How can I show the log of all changes based on the "root" of the stage branch? I want to be able to see all features in progress for that team/topic. In vanilla Git terms, how can I get the log of all commits that can reach a given (root) commit? For the life of me, I can't find a way to do this. I can do this for two branches with a common ancestor, but not for N branches derived from a common ancestor.

Upvotes: 3

Views: 931

Answers (3)

LVitya
LVitya

Reputation: 567

I was stuck with the same question. Googling didn't bring something suitable, so I decided to write a script. https://gist.github.com/lvitya/66a9f519d30b7fd2c90d8f95a0b3a1a1 It helps to visualize the tree of your commits.

Here is the contents of the script git_show_graph_from_ancestor.sh

#!/bin/bash -x
# $1 == ancestor

BR_LIST=$(git for-each-ref --contains "$1" --format="%(refname)")
git log "$1"^! $BR_LIST --oneline --decorate --graph

This produces a graph of all commits started from the given ancestor. That is you can see all feature branches based on the common master branch.

$ ~/scripts/git_show_graph_from_ancestor.sh master
* feature2
* commit
* commit
| * feature1
| * commit
|/
* master

Upvotes: 2

jthill
jthill

Reputation: 60255

how can I get the log of all commits that can reach a given (root) commit?

git log --ancestry-path --all --not $given

with any display options you want. --graph --decorate --oneline is the usual starting point, with --simplify-by-decoration to show as few un-decorated commits as practical while still showing the branch structure.

Upvotes: 0

PeterJCLaw
PeterJCLaw

Reputation: 1892

I think that this can be done by using a combination of git branch --contains <id> (as suggested by torek in a comment on the question) and git rev-list.

Specifically, assuming that you have local branches for all of the branches you're interested in (if not, try adding -r or -a to the git branches command), then the following should do what I think you're after:

$ git rev-list $(git branches --contains <ancestor>) --not <ancestor> --pretty=oneline

gitrev-list is a command which will give a list of all revisions which are reachable from some parents but not others. In the above invocation, we're using the list of all branches which contain the given ancestor as the starting points and then excluding all the history prior to that ancestor. Adding --pretty=oneline tells the command to include a brief description of the commit; it would normally just output the revision ids one-per-line.

Bear in mind that this may not quite do what you're after as I think the commits are ordered chronologically rather than by the topological graph of commits. git rev-list has a large number of options though, so there's probably one which can control that ordering.

If you really do want to just list all the commits which have a given ancestor, then there's a more brute-force way to do that (though it will include otherwise unreachable commits and stashes). Again we use rev-list, though instead of passing the list of interesting branches, we just specify --all:

$ git rev-list --all --not <ancestor> --pretty=oneline

Upvotes: 1

Related Questions