Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieve the list of child commits of a specific commit in Git

Tags:

I was wondering whether there is an efficient way to retrieve the children of a given commit. Although a method was discussed in Referencing the child of a commit in Git, it is very inefficient.

I thought this would be a straightforward thing to be done in Git, but apparently, it is not.

like image 486
leco Avatar asked Jan 09 '13 22:01

leco


People also ask

How do I find a list of file changes in a specific commit?

Find what file changed in a commit To find out which files changed in a given commit, use the git log --raw command. It's the fastest and simplest way to get insight into which files a commit affects.

How do I get a list of all commits?

On GitHub.com, you can access your project history by selecting the commit button from the code tab on your project. Locally, you can use git log . The git log command enables you to display a list of all of the commits on your current branch. By default, the git log command presents a lot of information all at once.

How do I find a specific commit in git?

If you have the hash for a commit, you can use the git show command to display the changes for that single commit. The output is identical to each individual commit when using git log -p .

Which git command shows the list of previous commits?

The most basic and powerful tool to do this is the git log command. By default, with no arguments, git log lists the commits made in that repository in reverse chronological order; that is, the most recent commits show up first.


2 Answers

git rev-list can show children, but these children have to be reachable from the commits you provide. Assuming you want to show all children reachable from all branches in your repo, you can use something like

git rev-list --all --not $COMMIT^@ --children | grep "^$COMMIT" 

This should output a line that looks like

$COMMIT $child1 $child2 $child3 ... 

For convenience, you can add turn the command into a git alias:

children = "!f() { git rev-list --all --not $1^@ --children | grep $(git rev-parse $1); }; f" # reachable children of a ref 

The syntax $COMMIT^@ might be confusing, so I'll explain it. Hopefully $COMMIT is self-explanatory. This is then followed by ^@, which expands to all parents of the referenced commit. So $COMMIT^@ means "all parents of $COMMIT". Since this follows the --not flag, this instructs rev-list to stop processing after it hits any parent of $COMMIT. This is basically just an optimization, because any commit reachable from $COMMIT cannot possibly be a child.


Note: a previous version of this answer said tail -1 instead of grep "^$COMMIT". This may work in a simple test repo (which is why I initially said it), but there's no guarantee that git rev-list will emit $COMMIT last, if you have any branches that do not contain $COMMIT.

like image 57
Lily Ballard Avatar answered Sep 23 '22 06:09

Lily Ballard


I use the following alias (based on @Lily Ballard's answer:

# Get all children of current or specified commit-ish children = "!bash -c 'c=${1:-HEAD}; set -- $(git rev-list --all --not \"$c\"^@ --children | grep $(git rev-parse \"$c\") ); shift; echo $*' -" 
  • With no argument - gives all children of HEAD
  • With a commit-ish - gives all children of that object
like image 25
Tom Hale Avatar answered Sep 23 '22 06:09

Tom Hale