@Override
  public void getChanges(@NotNull VcsDirtyScope dirtyScope,
                         @NotNull ChangelistBuilder builder,
                         @NotNull ProgressIndicator progress,
                         @NotNull ChangeListManagerGate addGate) throws VcsException {
    BackgroundTaskUtil.syncPublisher(project, GitRefreshListener.TOPIC).progressStarted();
    isRefreshInProgress = true;
    try {
      LOG.debug("initial dirty scope: ", dirtyScope);
      GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(project);

      Map<GitRepository, GitSubmodule> knownSubmodules = new HashMap<>();
      for (GitRepository repository : GitRepositoryManager.getInstance(project).getRepositories()) {
        Collection<GitRepository> submodules = GitSubmoduleKt.getDirectSubmodules(repository);
        for (GitRepository submodule : submodules) {
          knownSubmodules.put(submodule, new GitSubmodule(submodule, repository));
        }
      }

      List<FilePath> newDirtyPaths = new ArrayList<>();
      NonChangedHolder holder = new NonChangedHolder(project, addGate);

      Map<VirtualFile, RootDirtySet> dirtyPaths =
        GitStagingAreaHolder.collectDirtyPathsPerRoot((GitVcsDirtyScope)dirtyScope, knownSubmodules);
      LOG.debug("after adding nested vcs roots to dirt: ", dirtyPaths);

      for (Map.Entry<VirtualFile, RootDirtySet> entry : dirtyPaths.entrySet()) {
        VirtualFile root = entry.getKey();
        RootDirtySet rootDirtyPaths = entry.getValue();

        LOG.debug("checking root: ", root);
        GitRepository repo = repositoryManager.getRepositoryForRoot(root);
        if (repo == null) continue;

        GitStagingAreaHolder stageAreaHolder = repo.getStagingAreaHolder();

        boolean wasEmptyStaging = stageAreaHolder.isEmpty();
        List<GitFileStatus> newChanges = stageAreaHolder.refresh(rootDirtyPaths);

        GitChangesCollector collector = GitChangesCollector.collect(project, repo, newChanges);
        holder.markHeadRevision(root, collector.getHead());

        Collection<Change> changes = collector.getChanges();
        for (Change change : changes) {
          LOG.debug("process change: ", change);
          builder.processChange(change, GitVcs.getKey());

          FilePath beforePath = ChangesUtil.getBeforePath(change);
          FilePath afterPath = ChangesUtil.getAfterPath(change);

          if (beforePath != null) holder.markPathProcessed(beforePath);
          if (afterPath != null) holder.markPathProcessed(afterPath);

          if (change.isMoved() || change.isRenamed()) {
            if (dirtyScope.belongsTo(beforePath) != dirtyScope.belongsTo(afterPath)) {
              LOG.debug("schedule rename check for: ", change);
              newDirtyPaths.add(beforePath);
              newDirtyPaths.add(afterPath);
            }
          }
        }

        GitSubmodule asSubmodule = knownSubmodules.get(repo);
        if (asSubmodule != null) {
          updateDirtyPathsForSubmodule(asSubmodule, wasEmptyStaging, dirtyPaths, newDirtyPaths);
        }

        BackgroundTaskUtil.syncPublisher(project, GitRefreshListener.TOPIC).repositoryUpdated(repo);
      }
      holder.feedBuilder(dirtyScope, builder);

      VcsDirtyScopeManager.getInstance(project).filePathsDirty(newDirtyPaths, null);
    }
    finally {
      isRefreshInProgress = false;
      BackgroundTaskUtil.syncPublisher(project, GitRefreshListener.TOPIC).progressStopped();
    }
  }
@Override
  public void getChanges(@NotNull VcsDirtyScope dirtyScope,
                         @NotNull ChangelistBuilder builder,
                         @NotNull ProgressIndicator progress,
                         @NotNull ChangeListManagerGate addGate)