Efficient retrieval of releases that contain a commit

后端 未结 1 1515
Happy的楠姐
Happy的楠姐 2021-01-12 15:13

In the command line, if I type

git tag --contains {commit}

to obtain a list of releases that cont

1条回答
  •  自闭症患者
    2021-01-12 15:56

    You can get this almost directly from git rev-list.

    latest.awk:

    BEGIN { thiscommit=""; }
    $1 == "commit" {
        if ( thiscommit != "" )
            print thiscommit, tags[thiscommit]
        thiscommit=$2
        line[$2]=NR
        latest = 0;
        for ( i = 3 ; i <= NF ; ++i ) if ( line[$i] > latest ) {
            latest = line[$i];
            tags[$2] = tags[$i];
        }
        next;
    }
    $1 != "commit"  { tags[thiscommit] = $0; }
    END { if ( thiscommit != "" ) print thiscommit, tags[thiscommit]; }
    

    a sample command:

    git rev-list --date-order --children --format=%d --all | awk -f latest.awk
    

    you can also use --topo-order, and you'll probably have to weed out unwanted refs in the $1!="commit" logic.

    Depending on what kind of transitivity you want and how explicit the listing has to be, accumulating the tags might need a dictionary. Here's one that gets an explicit listing of all refs for all commits:

    all.awk:

    BEGIN {
        thiscommit="";
    }
    $1 == "commit" {
        if ( thiscommit != "" )
            print thiscommit, tags[thiscommit]
        thiscommit=$2
        line[$2]=NR
        split("",seen);
        for ( i = 3 ; i <= NF ; ++i ) {
            nnew=split(tags[$i],new);
            for ( n = 1 ; n <= nnew ; ++n ) {
                if ( !seen[new[n]] ) {
                    tags[$2]= tags[$2]" "new[n]
                    seen[new[n]] = 1
                }
            }
        }
        next;
    }
    $1 != "commit"  {
        nnew=split($0,new,", ");
        new[1]=substr(new[1],3);
        new[nnew]=substr(new[nnew],1,length(new[nnew])-1);
        for ( n = 1; n <= nnew ; ++n )
            tags[thiscommit] = tags[thiscommit]" "new[n]
    
    }
    END { if ( thiscommit != "" ) print thiscommit, tags[thiscommit]; }
    

    all.awk took a few minutes to do the 322K linux kernel repo commits, about a thousand a second or something like that (lots of duplicate strings and redundant processing) so you'd probably want to rewrite that in C++ if you're really after the complete cross-product ... but I don't think gitk shows that, only the nearest neighbors, right?

    0 讨论(0)
提交回复
热议问题