在Git中引用提交的孩子

如果要将HEAD移动到当前HEAD的父级,那很简单:

 git reset --hard HEAD^ 

但是有什么简单的方法可以做到与这个操作完全相反的,也就是将头部设置为当前头部的第一个子女提交?

现在,我使用gitk作为解决方法(alt-tab,向上箭头,alt-tab,中键),但我想要一个更优雅的解决scheme,也可以在gitk不可用时使用。

很可能不是最快的解决scheme,但它做我所需要的:

 #!/斌/庆典

 REV = $ 1

如果[x $ REV == x]; 然后
    回声“用法:git-get-child []”
    出口
科幻

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

 NUM = $ 16

如果[x $ NUM == x]; 然后
     NUM = 1
科幻

 git rev-list --all  - 父母|  grep“$ HASH”|  sed -n“$ {NUM} s / \([^] * \)。* $ / \\ 1 / p”

git rev-list --all --parents完成我所需要的工作:它迭代所有可访问的提交,并为每个提交以下行:

SHA1_commit SHA1_parent1 SHA1_parent2

grepexpression式中的空格确保只有在问题的SHA1是父项的位置才能find这些行。 然后我们得到第n个孩子的第n行,并得到孩子的SHA1。

上面的方法使用git rev-list --all考虑所有可用的提交,这可以是很多,往往是没有必要的。 如果有趣的子提交可以从某个分支到达,那么可以减less对一个有兴趣的子提交的提交的提交次数:

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

将确定$ commit是其祖先的一组分支。

使用这个集合, git rev-list --parents ^$commit $branches应该完全产生$ commit和所有分支头之间的所有父子关系的集合,这是它的一个祖先。

部分基于Paul Wagland的回答 ,部分取决于他的来源 ,我使用了以下内容:

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

我发现Paul的答案给了我更旧的提交(可能是由于合并?)的错误输出,其中主要的区别是--ancestry-path标志。

你可以使用gitk …因为可能有多个孩子,可能没有像HEAD^简单方法。

如果你想撤消你的整个操作,你也可以使用reflog。 使用git reflog来查找你可以用于reset命令的提交的指针。 看到这里 。

要移动HEAD(如问 – 这不会更新索引或工作树),使用:

git reset --soft $(git child)

您需要使用下面列出的configuration。

说明

基于@迈克尔的回答 ,我砍了我的.gitconfigchild别名。

它在默认情况下按预期工作,也是多function的。

 # 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' -" 

它默认给HEAD的孩子(除非另外提供一个commit-ish参数),通过跟随祖先一步走向当前分支的尖端(除非另一个提交ish作为第二个参数)。

如果你想使用短哈希表,可以使用%h而不是%H

有一个分离的头,没有分支,但获得第一个孩子仍然可以实现这个别名:

 # 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' -" 

$1更改为$*以打印所有的孩子

这取决于你在问什么。 当前负责人的子女数量可能无限,有些是本地的,有些是偏远的,还有很多已经被重新启用,并且在您的存储库中,但不是您打算发布的历史的一部分。

对于一个简单的例子,如果你刚刚重新设置了HEAD^ ,你可以找回刚才扔掉的孩子HEAD@{1}

基于如何在Git中find下一个提交的答案? ,我有另一个解决scheme,适合我。

假设你想在“master”分支上find下一个版本,那么你可以这样做:

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

这也假设有一个下一个版本,但是这是一个问题。

您可以使用Hudson(现在的Jenkins) Kohsuke Kawaguchi创作者的主旨(2013年11月):
kohsuke / git-children-of

给定提交,find该提交的直接子项。

 #!/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 

把这个脚本放到你的$PATH引用的文件夹中,只需input:

 git children-of <a-commit> 

这是绝对不可能的,因为git是分发的,所以你所提交的提交的大部分子代可能都在你的本地机器上没有的仓库中! 这当然是一个愚蠢的答案,但有些事情要考虑。 Git很less实现无法正确执行的操作。

这篇文章( http://www.jayway.com/2015/03/30/using-git-commits-to-drive-a-live-coding-session/#comment-282667 )显示了一个整洁的方式,如果这样做,如果您可以在提交堆栈的末尾创build一个定义良好的标记。 基本上git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`' git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`' ,其中”demo-end“是最后一个标签。