Referencing the child of a commit in Git
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
add a comment |
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
See also the script/commandgit 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
add a comment |
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
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
git
edited Nov 19 '09 at 9:17
AttishOculus
asked Nov 19 '09 at 8:51
AttishOculusAttishOculus
1,0261918
1,0261918
See also the script/commandgit 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
add a comment |
See also the script/commandgit 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
add a comment |
10 Answers
10
active
oldest
votes
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.
I believe it should begit 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/orgit fsck --unreachable
must be used.
– sleske
Sep 10 '12 at 9:38
1
should begit rev-parse
and notgit-rev-parse
-- won't let me edit the post.
– ben.snape
Feb 13 '13 at 13:29
add a comment |
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.
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 ofgit 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
add a comment |
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.
1
Use--reverse
and usehead -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
add a comment |
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.
add a comment |
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
Thanks - I've fixed it.
– Tom Hale
Sep 20 '16 at 4:09
add a comment |
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}
.
add a comment |
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.
add a comment |
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>
add a comment |
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.
12
Of course I only need the children from the current repository.
– AttishOculus
Nov 19 '09 at 9:38
add a comment |
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.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
I believe it should begit 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/orgit fsck --unreachable
must be used.
– sleske
Sep 10 '12 at 9:38
1
should begit rev-parse
and notgit-rev-parse
-- won't let me edit the post.
– ben.snape
Feb 13 '13 at 13:29
add a comment |
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.
I believe it should begit 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/orgit fsck --unreachable
must be used.
– sleske
Sep 10 '12 at 9:38
1
should begit rev-parse
and notgit-rev-parse
-- won't let me edit the post.
– ben.snape
Feb 13 '13 at 13:29
add a comment |
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.
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.
edited Nov 19 '09 at 14:53
answered Nov 19 '09 at 9:31
AttishOculusAttishOculus
1,0261918
1,0261918
I believe it should begit 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/orgit fsck --unreachable
must be used.
– sleske
Sep 10 '12 at 9:38
1
should begit rev-parse
and notgit-rev-parse
-- won't let me edit the post.
– ben.snape
Feb 13 '13 at 13:29
add a comment |
I believe it should begit 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/orgit fsck --unreachable
must be used.
– sleske
Sep 10 '12 at 9:38
1
should begit rev-parse
and notgit-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
add a comment |
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.
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 ofgit 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
add a comment |
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.
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 ofgit 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
add a comment |
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.
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.
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 ofgit 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
add a comment |
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 ofgit 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
add a comment |
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.
1
Use--reverse
and usehead -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
add a comment |
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.
1
Use--reverse
and usehead -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
add a comment |
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.
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.
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 usehead -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
add a comment |
1
Use--reverse
and usehead -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
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
edited Nov 19 '09 at 9:10
answered Nov 19 '09 at 8:57
tanasciustanascius
41.9k1399126
41.9k1399126
add a comment |
add a comment |
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
Thanks - I've fixed it.
– Tom Hale
Sep 20 '16 at 4:09
add a comment |
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
Thanks - I've fixed it.
– Tom Hale
Sep 20 '16 at 4:09
add a comment |
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
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
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
add a comment |
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
add a comment |
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}
.
add a comment |
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}
.
add a comment |
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}
.
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}
.
answered Nov 19 '09 at 17:51
DustinDustin
68k17100127
68k17100127
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
edited May 23 '17 at 10:30
Community♦
11
11
answered Jan 20 '13 at 16:19
Paul WaglandPaul Wagland
16.9k74467
16.9k74467
add a comment |
add a comment |
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>
add a comment |
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>
add a comment |
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>
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>
answered Nov 22 '13 at 9:48
VonCVonC
832k29026203162
832k29026203162
add a comment |
add a comment |
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.
12
Of course I only need the children from the current repository.
– AttishOculus
Nov 19 '09 at 9:38
add a comment |
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.
12
Of course I only need the children from the current repository.
– AttishOculus
Nov 19 '09 at 9:38
add a comment |
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.
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.
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
add a comment |
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
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Apr 3 '15 at 1:23
Alex DreskoAlex Dresko
3,54412550
3,54412550
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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