3

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.

Steve Hollasch
  • 2,011
  • 1
  • 20
  • 18
  • It sounds like you want `git merge-base --octopus` (to find an N-branch merge base, a la the usual two-branch merge base) followed by a `git log ^`. – torek Nov 03 '15 at 22:08
  • But that's rather recursive. To get a list of all changes that contain a given commit, I need to bring a list of all tips that contain that commit. If I could do that, I'd be close to done. But we can start there. So my corollary question is, given a commit, how can I find all tips that can reach that commit? – Steve Hollasch Nov 03 '15 at 22:12
  • 1
    `git branch --contains ` will print a list of all local branch labels that have that commit as an ancestor of their branch-tips. Add `-r` to include remote-tracking branches, if desired (probably not desired). (I had the impression from your question that you had the list of branch-tip labels already.) – torek Nov 03 '15 at 22:14

3 Answers3

1

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
PeterJCLaw
  • 1,862
  • 1
  • 16
  • 20
  • What is `git branches`? I don't seem to have that command on git 2.25.1, and a superficial google search is not turning it up... Perhaps this used to be the name of a command? – stochastic Jan 06 '22 at 17:01
1

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
LVitya
  • 528
  • 4
  • 11
  • 1
    Please don't just post some tool or library as an answer. At least demonstrate [how it solves the problem](http://meta.stackoverflow.com/a/251605) in the answer itself. – Baum mit Augen Jun 12 '17 at 14:30
  • Ok, so I had to post the contents of the bash script. – LVitya Jun 13 '17 at 11:54
  • This (namely the use of `git for-each-ref` ) produced the answer that I was looking for: the branch in question, and all the other branches that are rooted there. – stochastic Jan 06 '22 at 17:00
0

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.

jthill
  • 55,082
  • 5
  • 77
  • 137