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

时间:2014-03-28 13:33:41

标签: git

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

以下是这样做的一种方式:

git rev-list --all --topo-order | grep --file SET_OF_SHA1S

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

有更好更快的方法吗?

用例:

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

3 个答案:

答案 0 :(得分:5)

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

git rev-list --topo-order $(cat SET_OF_SHA1S) \
   | grep --file SET_OF_SHA1S --max-count $(wc -l SET_OF_SHA1S)

的优化:

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

答案 1 :(得分:4)

您可以使用--no-walk来阻止git转储除您提供的SHA-1以外的任何SHA-1,并使用--topo-order强制执行正确的命令。 As {{ 3}},这不起作用。 git文档获得了新文本(间接)注意到这个问题,如git版本2.4。 (我认为这是git rev-list中的一个错误,它应该加载足够的提交图来进行拓扑排序,然后以正确的顺序输出用户指定的修订ID。)

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

这或多或少是Mort pointed out in a comment所做的。

[原始答案,有缺陷的剧本,下面]


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

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

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

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

git rev-list --topo-order --no-walk $@
我认为

(根据需要使用或不使用--reverse)。

答案 2 :(得分:1)

加快git rev-list --topo-order速度的另一种方法是使用Git 2.20(2018年第四季度)

请参见commit 561b583commit b454241commit 5284fc5commit f0d9cc4commit d6b4071commit 4b47a9acommit aca4240(2018年11月1日)由Derrick Stolee (derrickstolee)
(由Junio C Hamano -- gitster --commit 62ca33e中合并,2018年11月18日)

  

revision.c:基于世代的拓扑顺序算法

当前的--topo-order算法要求在输出第一个值之前先遍历所有可到达的提交,并对它们进行拓扑排序。

  

此补丁引入了新算法,该算法使用存储的世代号   逐步进入拓扑顺序,在我们进行时输出提交。
  这样可以大大减少编写固定数量的提交的计算时间,例如在使用“ -n <N>”进行限制或填充寻呼机的第一页时。

     

在本地测试中,我在Linux系统信息库中以以下三种模式使用了以下Git命令:

     
      
  • HEAD~1,没有提交图,
  •   
  • HEAD~1和提交图,以及
  •   
  • 带有提交图的HEAD。
  •   
     

这允许比较通过从提交图解析提交而获得的收益,然后再通过限制遍历的提交集来再次获得收益。

Test: git rev-list --topo-order -100 HEAD
HEAD~1, no commit-graph: 6.80 s
HEAD~1, w/ commit-graph: 0.77 s
  HEAD, w/ commit-graph: 0.02 s

查看commit b454241中的所有详细信息。

注意:如commit d6b4071中所述:

  

rev-list命令对Git的功能至关重要。
  以下是一些重要的rev-list操作类型:

     
      
  • 基本git rev-list --topo-order HEAD
  •   
  • 范围git rev-list --topo-order compare..HEAD
  •   
  • 祖先git rev-list --topo-order --ancestry-path compare..HEAD
  •   
  • 对称差异git rev-list --topo-order compare...HEAD
  •   
相关问题