protected void perform(@NotNull DialogState dialogState, @NotNull Project project) {
    VirtualFile selectedRoot = dialogState.selectedRoot;
    Supplier<GitLineHandler> handlerProvider = dialogState.handlerProvider;
    Label beforeLabel = LocalHistory.getInstance().putSystemLabel(project, GitBundle.message("merge.action.before.update.label"));
    GitBranch selectedBranch = dialogState.selectedBranch;

    new Task.Backgroundable(project, dialogState.progressTitle, true) {
      @Override
      public void run(@NotNull ProgressIndicator indicator) {
        GitRepositoryManager repositoryManager = GitUtil.getRepositoryManager(project);
        Git git = Git.getInstance();
        GitLocalChangesWouldBeOverwrittenDetector localChangesDetector = new GitLocalChangesWouldBeOverwrittenDetector(selectedRoot, MERGE);
        GitUntrackedFilesOverwrittenByOperationDetector untrackedFilesDetector =
          new GitUntrackedFilesOverwrittenByOperationDetector(selectedRoot);
        GitSimpleEventDetector mergeConflict = new GitSimpleEventDetector(GitSimpleEventDetector.Event.MERGE_CONFLICT);

        GitRepository repository = repositoryManager.getRepositoryForRoot(selectedRoot);
        assert repository != null : "Repository can't be null for root " + selectedRoot;

        GitUpdatedRanges updatedRanges = null;
        if (repository.getCurrentBranch() != null) {
          GitBranchPair refPair = new GitBranchPair(repository.getCurrentBranch(), selectedBranch);
          updatedRanges = GitUpdatedRanges.calcInitialPositions(project, singletonMap(repository, refPair));
        }

        String beforeRevision = repository.getCurrentRevision();

        boolean setupRebaseEditor = shouldSetupRebaseEditor(project, selectedRoot);
        Ref<GitHandlerRebaseEditorManager> rebaseEditorManager = Ref.create();
        try (AccessToken ignore = DvcsUtil.workingTreeChangeStarted(project, GitBundle.message("activity.name.merge"), GitActivity.Merge)) {
          GitCommandResult result = git.runCommand(() -> {
            GitLineHandler handler = handlerProvider.get();

            if (setupRebaseEditor) {
              if (!rebaseEditorManager.isNull()) {
                rebaseEditorManager.get().close();
              }
              GitInteractiveRebaseEditorHandler editor = new GitInteractiveRebaseEditorHandler(project, selectedRoot);
              rebaseEditorManager.set(GitHandlerRebaseEditorManager.prepareEditor(handler, editor));
              handler.overwriteConfig(REBASE_CONFIG_PARAMS);
            }

            handler.addLineListener(localChangesDetector);
            handler.addLineListener(untrackedFilesDetector);
            handler.addLineListener(mergeConflict);
            return handler;
          });

          if (beforeRevision != null) {
            GitRevisionNumber currentRev = new GitRevisionNumber(beforeRevision);
            handleResult(result, project, mergeConflict, localChangesDetector, untrackedFilesDetector, repository, currentRev, beforeLabel,
                         updatedRanges, dialogState.commitAfterMerge);
          }
        }
        finally {
          if (!rebaseEditorManager.isNull()) {
            rebaseEditorManager.get().close();
          }
        }
      }
    }.queue();
  }
protected void perform(@NotNull DialogState dialogState, @NotNull Project project)