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.
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.
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.
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 .
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.
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
.
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 $*' -"
HEAD
commit-ish
- gives all children of that objectIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With