void (List<? extends Change> changes, List<VcsException> exceptions, @NotNull RollbackProgressListener listener) { HashMap<VirtualFile, List<FilePath>> toUnindex = new HashMap<>(); HashMap<VirtualFile, List<FilePath>> toUnversion = new HashMap<>(); HashMap<VirtualFile, List<FilePath>> toRevert = new HashMap<>(); List<FilePath> toDelete = new ArrayList<>(); listener.determinate(); // collect changes to revert for (Change c : changes) { switch (c.getType()) { case NEW -> // note that this the only change that could happen // for HEAD-less working directories. registerFile(toUnversion, c.getAfterRevision().getFile(), exceptions); case MOVED -> { registerFile(toRevert, c.getBeforeRevision().getFile(), exceptions); registerFile(toUnindex, c.getAfterRevision().getFile(), exceptions); toDelete.add(c.getAfterRevision().getFile()); } case MODIFICATION -> // note that changes are also removed from index, if they got into index somehow registerFile(toRevert, c.getBeforeRevision().getFile(), exceptions); case DELETED -> registerFile(toRevert, c.getBeforeRevision().getFile(), exceptions); } } // unindex files for (Map.Entry<VirtualFile, List<FilePath>> entry : toUnindex.entrySet()) { listener.accept(entry.getValue()); try { unindex(entry.getKey(), entry.getValue(), false); } catch (VcsException e) { exceptions.add(e); } } // unversion files for (Map.Entry<VirtualFile, List<FilePath>> entry : toUnversion.entrySet()) { listener.accept(entry.getValue()); try { unindex(entry.getKey(), entry.getValue(), true); } catch (VcsException e) { exceptions.add(e); } } // delete files for (FilePath file : toDelete) { listener.accept(file); try { File ioFile = file.getIOFile(); if (ioFile.exists()) { if (!ioFile.delete()) { exceptions.add(new VcsException(GitBundle.message("error.cannot.delete.file", file.getPresentableUrl()))); } } } catch (Exception e) { exceptions.add(new VcsException(GitBundle.message("error.cannot.delete.file", file.getPresentableUrl()), e)); } } // revert files from HEAD try (AccessToken ignore = DvcsUtil.workingTreeChangeStarted(myProject, getRollbackOperationName())) { for (Map.Entry<VirtualFile, List<FilePath>> entry : toRevert.entrySet()) { listener.accept(entry.getValue()); try { revert(entry.getKey(), entry.getValue()); } catch (VcsException e) { exceptions.add(e); } } } LocalFileSystem lfs = LocalFileSystem.getInstance(); HashSet<File> filesToRefresh = new HashSet<>(); for (Change c : changes) { ContentRevision before = c.getBeforeRevision(); if (before != null) { filesToRefresh.add(new File(before.getFile().getPath())); } ContentRevision after = c.getAfterRevision(); if (after != null) { filesToRefresh.add(new File(after.getFile().getPath())); } } lfs.refreshIoFiles(filesToRefresh); GitIndexFileSystemRefresher.refreshFilePaths(myProject, toUnindex); for (GitRepository repo : GitUtil.getRepositoryManager(myProject).getRepositories()) { repo.update(); } }