@Override
  public void filesChanged(@NotNull List<? extends @NotNull VFileEvent> events) {
    GitLocalBranch currentBranch = myRepository.getCurrentBranch();

    // which files in .git were changed
    boolean configChanged = false;
    boolean indexChanged = false;
    boolean headChanged = false;
    boolean headMoved = false;
    boolean branchFileChanged = false;
    boolean currentBranchChanged = false;
    boolean packedRefsChanged = false;
    boolean rebaseFileChanged = false;
    boolean mergeFileChanged = false;
    boolean externallyCommitted = false;
    boolean tagChanged = false;
    boolean gitignoreChanged = false;

    Set<VirtualFile> toReloadVfs = new HashSet<>();
    for (VFileEvent event : events) {
      String filePath = event.getPath();
      if (isRootDirChange(event)) {
        if (myRepositoryFiles.isConfigFile(filePath)) {
          configChanged = true;
        }
        else if (myRepositoryFiles.isIndexFile(filePath)) {
          indexChanged = true;
        }
        else if (myRepositoryFiles.isHeadFile(filePath)) {
          headChanged = true;
        }
        else if (myRepositoryFiles.isOrigHeadFile(filePath)) {
          headMoved = true;
        }
        else if (myRepositoryFiles.isBranchFile(filePath)) {
          // it is also possible, that a local branch with complex name ("folder/branch") was created => the folder also to be watched.
          branchFileChanged = true;
          ContainerUtil.addIfNotNull(toReloadVfs, myHeadsDir);

          if (currentBranch != null && myRepositoryFiles.isBranchFile(filePath, currentBranch.getFullName())) {
            currentBranchChanged = true;
          }
        }
        else if (myRepositoryFiles.isRemoteBranchFile(filePath)) {
          // it is possible, that a branch from a new remote was fetch => we need to add new remote folder to the VFS
          branchFileChanged = true;
          ContainerUtil.addIfNotNull(toReloadVfs, myRemotesDir);
        }
        else if (myRepositoryFiles.isPackedRefs(filePath)) {
          packedRefsChanged = true;
        }
        else if (myRepositoryFiles.isRebaseFile(filePath)) {
          rebaseFileChanged = true;
        }
        else if (myRepositoryFiles.isMergeFile(filePath)) {
          mergeFileChanged = true;
        }
        else if (myRepositoryFiles.isCommitMessageFile(filePath)) {
          externallyCommitted = true;
        }
        else if (myRepositoryFiles.isTagFile(filePath)) {
          tagChanged = true;
          ContainerUtil.addIfNotNull(toReloadVfs, myTagsDir);
        }
        else if (myRepositoryFiles.isExclude(filePath)) {
          // TODO watch file stored in core.excludesfile
          gitignoreChanged = true;
        }
      }
      else {
        if (filePath.endsWith(GitRepositoryFiles.GITIGNORE)) {
          gitignoreChanged = true;
        }
      }
    }
    for (VirtualFile dir : toReloadVfs) {
      VfsUtilCore.processFilesRecursively(dir, CommonProcessors.alwaysTrue());
    }

    if (headChanged || configChanged || branchFileChanged || packedRefsChanged || rebaseFileChanged || mergeFileChanged) {
      myRepository.update();
    }
    if (tagChanged || packedRefsChanged) {
      myRepository.getTagHolder().reload();
      BackgroundTaskUtil.syncPublisher(myRepository.getProject(), GitRepository.GIT_REPO_CHANGE).repositoryChanged(myRepository);
    }
    if (configChanged) {
      BackgroundTaskUtil.syncPublisher(myRepository.getProject(), GitConfigListener.TOPIC).notifyConfigChanged(myRepository);
    }
    if (indexChanged || externallyCommitted || headMoved || headChanged || currentBranchChanged || gitignoreChanged) {
      VcsDirtyScopeManager.getInstance(myRepository.getProject()).dirDirtyRecursively(myRepository.getRoot());
      myRepository.getUntrackedFilesHolder().invalidate();
    }
    if (indexChanged) {
      GitIndexFileSystemRefresher.refreshRoots(myRepository.getProject(), Collections.singletonList(myRepository.getRoot()));
    }
  }
@Override
  public void filesChanged(@NotNull List<? extends @NotNull VFileEvent> events)