如何按拓扑顺序对一组git提交ID进行排序?

Fli*_*imm 9 git

我有一组提交SHA1,没有特别的顺序.我想将此set管道传递给命令,并以拓扑顺序返回这些提交.

这是一种方法:

git rev-list --all --topo-order | grep --file SET_OF_SHA1S
Run Code Online (Sandbox Code Playgroud)

可以想象,这是一种非常缓慢的方式,因为git rev-list必须打印出所有提交SHA1,而不仅仅是我的集合中的那些.

有没有更好更快的方法呢?

使用案例:

我的测试框架测试某些Git提交并将结果存储在数据库中.我正在编写一个总结这些结果的网页,按顺序显示结果会很好.按提交日期排序并不理想,因为某些重新提交的提交将具有完全相同的提交日期.

Fli*_*imm 7

这是加快速度的一种方法:

git rev-list --topo-order $(cat SET_OF_SHA1S) \
   | grep --file SET_OF_SHA1S --max-count $(wc -l SET_OF_SHA1S)
Run Code Online (Sandbox Code Playgroud)

最佳化:

  • 只要求rev-list列出从您的SHA1集中可以访问的所有提交.
  • 只要rev-list打印出包含您感兴趣的SHA1集的足够提交,就告诉grep使用--max-count参数停止grepping .grep将依次关闭其输入,并将rev-list不必要地打印出更多的SHA1.


tor*_*rek 5

您可以使用它--no-walk来防止 git 转储除您提供的 SHA-1 之外的任何 SHA-1,并使用它--topo-order来强制执行正确的顺序。 正如Mort 在评论中指出的那样,这是行不通的。从 git 版本 2.4 开始,git 文档获得了新的文本(间接)指出了这个问题。(我认为这是 中的一个错误git rev-list,它应该加载足够的提交图来进行拓扑排序,然后以正确的顺序仅输出用户指定的修订 ID。)

因此,我的原始脚本(留在此处)也不起作用。--no-walk可以通过从生成临时文件的步骤中删除$TF2,然后使用 的内容$TF1从其(排序的)顺序中提取并打印“有趣的”修订版本来使其工作$TF2

这或多或少就是弗利姆自己的答案的作用。

[原始答案,脚本有缺陷,如下]


我不确定我到底用这段代码做了什么,但很久以前,我编写了一个脚本来检查提供的参数是否按拓扑顺序排列:

#! /bin/sh
#
# check a list of IDs to see if they're in "topo order"
usage()
{
    echo "usage: $0 id [...]"
}

case $# in
0) usage 1>&2; exit 1;;
esac

TF1=$(mktemp)
TF2=$(mktemp)
trap "rm -f $TF1 $TF2; exit" 0 1 2 3 15

# parse the arguments into one file
git rev-parse $@ > $TF1 || exit 1
# and topo-sort the arguments into another
git rev-list --topo-order --no-walk --reverse $@ > $TF2 || exit 1
# If the list is in the correct order the files will be the same
cmp -s $TF1 $TF2 || {
    # If the files differ, it's possible that some argument(s) name
    # the same rev...
    [ $(wc -l < $TF1) -eq $(wc -l < $TF2) ] || {
        echo "ERROR: there are repeats in $@"
        # finding them is a pain, we don't bother trying
        exit 1
    }
    echo "ERROR: $@ NOT in topo order"
    echo "use instead:"
    # read the topo-ordered raw IDs
    while read sha1; do
        # and find the (single) arg in $@ that names this one
        for i; do
            if [ $(git rev-parse $i) = $sha1 ]; then
                printf ' %s' $i
                break
            fi
        done
    done < $TF2
    echo
    exit 1
}
echo "$@ in topo order"
exit 0
Run Code Online (Sandbox Code Playgroud)

我在这里想要的是发出相同的参数名称,例如,如果你说它git-check-topo v1.7 1234567 branchX会告诉你使用(字面意思)branchX v1.7 1234567,如果这就是你正确的顺序,而不是仅仅显示原始的 SHA-1。

为了您的目的,一个简单的:

git rev-list --topo-order --no-walk $@
Run Code Online (Sandbox Code Playgroud)

我认为(有或没有--reverse根据需要)应该有效。