Referencing the child of a commit in Git












34














If you want to move the HEAD to the parent of the current HEAD, that's easy:



git reset --hard HEAD^


But is there any simple way to do the exact opposite of this operation, that is, set the head to the current head's first child commit?



Right now, I use gitk as a workaround (alt-tab, up-arrow, alt-tab, middle-click), but I would like a more elegant solution, one that can also be used when gitk is not available.










share|improve this question
























  • See also the script/command git children-of!
    – VonC
    Nov 22 '13 at 9:49






  • 1




    There is a good solution at stackoverflow.com/questions/2263674/…
    – William Pursell
    Jun 14 '14 at 13:38












  • Possible duplicate of How do I find the next commit in git?
    – Ciro Santilli 新疆改造中心 六四事件 法轮功
    Apr 1 '18 at 10:40
















34














If you want to move the HEAD to the parent of the current HEAD, that's easy:



git reset --hard HEAD^


But is there any simple way to do the exact opposite of this operation, that is, set the head to the current head's first child commit?



Right now, I use gitk as a workaround (alt-tab, up-arrow, alt-tab, middle-click), but I would like a more elegant solution, one that can also be used when gitk is not available.










share|improve this question
























  • See also the script/command git children-of!
    – VonC
    Nov 22 '13 at 9:49






  • 1




    There is a good solution at stackoverflow.com/questions/2263674/…
    – William Pursell
    Jun 14 '14 at 13:38












  • Possible duplicate of How do I find the next commit in git?
    – Ciro Santilli 新疆改造中心 六四事件 法轮功
    Apr 1 '18 at 10:40














34












34








34


10





If you want to move the HEAD to the parent of the current HEAD, that's easy:



git reset --hard HEAD^


But is there any simple way to do the exact opposite of this operation, that is, set the head to the current head's first child commit?



Right now, I use gitk as a workaround (alt-tab, up-arrow, alt-tab, middle-click), but I would like a more elegant solution, one that can also be used when gitk is not available.










share|improve this question















If you want to move the HEAD to the parent of the current HEAD, that's easy:



git reset --hard HEAD^


But is there any simple way to do the exact opposite of this operation, that is, set the head to the current head's first child commit?



Right now, I use gitk as a workaround (alt-tab, up-arrow, alt-tab, middle-click), but I would like a more elegant solution, one that can also be used when gitk is not available.







git






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 19 '09 at 9:17







AttishOculus

















asked Nov 19 '09 at 8:51









AttishOculusAttishOculus

1,0261918




1,0261918












  • See also the script/command git children-of!
    – VonC
    Nov 22 '13 at 9:49






  • 1




    There is a good solution at stackoverflow.com/questions/2263674/…
    – William Pursell
    Jun 14 '14 at 13:38












  • Possible duplicate of How do I find the next commit in git?
    – Ciro Santilli 新疆改造中心 六四事件 法轮功
    Apr 1 '18 at 10:40


















  • See also the script/command git children-of!
    – VonC
    Nov 22 '13 at 9:49






  • 1




    There is a good solution at stackoverflow.com/questions/2263674/…
    – William Pursell
    Jun 14 '14 at 13:38












  • Possible duplicate of How do I find the next commit in git?
    – Ciro Santilli 新疆改造中心 六四事件 法轮功
    Apr 1 '18 at 10:40
















See also the script/command git children-of!
– VonC
Nov 22 '13 at 9:49




See also the script/command git children-of!
– VonC
Nov 22 '13 at 9:49




1




1




There is a good solution at stackoverflow.com/questions/2263674/…
– William Pursell
Jun 14 '14 at 13:38






There is a good solution at stackoverflow.com/questions/2263674/…
– William Pursell
Jun 14 '14 at 13:38














Possible duplicate of How do I find the next commit in git?
– Ciro Santilli 新疆改造中心 六四事件 法轮功
Apr 1 '18 at 10:40




Possible duplicate of How do I find the next commit in git?
– Ciro Santilli 新疆改造中心 六四事件 法轮功
Apr 1 '18 at 10:40












10 Answers
10






active

oldest

votes


















16














Very probably not the fastest possible solution, but it does what I need:




#!/bin/bash

REV=$1

if [ x$REV == x ]; then
echo "Usage: git-get-child "
exit
fi

HASH=$(git-rev-parse $REV)

NUM=$2

if [ x$NUM == x ]; then
NUM=1
fi

git rev-list --all --parents | grep " $HASH" | sed -n "${NUM}s/([^ ]*) .*$/\1/p"


The git rev-list --all --parents does exactly what I need: it iterates over all reachable commits, and prints the following line for each:



SHA1_commit SHA1_parent1 SHA1_parent2 etc.



The space in the grep expression ensures that only those lines are found where the SHA1 in question is a parent. Then we get the nth line for the nth child and get the child's SHA1.






share|improve this answer























  • I believe it should be git rev-list --all --parents | grep -m 1 -B $(($NUM-1)) " $HASH" | head -1 | sed 's/ .*//' else it doesn't quite work when $NUM != 1
    – Schwern
    Feb 27 '10 at 3:08






  • 2




    See below for a potentially significant performance improvement
    – MatrixFrog
    Apr 7 '11 at 6:01










  • Note that this does not find dangling commits, i.e. commits no longer reachable from any branch. git reset --hard HEAD^ will typically make the HEAD commit unreachable (unless it is also on a branch). So this may not find all commits. To find all commits, git rev-list --walk-reflog and/or git fsck --unreachable must be used.
    – sleske
    Sep 10 '12 at 9:38






  • 1




    should be git rev-parse and not git-rev-parse -- won't let me edit the post.
    – ben.snape
    Feb 13 '13 at 13:29



















12














The above method using git rev-list --all considers all available commits, which can be a lot and is often not necessary. If the interesting child commits are reachable from some branch, the number of commits that a script interested in child commits needs to process can be reduced:



branches=$(git branch --contains $commit)


will determine the set of branches that $commit is an ancestor of.



Using this set, git rev-list --parents ^$commit $branches should yield exactly the set of all parent-child relationships between $commit and all branch heads that it is an ancestor of.






share|improve this answer























  • This worked for me, however I did have to filter out the '* (no branch)' row, as I was at that point on a detached branch. For my repository this was about 10 times as fast, 0.13 s vs 1.4 seconds.
    – Paul Wagland
    Jan 20 '13 at 15:59










  • consider simplifying the output of git branch with --format='%(refname:short) (to remove the leading space and *)
    – Joshua Goldberg
    Nov 21 '18 at 19:35












  • zsh (but not bash) has trouble with $branches on the second commandline, because of the way the newlines are interpreted. Both bash and zsh work fine if branches is stored as an array: branches=($(git branch --contains ... ))
    – Joshua Goldberg
    Nov 21 '18 at 19:42



















4














Based partly on Paul Wagland's answer and partly on his source, I am using the following:



git log --ancestry-path --format=%H ${commit}..master | tail -1


I found that Paul's answer gave me the wrong output for older commits (possibly due to merging?), where the primary difference is the --ancestry-path flag.






share|improve this answer



















  • 1




    Use --reverse and use head -1 for a mild speed-up
    – Tom Hale
    Sep 18 '16 at 13:49










  • See my answer for a more generic solution
    – Tom Hale
    Sep 19 '16 at 3:53



















3














You can use gitk ... since there can be more than one child there is probably no easy way like HEAD^.



If you want to undo your whole operation you can use the reflog, too. Use git reflog to find your commit’s pointer, which you can use for the reset command. See here.






share|improve this answer































    3














    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






    share|improve this answer























    • Thanks - I've fixed it.
      – Tom Hale
      Sep 20 '16 at 4:09



















    2














    It depends on what you're asking. There could be an infinite number of children of the current head in an infinite number of branches, some local, some remote, and many that have been rebased away and are in your repository, but not part of a history you intend to publish.



    For a simple case, if you have just done a reset to HEAD^, you can get back the child you just threw away as HEAD@{1}.






    share|improve this answer





























      2














      Based on the answer given in How do I find the next commit in git?, I have another solution that works for me.



      Assuming that you want to find the next revision on the "master" branch, then you can do:



      git log --reverse ${commit}..master | sed 's/commit //; q'


      This also assumes that there is one next revision, but that is kind of assumed by the question anyway.






      share|improve this answer































        1














        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>





        share|improve this answer





























          0














          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.






          share|improve this answer

















          • 12




            Of course I only need the children from the current repository.
            – AttishOculus
            Nov 19 '09 at 9:38



















          0














          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.






          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1761825%2freferencing-the-child-of-a-commit-in-git%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            10 Answers
            10






            active

            oldest

            votes








            10 Answers
            10






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            16














            Very probably not the fastest possible solution, but it does what I need:




            #!/bin/bash

            REV=$1

            if [ x$REV == x ]; then
            echo "Usage: git-get-child "
            exit
            fi

            HASH=$(git-rev-parse $REV)

            NUM=$2

            if [ x$NUM == x ]; then
            NUM=1
            fi

            git rev-list --all --parents | grep " $HASH" | sed -n "${NUM}s/([^ ]*) .*$/\1/p"


            The git rev-list --all --parents does exactly what I need: it iterates over all reachable commits, and prints the following line for each:



            SHA1_commit SHA1_parent1 SHA1_parent2 etc.



            The space in the grep expression ensures that only those lines are found where the SHA1 in question is a parent. Then we get the nth line for the nth child and get the child's SHA1.






            share|improve this answer























            • I believe it should be git rev-list --all --parents | grep -m 1 -B $(($NUM-1)) " $HASH" | head -1 | sed 's/ .*//' else it doesn't quite work when $NUM != 1
              – Schwern
              Feb 27 '10 at 3:08






            • 2




              See below for a potentially significant performance improvement
              – MatrixFrog
              Apr 7 '11 at 6:01










            • Note that this does not find dangling commits, i.e. commits no longer reachable from any branch. git reset --hard HEAD^ will typically make the HEAD commit unreachable (unless it is also on a branch). So this may not find all commits. To find all commits, git rev-list --walk-reflog and/or git fsck --unreachable must be used.
              – sleske
              Sep 10 '12 at 9:38






            • 1




              should be git rev-parse and not git-rev-parse -- won't let me edit the post.
              – ben.snape
              Feb 13 '13 at 13:29
















            16














            Very probably not the fastest possible solution, but it does what I need:




            #!/bin/bash

            REV=$1

            if [ x$REV == x ]; then
            echo "Usage: git-get-child "
            exit
            fi

            HASH=$(git-rev-parse $REV)

            NUM=$2

            if [ x$NUM == x ]; then
            NUM=1
            fi

            git rev-list --all --parents | grep " $HASH" | sed -n "${NUM}s/([^ ]*) .*$/\1/p"


            The git rev-list --all --parents does exactly what I need: it iterates over all reachable commits, and prints the following line for each:



            SHA1_commit SHA1_parent1 SHA1_parent2 etc.



            The space in the grep expression ensures that only those lines are found where the SHA1 in question is a parent. Then we get the nth line for the nth child and get the child's SHA1.






            share|improve this answer























            • I believe it should be git rev-list --all --parents | grep -m 1 -B $(($NUM-1)) " $HASH" | head -1 | sed 's/ .*//' else it doesn't quite work when $NUM != 1
              – Schwern
              Feb 27 '10 at 3:08






            • 2




              See below for a potentially significant performance improvement
              – MatrixFrog
              Apr 7 '11 at 6:01










            • Note that this does not find dangling commits, i.e. commits no longer reachable from any branch. git reset --hard HEAD^ will typically make the HEAD commit unreachable (unless it is also on a branch). So this may not find all commits. To find all commits, git rev-list --walk-reflog and/or git fsck --unreachable must be used.
              – sleske
              Sep 10 '12 at 9:38






            • 1




              should be git rev-parse and not git-rev-parse -- won't let me edit the post.
              – ben.snape
              Feb 13 '13 at 13:29














            16












            16








            16






            Very probably not the fastest possible solution, but it does what I need:




            #!/bin/bash

            REV=$1

            if [ x$REV == x ]; then
            echo "Usage: git-get-child "
            exit
            fi

            HASH=$(git-rev-parse $REV)

            NUM=$2

            if [ x$NUM == x ]; then
            NUM=1
            fi

            git rev-list --all --parents | grep " $HASH" | sed -n "${NUM}s/([^ ]*) .*$/\1/p"


            The git rev-list --all --parents does exactly what I need: it iterates over all reachable commits, and prints the following line for each:



            SHA1_commit SHA1_parent1 SHA1_parent2 etc.



            The space in the grep expression ensures that only those lines are found where the SHA1 in question is a parent. Then we get the nth line for the nth child and get the child's SHA1.






            share|improve this answer














            Very probably not the fastest possible solution, but it does what I need:




            #!/bin/bash

            REV=$1

            if [ x$REV == x ]; then
            echo "Usage: git-get-child "
            exit
            fi

            HASH=$(git-rev-parse $REV)

            NUM=$2

            if [ x$NUM == x ]; then
            NUM=1
            fi

            git rev-list --all --parents | grep " $HASH" | sed -n "${NUM}s/([^ ]*) .*$/\1/p"


            The git rev-list --all --parents does exactly what I need: it iterates over all reachable commits, and prints the following line for each:



            SHA1_commit SHA1_parent1 SHA1_parent2 etc.



            The space in the grep expression ensures that only those lines are found where the SHA1 in question is a parent. Then we get the nth line for the nth child and get the child's SHA1.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 19 '09 at 14:53

























            answered Nov 19 '09 at 9:31









            AttishOculusAttishOculus

            1,0261918




            1,0261918












            • I believe it should be git rev-list --all --parents | grep -m 1 -B $(($NUM-1)) " $HASH" | head -1 | sed 's/ .*//' else it doesn't quite work when $NUM != 1
              – Schwern
              Feb 27 '10 at 3:08






            • 2




              See below for a potentially significant performance improvement
              – MatrixFrog
              Apr 7 '11 at 6:01










            • Note that this does not find dangling commits, i.e. commits no longer reachable from any branch. git reset --hard HEAD^ will typically make the HEAD commit unreachable (unless it is also on a branch). So this may not find all commits. To find all commits, git rev-list --walk-reflog and/or git fsck --unreachable must be used.
              – sleske
              Sep 10 '12 at 9:38






            • 1




              should be git rev-parse and not git-rev-parse -- won't let me edit the post.
              – ben.snape
              Feb 13 '13 at 13:29


















            • I believe it should be git rev-list --all --parents | grep -m 1 -B $(($NUM-1)) " $HASH" | head -1 | sed 's/ .*//' else it doesn't quite work when $NUM != 1
              – Schwern
              Feb 27 '10 at 3:08






            • 2




              See below for a potentially significant performance improvement
              – MatrixFrog
              Apr 7 '11 at 6:01










            • Note that this does not find dangling commits, i.e. commits no longer reachable from any branch. git reset --hard HEAD^ will typically make the HEAD commit unreachable (unless it is also on a branch). So this may not find all commits. To find all commits, git rev-list --walk-reflog and/or git fsck --unreachable must be used.
              – sleske
              Sep 10 '12 at 9:38






            • 1




              should be git rev-parse and not git-rev-parse -- won't let me edit the post.
              – ben.snape
              Feb 13 '13 at 13:29
















            I believe it should be git rev-list --all --parents | grep -m 1 -B $(($NUM-1)) " $HASH" | head -1 | sed 's/ .*//' else it doesn't quite work when $NUM != 1
            – Schwern
            Feb 27 '10 at 3:08




            I believe it should be git rev-list --all --parents | grep -m 1 -B $(($NUM-1)) " $HASH" | head -1 | sed 's/ .*//' else it doesn't quite work when $NUM != 1
            – Schwern
            Feb 27 '10 at 3:08




            2




            2




            See below for a potentially significant performance improvement
            – MatrixFrog
            Apr 7 '11 at 6:01




            See below for a potentially significant performance improvement
            – MatrixFrog
            Apr 7 '11 at 6:01












            Note that this does not find dangling commits, i.e. commits no longer reachable from any branch. git reset --hard HEAD^ will typically make the HEAD commit unreachable (unless it is also on a branch). So this may not find all commits. To find all commits, git rev-list --walk-reflog and/or git fsck --unreachable must be used.
            – sleske
            Sep 10 '12 at 9:38




            Note that this does not find dangling commits, i.e. commits no longer reachable from any branch. git reset --hard HEAD^ will typically make the HEAD commit unreachable (unless it is also on a branch). So this may not find all commits. To find all commits, git rev-list --walk-reflog and/or git fsck --unreachable must be used.
            – sleske
            Sep 10 '12 at 9:38




            1




            1




            should be git rev-parse and not git-rev-parse -- won't let me edit the post.
            – ben.snape
            Feb 13 '13 at 13:29




            should be git rev-parse and not git-rev-parse -- won't let me edit the post.
            – ben.snape
            Feb 13 '13 at 13:29













            12














            The above method using git rev-list --all considers all available commits, which can be a lot and is often not necessary. If the interesting child commits are reachable from some branch, the number of commits that a script interested in child commits needs to process can be reduced:



            branches=$(git branch --contains $commit)


            will determine the set of branches that $commit is an ancestor of.



            Using this set, git rev-list --parents ^$commit $branches should yield exactly the set of all parent-child relationships between $commit and all branch heads that it is an ancestor of.






            share|improve this answer























            • This worked for me, however I did have to filter out the '* (no branch)' row, as I was at that point on a detached branch. For my repository this was about 10 times as fast, 0.13 s vs 1.4 seconds.
              – Paul Wagland
              Jan 20 '13 at 15:59










            • consider simplifying the output of git branch with --format='%(refname:short) (to remove the leading space and *)
              – Joshua Goldberg
              Nov 21 '18 at 19:35












            • zsh (but not bash) has trouble with $branches on the second commandline, because of the way the newlines are interpreted. Both bash and zsh work fine if branches is stored as an array: branches=($(git branch --contains ... ))
              – Joshua Goldberg
              Nov 21 '18 at 19:42
















            12














            The above method using git rev-list --all considers all available commits, which can be a lot and is often not necessary. If the interesting child commits are reachable from some branch, the number of commits that a script interested in child commits needs to process can be reduced:



            branches=$(git branch --contains $commit)


            will determine the set of branches that $commit is an ancestor of.



            Using this set, git rev-list --parents ^$commit $branches should yield exactly the set of all parent-child relationships between $commit and all branch heads that it is an ancestor of.






            share|improve this answer























            • This worked for me, however I did have to filter out the '* (no branch)' row, as I was at that point on a detached branch. For my repository this was about 10 times as fast, 0.13 s vs 1.4 seconds.
              – Paul Wagland
              Jan 20 '13 at 15:59










            • consider simplifying the output of git branch with --format='%(refname:short) (to remove the leading space and *)
              – Joshua Goldberg
              Nov 21 '18 at 19:35












            • zsh (but not bash) has trouble with $branches on the second commandline, because of the way the newlines are interpreted. Both bash and zsh work fine if branches is stored as an array: branches=($(git branch --contains ... ))
              – Joshua Goldberg
              Nov 21 '18 at 19:42














            12












            12








            12






            The above method using git rev-list --all considers all available commits, which can be a lot and is often not necessary. If the interesting child commits are reachable from some branch, the number of commits that a script interested in child commits needs to process can be reduced:



            branches=$(git branch --contains $commit)


            will determine the set of branches that $commit is an ancestor of.



            Using this set, git rev-list --parents ^$commit $branches should yield exactly the set of all parent-child relationships between $commit and all branch heads that it is an ancestor of.






            share|improve this answer














            The above method using git rev-list --all considers all available commits, which can be a lot and is often not necessary. If the interesting child commits are reachable from some branch, the number of commits that a script interested in child commits needs to process can be reduced:



            branches=$(git branch --contains $commit)


            will determine the set of branches that $commit is an ancestor of.



            Using this set, git rev-list --parents ^$commit $branches should yield exactly the set of all parent-child relationships between $commit and all branch heads that it is an ancestor of.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 21 '18 at 19:45









            Joshua Goldberg

            2,7781934




            2,7781934










            answered Mar 18 '11 at 14:12









            Rainer BlomeRainer Blome

            40949




            40949












            • This worked for me, however I did have to filter out the '* (no branch)' row, as I was at that point on a detached branch. For my repository this was about 10 times as fast, 0.13 s vs 1.4 seconds.
              – Paul Wagland
              Jan 20 '13 at 15:59










            • consider simplifying the output of git branch with --format='%(refname:short) (to remove the leading space and *)
              – Joshua Goldberg
              Nov 21 '18 at 19:35












            • zsh (but not bash) has trouble with $branches on the second commandline, because of the way the newlines are interpreted. Both bash and zsh work fine if branches is stored as an array: branches=($(git branch --contains ... ))
              – Joshua Goldberg
              Nov 21 '18 at 19:42


















            • This worked for me, however I did have to filter out the '* (no branch)' row, as I was at that point on a detached branch. For my repository this was about 10 times as fast, 0.13 s vs 1.4 seconds.
              – Paul Wagland
              Jan 20 '13 at 15:59










            • consider simplifying the output of git branch with --format='%(refname:short) (to remove the leading space and *)
              – Joshua Goldberg
              Nov 21 '18 at 19:35












            • zsh (but not bash) has trouble with $branches on the second commandline, because of the way the newlines are interpreted. Both bash and zsh work fine if branches is stored as an array: branches=($(git branch --contains ... ))
              – Joshua Goldberg
              Nov 21 '18 at 19:42
















            This worked for me, however I did have to filter out the '* (no branch)' row, as I was at that point on a detached branch. For my repository this was about 10 times as fast, 0.13 s vs 1.4 seconds.
            – Paul Wagland
            Jan 20 '13 at 15:59




            This worked for me, however I did have to filter out the '* (no branch)' row, as I was at that point on a detached branch. For my repository this was about 10 times as fast, 0.13 s vs 1.4 seconds.
            – Paul Wagland
            Jan 20 '13 at 15:59












            consider simplifying the output of git branch with --format='%(refname:short) (to remove the leading space and *)
            – Joshua Goldberg
            Nov 21 '18 at 19:35






            consider simplifying the output of git branch with --format='%(refname:short) (to remove the leading space and *)
            – Joshua Goldberg
            Nov 21 '18 at 19:35














            zsh (but not bash) has trouble with $branches on the second commandline, because of the way the newlines are interpreted. Both bash and zsh work fine if branches is stored as an array: branches=($(git branch --contains ... ))
            – Joshua Goldberg
            Nov 21 '18 at 19:42




            zsh (but not bash) has trouble with $branches on the second commandline, because of the way the newlines are interpreted. Both bash and zsh work fine if branches is stored as an array: branches=($(git branch --contains ... ))
            – Joshua Goldberg
            Nov 21 '18 at 19:42











            4














            Based partly on Paul Wagland's answer and partly on his source, I am using the following:



            git log --ancestry-path --format=%H ${commit}..master | tail -1


            I found that Paul's answer gave me the wrong output for older commits (possibly due to merging?), where the primary difference is the --ancestry-path flag.






            share|improve this answer



















            • 1




              Use --reverse and use head -1 for a mild speed-up
              – Tom Hale
              Sep 18 '16 at 13:49










            • See my answer for a more generic solution
              – Tom Hale
              Sep 19 '16 at 3:53
















            4














            Based partly on Paul Wagland's answer and partly on his source, I am using the following:



            git log --ancestry-path --format=%H ${commit}..master | tail -1


            I found that Paul's answer gave me the wrong output for older commits (possibly due to merging?), where the primary difference is the --ancestry-path flag.






            share|improve this answer



















            • 1




              Use --reverse and use head -1 for a mild speed-up
              – Tom Hale
              Sep 18 '16 at 13:49










            • See my answer for a more generic solution
              – Tom Hale
              Sep 19 '16 at 3:53














            4












            4








            4






            Based partly on Paul Wagland's answer and partly on his source, I am using the following:



            git log --ancestry-path --format=%H ${commit}..master | tail -1


            I found that Paul's answer gave me the wrong output for older commits (possibly due to merging?), where the primary difference is the --ancestry-path flag.






            share|improve this answer














            Based partly on Paul Wagland's answer and partly on his source, I am using the following:



            git log --ancestry-path --format=%H ${commit}..master | tail -1


            I found that Paul's answer gave me the wrong output for older commits (possibly due to merging?), where the primary difference is the --ancestry-path flag.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited May 23 '17 at 11:55









            Community

            11




            11










            answered Jan 9 '14 at 22:59









            MichaelMichael

            3,41333857




            3,41333857








            • 1




              Use --reverse and use head -1 for a mild speed-up
              – Tom Hale
              Sep 18 '16 at 13:49










            • See my answer for a more generic solution
              – Tom Hale
              Sep 19 '16 at 3:53














            • 1




              Use --reverse and use head -1 for a mild speed-up
              – Tom Hale
              Sep 18 '16 at 13:49










            • See my answer for a more generic solution
              – Tom Hale
              Sep 19 '16 at 3:53








            1




            1




            Use --reverse and use head -1 for a mild speed-up
            – Tom Hale
            Sep 18 '16 at 13:49




            Use --reverse and use head -1 for a mild speed-up
            – Tom Hale
            Sep 18 '16 at 13:49












            See my answer for a more generic solution
            – Tom Hale
            Sep 19 '16 at 3:53




            See my answer for a more generic solution
            – Tom Hale
            Sep 19 '16 at 3:53











            3














            You can use gitk ... since there can be more than one child there is probably no easy way like HEAD^.



            If you want to undo your whole operation you can use the reflog, too. Use git reflog to find your commit’s pointer, which you can use for the reset command. See here.






            share|improve this answer




























              3














              You can use gitk ... since there can be more than one child there is probably no easy way like HEAD^.



              If you want to undo your whole operation you can use the reflog, too. Use git reflog to find your commit’s pointer, which you can use for the reset command. See here.






              share|improve this answer


























                3












                3








                3






                You can use gitk ... since there can be more than one child there is probably no easy way like HEAD^.



                If you want to undo your whole operation you can use the reflog, too. Use git reflog to find your commit’s pointer, which you can use for the reset command. See here.






                share|improve this answer














                You can use gitk ... since there can be more than one child there is probably no easy way like HEAD^.



                If you want to undo your whole operation you can use the reflog, too. Use git reflog to find your commit’s pointer, which you can use for the reset command. See here.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 19 '09 at 9:10

























                answered Nov 19 '09 at 8:57









                tanasciustanascius

                41.9k1399126




                41.9k1399126























                    3














                    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






                    share|improve this answer























                    • Thanks - I've fixed it.
                      – Tom Hale
                      Sep 20 '16 at 4:09
















                    3














                    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






                    share|improve this answer























                    • Thanks - I've fixed it.
                      – Tom Hale
                      Sep 20 '16 at 4:09














                    3












                    3








                    3






                    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






                    share|improve this answer














                    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







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 23 '17 at 12:18









                    Community

                    11




                    11










                    answered Sep 18 '16 at 14:14









                    Tom HaleTom Hale

                    6,5364051




                    6,5364051












                    • Thanks - I've fixed it.
                      – Tom Hale
                      Sep 20 '16 at 4:09


















                    • Thanks - I've fixed it.
                      – Tom Hale
                      Sep 20 '16 at 4:09
















                    Thanks - I've fixed it.
                    – Tom Hale
                    Sep 20 '16 at 4:09




                    Thanks - I've fixed it.
                    – Tom Hale
                    Sep 20 '16 at 4:09











                    2














                    It depends on what you're asking. There could be an infinite number of children of the current head in an infinite number of branches, some local, some remote, and many that have been rebased away and are in your repository, but not part of a history you intend to publish.



                    For a simple case, if you have just done a reset to HEAD^, you can get back the child you just threw away as HEAD@{1}.






                    share|improve this answer


























                      2














                      It depends on what you're asking. There could be an infinite number of children of the current head in an infinite number of branches, some local, some remote, and many that have been rebased away and are in your repository, but not part of a history you intend to publish.



                      For a simple case, if you have just done a reset to HEAD^, you can get back the child you just threw away as HEAD@{1}.






                      share|improve this answer
























                        2












                        2








                        2






                        It depends on what you're asking. There could be an infinite number of children of the current head in an infinite number of branches, some local, some remote, and many that have been rebased away and are in your repository, but not part of a history you intend to publish.



                        For a simple case, if you have just done a reset to HEAD^, you can get back the child you just threw away as HEAD@{1}.






                        share|improve this answer












                        It depends on what you're asking. There could be an infinite number of children of the current head in an infinite number of branches, some local, some remote, and many that have been rebased away and are in your repository, but not part of a history you intend to publish.



                        For a simple case, if you have just done a reset to HEAD^, you can get back the child you just threw away as HEAD@{1}.







                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        answered Nov 19 '09 at 17:51









                        DustinDustin

                        68k17100127




                        68k17100127























                            2














                            Based on the answer given in How do I find the next commit in git?, I have another solution that works for me.



                            Assuming that you want to find the next revision on the "master" branch, then you can do:



                            git log --reverse ${commit}..master | sed 's/commit //; q'


                            This also assumes that there is one next revision, but that is kind of assumed by the question anyway.






                            share|improve this answer




























                              2














                              Based on the answer given in How do I find the next commit in git?, I have another solution that works for me.



                              Assuming that you want to find the next revision on the "master" branch, then you can do:



                              git log --reverse ${commit}..master | sed 's/commit //; q'


                              This also assumes that there is one next revision, but that is kind of assumed by the question anyway.






                              share|improve this answer


























                                2












                                2








                                2






                                Based on the answer given in How do I find the next commit in git?, I have another solution that works for me.



                                Assuming that you want to find the next revision on the "master" branch, then you can do:



                                git log --reverse ${commit}..master | sed 's/commit //; q'


                                This also assumes that there is one next revision, but that is kind of assumed by the question anyway.






                                share|improve this answer














                                Based on the answer given in How do I find the next commit in git?, I have another solution that works for me.



                                Assuming that you want to find the next revision on the "master" branch, then you can do:



                                git log --reverse ${commit}..master | sed 's/commit //; q'


                                This also assumes that there is one next revision, but that is kind of assumed by the question anyway.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited May 23 '17 at 10:30









                                Community

                                11




                                11










                                answered Jan 20 '13 at 16:19









                                Paul WaglandPaul Wagland

                                16.9k74467




                                16.9k74467























                                    1














                                    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>





                                    share|improve this answer


























                                      1














                                      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>





                                      share|improve this answer
























                                        1












                                        1








                                        1






                                        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>





                                        share|improve this answer












                                        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>






                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered Nov 22 '13 at 9:48









                                        VonCVonC

                                        832k29026203162




                                        832k29026203162























                                            0














                                            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.






                                            share|improve this answer

















                                            • 12




                                              Of course I only need the children from the current repository.
                                              – AttishOculus
                                              Nov 19 '09 at 9:38
















                                            0














                                            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.






                                            share|improve this answer

















                                            • 12




                                              Of course I only need the children from the current repository.
                                              – AttishOculus
                                              Nov 19 '09 at 9:38














                                            0












                                            0








                                            0






                                            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.






                                            share|improve this answer












                                            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.







                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered Nov 19 '09 at 9:33









                                            u0b34a0f6aeu0b34a0f6ae

                                            31.8k107795




                                            31.8k107795








                                            • 12




                                              Of course I only need the children from the current repository.
                                              – AttishOculus
                                              Nov 19 '09 at 9:38














                                            • 12




                                              Of course I only need the children from the current repository.
                                              – AttishOculus
                                              Nov 19 '09 at 9:38








                                            12




                                            12




                                            Of course I only need the children from the current repository.
                                            – AttishOculus
                                            Nov 19 '09 at 9:38




                                            Of course I only need the children from the current repository.
                                            – AttishOculus
                                            Nov 19 '09 at 9:38











                                            0














                                            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.






                                            share|improve this answer


























                                              0














                                              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.






                                              share|improve this answer
























                                                0












                                                0








                                                0






                                                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.






                                                share|improve this answer












                                                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.







                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered Apr 3 '15 at 1:23









                                                Alex DreskoAlex Dresko

                                                3,54412550




                                                3,54412550






























                                                    draft saved

                                                    draft discarded




















































                                                    Thanks for contributing an answer to Stack Overflow!


                                                    • Please be sure to answer the question. Provide details and share your research!

                                                    But avoid



                                                    • Asking for help, clarification, or responding to other answers.

                                                    • Making statements based on opinion; back them up with references or personal experience.


                                                    To learn more, see our tips on writing great answers.





                                                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                                    Please pay close attention to the following guidance:


                                                    • Please be sure to answer the question. Provide details and share your research!

                                                    But avoid



                                                    • Asking for help, clarification, or responding to other answers.

                                                    • Making statements based on opinion; back them up with references or personal experience.


                                                    To learn more, see our tips on writing great answers.




                                                    draft saved


                                                    draft discarded














                                                    StackExchange.ready(
                                                    function () {
                                                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1761825%2freferencing-the-child-of-a-commit-in-git%23new-answer', 'question_page');
                                                    }
                                                    );

                                                    Post as a guest















                                                    Required, but never shown





















































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown

































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown







                                                    Popular posts from this blog

                                                    404 Error Contact Form 7 ajax form submitting

                                                    How to know if a Active Directory user can login interactively

                                                    Refactoring coordinates for Minecraft Pi buildings written in Python