If you want to move the HEAD
to the parent of the current HEAD
, that\'s easy:
git reset --hard HEAD^
But is there
It is strictly not possible to give a good answer -- since git is distributed, most of the children of the commit you ask about might be in repositories that you don't have on your local machine! That's of course a silly answer, but something to think about. Git rarely implements operations that it can't implement correctly.
This post (http://www.jayway.com/2015/03/30/using-git-commits-to-drive-a-live-coding-session/#comment-282667) shows a neat way if doing it if you can create a well defined tag at the end of your commit stack. Essentially
git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`'
where "demo-end" is the last tag.
You can use the gist of the creator for Hudson (now Jenkins) Kohsuke Kawaguchi (November 2013):
kohsuke / git-children-of:
Given a commit, find immediate children of that commit.
#!/bin/bash -e
# given a commit, find immediate children of that commit.
for arg in "$@"; do
for commit in $(git rev-parse $arg^0); do
for child in $(git log --format='%H %P' --all | grep -F " $commit" | cut -f1 -d' '); do
git describe $child
done
done
done
Put that script in a folder referenced by your $PATH
, and simply type:
git children-of <a-commit>
To just move HEAD (as asked - this doesn't update the index or working tree), use:
git reset --soft $(git child)
You'll need to use the configuration listed below.
Explanation
Based on @Michael's answer, I hacked up the child
alias in my .gitconfig
.
It works as expected in the default case, and is also versatile.
# Get the child commit of the current commit.
# Use $1 instead of 'HEAD' if given. Use $2 instead of curent branch if given.
child = "!bash -c 'git log --format=%H --reverse --ancestry-path ${1:-HEAD}..${2:\"$(git rev-parse --abbrev-ref HEAD)\"} | head -1' -"
It defaults to giving the child of HEAD (unless another commit-ish argument is given) by following the ancestry one step toward the tip of the current branch (unless another commit-ish is given as second argument).
Use %h
instead of %H
if you want the short hash form.
With a detached head, there is no branch, but getting the first child can still be achieved with this alias:
# For the current (or specified) commit-ish, get the all children, print the first child
children = "!bash -c 'c=${1:-HEAD}; set -- $(git rev-list --all --not \"$c\"^@ --children | grep $(git rev-parse \"$c\") ); shift; echo $1' -"
Change the $1
to $*
to print all the children