@Override
  public @NotNull DetailedLogData readFirstBlock(@NotNull VirtualFile root, @NotNull Requirements requirements) throws VcsException {
    GitRepository repository = getRepository(root);
    if (repository == null) {
      return LogDataImpl.empty();
    }

    // need to query more to sort them manually; this doesn't affect performance: it is equal for -1000 and -2000
    int commitCount = requirements.getCommitCount() * 2;

    String[] params = new String[]{GitUtil.HEAD, "--branches", "--remotes", "--max-count=" + commitCount};
    // NB: not specifying --tags, because it introduces great slowdown if there are many tags,
    // but makes sense only if there are heads without branch or HEAD labels (rare case). Such cases are partially handled below.

    boolean refresh = false, isRefreshRefs = false;

    if (requirements instanceof VcsLogProviderRequirementsEx requirementsEx) {
      refresh = requirementsEx.isRefresh();
      isRefreshRefs = requirementsEx.isRefreshRefs();
    }

    DetailedLogData data = GitLogUtil.collectMetadata(myProject, root, params);

    Set<VcsRef> safeRefs = data.getRefs();
    Set<VcsRef> allRefs = new ObjectOpenCustomHashSet<>(safeRefs, DONT_CONSIDER_SHA);
    Set<VcsRef> branches = Collections.emptySet();

    if (isRefreshRefs) {
      branches = readBranches(repository);
      addNewElements(allRefs, branches);
    }

    Collection<VcsCommitMetadata> allDetails;
    Set<String> currentTagNames = null;
    DetailedLogData commitsFromTags = null;
    if (!refresh || !isRefreshRefs) {
      allDetails = data.getCommits();
    }
    else {
      // on refresh: get new tags, which point to commits not from the first block; then get history, walking down just from these tags
      // on init: just ignore such tagged-only branches. The price for speed-up.
      VcsLogProviderRequirementsEx rex = (VcsLogProviderRequirementsEx)requirements;

      currentTagNames = readCurrentTagNames(root);
      addOldStillExistingTags(allRefs, currentTagNames, rex.getPreviousRefs());

      allDetails = new HashSet<>(data.getCommits());

      Set<String> previousTags = new HashSet<>(ContainerUtil.mapNotNull(rex.getPreviousRefs(), GET_TAG_NAME));
      Set<String> safeTags = new HashSet<>(ContainerUtil.mapNotNull(safeRefs, GET_TAG_NAME));
      Set<String> newUnmatchedTags = remove(currentTagNames, previousTags, safeTags);

      if (!newUnmatchedTags.isEmpty()) {
        commitsFromTags = loadSomeCommitsOnTaggedBranches(root, commitCount, newUnmatchedTags);
        addNewElements(allDetails, commitsFromTags.getCommits());
        addNewElements(allRefs, commitsFromTags.getRefs());
      }
    }

    List<VcsCommitMetadata> sortedCommits = computeWithSpan(myTracer, SortingCommits.getName(), span -> {
      span.setAttribute("rootName", root.getName());
      List<VcsCommitMetadata> commits = VcsLogSorter.sortByDateTopoOrder(allDetails);
      return ContainerUtil.getFirstItems(commits, requirements.getCommitCount());
    });

    if (LOG.isDebugEnabled()) {
      validateDataAndReportError(root, allRefs, sortedCommits, data, branches, currentTagNames, commitsFromTags);
    }

    return new LogDataImpl(allRefs, sortedCommits);
  }
@Override
  public @NotNull DetailedLogData readFirstBlock(@NotNull VirtualFile root, @NotNull Requirements requirements)