GitPushResult () { PushUpdateSettings updateSettings = readPushUpdateSettings(); Label beforePushLabel = null; Label afterPushLabel = null; Map<GitRepository, String> preUpdatePositions = updateRootInfoAndRememberPositions(); Boolean rebaseOverMergeProblemDetected = null; final Map<GitRepository, GitPushRepoResult> results = new HashMap<>(); Map<GitRepository, GitUpdateResult> updatedRoots = new HashMap<>(); try { Collection<GitRepository> remainingRoots = myPushSpecs.keySet(); for (int pushAttempt = 0; pushAttempt < MAX_PUSH_ATTEMPTS && !remainingRoots.isEmpty(); pushAttempt++, remainingRoots = getRejectedAndNotPushed(results)) { LOG.debug("Starting push attempt #" + pushAttempt); Map<GitRepository, GitPushRepoResult> resultMap = push(myRepositoryManager.sortByDependency(remainingRoots)); results.putAll(resultMap); GroupedPushResult result = GroupedPushResult.group(resultMap); // stop if error happens, or if push is rejected for a custom reason (not because a pull is needed) if (!result.errors.isEmpty() || !result.customRejected.isEmpty()) { break; } if (!result.rejected.isEmpty()) { if (myForceMode.isForce() || pushingToNotTrackedBranch(result.rejected) || pushingNotCurrentBranch(result.rejected)) { break; } // propose to update if rejected if (pushAttempt == 0 && !mySettings.autoUpdateIfPushRejected()) { // the dialog will be shown => check for rebase-over-merge problem in advance to avoid showing several dialogs in a row rebaseOverMergeProblemDetected = !findRootsWithMergeCommits(myRepositoryManager.getRepositories()).isEmpty(); updateSettings = showDialogAndGetExitCode(result.rejected.keySet(), updateSettings, rebaseOverMergeProblemDetected.booleanValue()); if (updateSettings == null) break; savePushUpdateSettings(updateSettings, rebaseOverMergeProblemDetected.booleanValue()); } if (beforePushLabel == null) { // put the label only before the very first update beforePushLabel = LocalHistory.getInstance().putSystemLabel(myProject, GitBundle.message("push.local.history.system.label.before")); } Collection<GitRepository> rootsToUpdate = myRepositoryManager.getRepositories(); LOG.debug("roots to update: " + rootsToUpdate); GitUpdateResult updateResult = update(rootsToUpdate, updateSettings.getUpdateMethod(), rebaseOverMergeProblemDetected == null); for (GitRepository repository : rootsToUpdate) { updatedRoots.put(repository, updateResult); // TODO update result in GitUpdateProcess is a single for several roots } if (!updateResult.isSuccess() || updateResult == GitUpdateResult.SUCCESS_WITH_RESOLVED_CONFLICTS || updateResult == GitUpdateResult.INCOMPLETE) { break; } } } } finally { if (beforePushLabel != null) { afterPushLabel = LocalHistory.getInstance().putSystemLabel(myProject, GitBundle.message("push.local.history.system.label.after")); } for (GitRepository repository : myPushSpecs.keySet()) { repository.update(); } } return prepareCombinedResult(results, updatedRoots, preUpdatePositions, beforePushLabel, afterPushLabel); }