mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[git] IDEA-87609 When updating via Rebase, use merge instead of rebase, if it is fast-forward.
Before starting the normal update procedure (with possible stash-unstash), try to perform a fast-forward merge instead of rebase, because it is equal to fast-forward rebase, but is faster, because doesn't require stash-unstash (unless the uncommitted files would be overwritten by merge) Any failure in 'git merge --ff-only' means, than this repository will then be updated in a usual manner. No pre-checking if a fast-forward merge is possible is done, because it is fast enough to execute the command and get the error.
This commit is contained in:
@@ -93,7 +93,7 @@ class GitMergeOperation extends GitBranchOperation {
|
||||
GitSimpleEventDetector mergeConflict = new GitSimpleEventDetector(GitSimpleEventDetector.Event.MERGE_CONFLICT);
|
||||
GitSimpleEventDetector alreadyUpToDateDetector = new GitSimpleEventDetector(GitSimpleEventDetector.Event.ALREADY_UP_TO_DATE);
|
||||
|
||||
GitCommandResult result = myGit.merge(repository, myBranchToMerge,
|
||||
GitCommandResult result = myGit.merge(repository, myBranchToMerge, Collections.<String>emptyList(),
|
||||
localChangesOverwrittenByMerge, unmergedFiles, untrackedOverwrittenByMerge, mergeConflict,
|
||||
alreadyUpToDateDetector);
|
||||
if (result.success()) {
|
||||
@@ -238,7 +238,7 @@ class GitMergeOperation extends GitBranchOperation {
|
||||
private boolean doMerge(@NotNull Collection<GitRepository> repositories) {
|
||||
for (GitRepository repository : repositories) {
|
||||
GitSimpleEventDetector mergeConflict = new GitSimpleEventDetector(GitSimpleEventDetector.Event.MERGE_CONFLICT);
|
||||
GitCommandResult result = myGit.merge(repository, myBranchToMerge, mergeConflict);
|
||||
GitCommandResult result = myGit.merge(repository, myBranchToMerge, Collections.<String>emptyList(), mergeConflict);
|
||||
if (!result.success()) {
|
||||
if (mergeConflict.hasHappened()) {
|
||||
myConflictedRepositories.put(repository, Boolean.TRUE);
|
||||
|
||||
@@ -49,7 +49,8 @@ public interface Git {
|
||||
GitCommandResult clone(@NotNull Project project, @NotNull File parentDirectory, @NotNull String url, @NotNull String clonedDirectoryName);
|
||||
|
||||
@NotNull
|
||||
GitCommandResult merge(@NotNull GitRepository repository, @NotNull String branchToMerge, @NotNull GitLineHandlerListener... listeners);
|
||||
GitCommandResult merge(@NotNull GitRepository repository, @NotNull String branchToMerge, @Nullable List<String> additionalParams,
|
||||
@NotNull GitLineHandlerListener... listeners);
|
||||
|
||||
@NotNull
|
||||
GitCommandResult checkout(@NotNull GitRepository repository, @NotNull String reference, @Nullable String newBranch, boolean force,
|
||||
|
||||
@@ -139,10 +139,13 @@ public class GitImpl implements Git {
|
||||
@Override
|
||||
@NotNull
|
||||
public GitCommandResult merge(@NotNull GitRepository repository, @NotNull String branchToMerge,
|
||||
@NotNull GitLineHandlerListener... listeners) {
|
||||
@Nullable List<String> additionalParams, @NotNull GitLineHandlerListener... listeners) {
|
||||
final GitLineHandler mergeHandler = new GitLineHandler(repository.getProject(), repository.getRoot(), GitCommand.MERGE);
|
||||
mergeHandler.setSilent(false);
|
||||
mergeHandler.addParameters(branchToMerge);
|
||||
if (additionalParams != null) {
|
||||
mergeHandler.addParameters(additionalParams);
|
||||
}
|
||||
for (GitLineHandlerListener listener : listeners) {
|
||||
mergeHandler.addLineListener(listener);
|
||||
}
|
||||
|
||||
@@ -24,12 +24,15 @@ import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.update.UpdatedFiles;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.PlatformFacade;
|
||||
import git4idea.branch.GitBranchPair;
|
||||
import git4idea.commands.*;
|
||||
import git4idea.merge.GitConflictResolver;
|
||||
import git4idea.rebase.GitRebaseProblemDetector;
|
||||
import git4idea.rebase.GitRebaser;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.util.GitUIUtil;
|
||||
import git4idea.util.UntrackedFilesNotifier;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -60,8 +63,7 @@ public class GitRebaseUpdater extends GitUpdater {
|
||||
|
||||
protected GitUpdateResult doUpdate() {
|
||||
LOG.info("doUpdate ");
|
||||
GitBranchPair gitBranchPair = myTrackedBranches.get(myRoot);
|
||||
String remoteBranch = gitBranchPair.getDest().getName();
|
||||
String remoteBranch = getRemoteBranchToMerge();
|
||||
|
||||
final GitLineHandler rebaseHandler = new GitLineHandler(myProject, myRoot, GitCommand.REBASE);
|
||||
rebaseHandler.addParameters(remoteBranch);
|
||||
@@ -99,6 +101,15 @@ public class GitRebaseUpdater extends GitUpdater {
|
||||
return updateResult.get();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getRemoteBranchToMerge() {
|
||||
GitBranchPair gitBranchPair = myTrackedBranches.get(myRoot);
|
||||
GitBranch dest = gitBranchPair.getDest();
|
||||
LOG.assertTrue(dest != null, String.format("Destination branch is null for source branch %s in %s",
|
||||
gitBranchPair.getBranch().getName(), myRoot));
|
||||
return dest.getName();
|
||||
}
|
||||
|
||||
private GitUpdateResult handleRebaseFailure(GitLineHandler pullHandler,
|
||||
GitRebaseProblemDetector rebaseConflictDetector,
|
||||
final GitMessageWithFilesDetector untrackedWouldBeOverwrittenDetector) {
|
||||
@@ -159,6 +170,17 @@ public class GitRebaseUpdater extends GitUpdater {
|
||||
return "Rebase updater";
|
||||
}
|
||||
|
||||
public boolean fastForwardMerge() {
|
||||
LOG.info("Trying fast-forward merge for " + myRoot);
|
||||
GitRepository repository = GitUtil.getRepositoryManager(myProject).getRepositoryForRoot(myRoot);
|
||||
if (repository == null) {
|
||||
LOG.error("Repository is null for " + myRoot);
|
||||
return false;
|
||||
}
|
||||
GitCommandResult result = myGit.merge(repository, getRemoteBranchToMerge(), Collections.singletonList("--ff-only"));
|
||||
return result.success();
|
||||
}
|
||||
|
||||
private static class MyConflictResolver extends GitConflictResolver {
|
||||
private final GitRebaser myRebaser;
|
||||
private final VirtualFile myRoot;
|
||||
|
||||
@@ -134,7 +134,7 @@ public class GitUpdateProcess {
|
||||
|
||||
@NotNull
|
||||
private GitUpdateResult updateImpl(@NotNull UpdateMethod updateMethod, ContinuationContext context) {
|
||||
final Map<VirtualFile, GitUpdater> updaters;
|
||||
Map<VirtualFile, GitUpdater> updaters;
|
||||
try {
|
||||
updaters = defineUpdaters(updateMethod);
|
||||
}
|
||||
@@ -144,6 +144,8 @@ public class GitUpdateProcess {
|
||||
return GitUpdateResult.ERROR;
|
||||
}
|
||||
|
||||
updaters = tryFastForwardMergeForRebaseUpdaters(updaters);
|
||||
|
||||
if (updaters.isEmpty()) {
|
||||
return GitUpdateResult.NOTHING_TO_UPDATE;
|
||||
}
|
||||
@@ -204,6 +206,22 @@ public class GitUpdateProcess {
|
||||
return compoundResult;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Map<VirtualFile, GitUpdater> tryFastForwardMergeForRebaseUpdaters(@NotNull Map<VirtualFile, GitUpdater> updaters) {
|
||||
Map<VirtualFile, GitUpdater> modifiedUpdaters = new HashMap<VirtualFile, GitUpdater>();
|
||||
for (Map.Entry<VirtualFile, GitUpdater> updaterEntry : updaters.entrySet()) {
|
||||
GitUpdater updater = updaterEntry.getValue();
|
||||
if (updater instanceof GitRebaseUpdater) {
|
||||
GitRebaseUpdater rebaseUpdater = (GitRebaseUpdater) updater;
|
||||
if (rebaseUpdater.fastForwardMerge()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
modifiedUpdaters.put(updaterEntry.getKey(), updaterEntry.getValue());
|
||||
}
|
||||
return modifiedUpdaters;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Map<VirtualFile, GitUpdater> defineUpdaters(@NotNull UpdateMethod updateMethod) throws VcsException {
|
||||
final Map<VirtualFile, GitUpdater> updaters = new HashMap<VirtualFile, GitUpdater>();
|
||||
|
||||
@@ -88,7 +88,8 @@ class MockGit implements Git {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
GitCommandResult merge(@NotNull GitRepository repository, @NotNull String branchToMerge, @NotNull GitLineHandlerListener... listeners) {
|
||||
GitCommandResult merge(@NotNull GitRepository repository, @NotNull String branchToMerge, @Nullable List<String> additionalParams,
|
||||
@NotNull GitLineHandlerListener... listeners) {
|
||||
throw new UnsupportedOperationException()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user