Вопрос по git – Эффективный поиск релизов, содержащих коммит

6

В командной строке, если я наберу

git tag --contains {commit}

чтобы получить список выпусков, которые содержат данный коммит, требуется от 11 до 20 секунд для каждого коммита. Поскольку в целевой базе кода существует более 300 000 коммитов, потребуется много времени, чтобы получить эту информацию для всех коммитов.

Тем не мение,gitk по-видимому, удается сделать хорошую работу по извлечению этих данных. Из того, что я искал, он использует кеш для этой цели.

У меня есть два вопроса:

  1. How can I interpret that cache format?
  2. Is there a way to obtain a dump from the git command line tool to generate that same information?
Будет ли работать ваша собственная функциональность Cli-кеша? Если так, то я думаю, что могу предложить некоторые идеи для этого. Alexander Bird
Да, это сработало бы для меня. leco

Ваш Ответ

1   ответ
5

Вы можете получить это почти напрямую от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]; }

пример команды:

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

Вы также можете использовать--topo-orderи вам, вероятно, придется отсеять ненужные ссылки в$1!="commit" логика.

В зависимости от того, какой тип транзитивности вы хотите использовать, и насколько явным должен быть листинг, для накопления тегов может потребоваться словарь. Вот тот, который получает явный список всех ссылок для всех коммитов:

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 Потребовалось несколько минут для выполнения репозиториев ядра Linux 322K, около тысячи секунд или что-то в этом роде (много дублирующихся строк и избыточная обработка), так что вы, вероятно, захотите переписать это в C ++, если вы действительно после завершения перекрестный продукт ... но я не думаю, что Гитк показывает, что только ближайшие соседи, верно?

Таким образом, чтобы уточнить для нас, не-awk пользователей: эти скрипты делают то же самое, что иgit tag --contains {commit}?
rev-list 's% d показывает все ссылки не только теги, поэтому all.awk получает все теги и ветви не только теги, но кроме этого, да, all.awk является партией - содержит ... кстати, он не будет принимать два часа, чтобы выучить awk.

Похожие вопросы