Remove experiment flag for rebasing merge commits
This was fully rolled out at Google without any issues. Hence this no
longer needs to be protected by an experiment flag.
Bug: Google b/262486352
Release-Notes: skip
Change-Id: I5e3891ba2594b636d6647514ed7e5435f35933cc
Signed-off-by: Edwin Kempin <ekempin@google.com>
diff --git a/java/com/google/gerrit/server/experiments/ExperimentFeaturesConstants.java b/java/com/google/gerrit/server/experiments/ExperimentFeaturesConstants.java
index 61e3819..cd91745 100644
--- a/java/com/google/gerrit/server/experiments/ExperimentFeaturesConstants.java
+++ b/java/com/google/gerrit/server/experiments/ExperimentFeaturesConstants.java
@@ -57,9 +57,6 @@
public static String GERRIT_BACKEND_FEATURE_ALWAYS_REJECT_IMPLICIT_MERGES_ON_MERGE =
"GerritBackendFeature__always_reject_implicit_merges_on_merge";
- /** Whether the rebase submit strategies should rebase merge commits. */
- public static final String REBASE_MERGE_COMMITS = "GerritBackendFeature__rebase_merge_commits";
-
/** Whether we allow fix suggestions in HumanComments. */
public static final String ALLOW_FIX_SUGGESTIONS_IN_COMMENTS =
"GerritBackendFeature__allow_fix_suggestions_in_comments";
diff --git a/java/com/google/gerrit/server/submit/MergeOp.java b/java/com/google/gerrit/server/submit/MergeOp.java
index 3fa4157..eb41690 100644
--- a/java/com/google/gerrit/server/submit/MergeOp.java
+++ b/java/com/google/gerrit/server/submit/MergeOp.java
@@ -19,7 +19,6 @@
import static com.google.gerrit.server.experiments.ExperimentFeaturesConstants.GERRIT_BACKEND_FEATURE_ALWAYS_REJECT_IMPLICIT_MERGES_ON_MERGE;
import static com.google.gerrit.server.experiments.ExperimentFeaturesConstants.GERRIT_BACKEND_FEATURE_CHECK_IMPLICIT_MERGES_ON_MERGE;
import static com.google.gerrit.server.experiments.ExperimentFeaturesConstants.GERRIT_BACKEND_FEATURE_REJECT_IMPLICIT_MERGES_ON_MERGE;
-import static com.google.gerrit.server.experiments.ExperimentFeaturesConstants.REBASE_MERGE_COMMITS;
import static com.google.gerrit.server.project.ProjectCache.illegalState;
import static com.google.gerrit.server.update.RetryableAction.ActionType.INDEX_QUERY;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.MERGE_CHANGE;
@@ -877,9 +876,7 @@
GERRIT_BACKEND_FEATURE_CHECK_IMPLICIT_MERGES_ON_MERGE, project)) {
return;
}
- boolean rebaseMergeCommits = experimentFeatures.isFeatureEnabled(REBASE_MERGE_COMMITS, project);
- if (submitType == SubmitType.CHERRY_PICK
- || (rebaseMergeCommits && submitType == SubmitType.REBASE_ALWAYS)) {
+ if (submitType == SubmitType.CHERRY_PICK || submitType == SubmitType.REBASE_ALWAYS) {
return;
}
diff --git a/java/com/google/gerrit/server/submit/RebaseSorter.java b/java/com/google/gerrit/server/submit/RebaseSorter.java
index 3645d3f..d769ddd 100644
--- a/java/com/google/gerrit/server/submit/RebaseSorter.java
+++ b/java/com/google/gerrit/server/submit/RebaseSorter.java
@@ -31,6 +31,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevFlag;
@@ -65,8 +66,10 @@
public List<CodeReviewCommit> sort(Collection<CodeReviewCommit> toSort) throws IOException {
final List<CodeReviewCommit> sorted = new ArrayList<>();
final Set<CodeReviewCommit> sort = new HashSet<>(toSort);
+ final Set<ObjectId> uninterestingParents = new HashSet<>();
while (!sort.isEmpty()) {
final CodeReviewCommit n = removeOne(sort);
+ collectUninterestingParents(n, uninterestingParents);
rw.resetRetain(canMergeFlag);
rw.markStart(n);
@@ -77,6 +80,8 @@
CodeReviewCommit c;
final List<CodeReviewCommit> contents = new ArrayList<>();
while ((c = rw.next()) != null) {
+ collectUninterestingParents(c, uninterestingParents);
+
if (!c.has(canMergeFlag) || !incoming.contains(c)) {
if (isMergedInBranchAsSubmittedChange(c, n.change().getDest())
|| isAlreadyMergedInAnyBranch(c)) {
@@ -106,9 +111,27 @@
sorted.removeAll(contents);
sorted.addAll(contents);
}
+ sorted.removeAll(uninterestingParents);
return sorted;
}
+ /**
+ * Rebasing merge commits is done by rebasing their first parent commit, i.e. the first parent is
+ * updated to the new base while the second parent stays intact. This means for chains of changes
+ * we only need to rebase changes that are reachable via the first parents. Changes that are
+ * reachable via second parents do not need to be rebased (since the second parent of merge
+ * commits stays intact) which is why we filter them out here by marking them as uninteresting.
+ */
+ private void collectUninterestingParents(CodeReviewCommit c, Set<ObjectId> uninterestingParents)
+ throws IOException {
+ if (c.getParentCount() > 0) {
+ for (int parent = 1; parent < c.getParentCount(); parent++) {
+ uninterestingParents.add(c.getParent(parent));
+ rw.markUninteresting(c.getParent(parent));
+ }
+ }
+ }
+
private boolean isAlreadyMergedInAnyBranch(CodeReviewCommit commit) throws IOException {
try (CodeReviewRevWalk mirw = CodeReviewCommit.newRevWalk(rw.getObjectReader())) {
mirw.reset();
diff --git a/java/com/google/gerrit/server/submit/RebaseSorterNew.java b/java/com/google/gerrit/server/submit/RebaseSorterNew.java
deleted file mode 100644
index 7fbabb4..0000000
--- a/java/com/google/gerrit/server/submit/RebaseSorterNew.java
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (C) 2012 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.submit;
-
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.entities.BranchNameKey;
-import com.google.gerrit.exceptions.StorageException;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.git.CodeReviewCommit;
-import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
-import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.query.change.InternalChangeQuery;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevFlag;
-
-/**
- * This is a temporary copy of {@code RebaseSorter} with an extension to filter out secondary
- * parents, which is needed for rebasing merge commits. Rebasing merge commits is protected by an
- * experiment flag, which means for now we have to keep the old logic working (hence we cannot
- * replace the original {@code RebaseSorter} yet. Once the experiment was successful, we will
- * replace {@code RebaseSorter} with this class.
- */
-public class RebaseSorterNew {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private final CurrentUser caller;
- private final CodeReviewRevWalk rw;
- private final RevFlag canMergeFlag;
- private final RevCommit initialTip;
- private final Set<RevCommit> alreadyAccepted;
- private final Provider<InternalChangeQuery> queryProvider;
- private final Set<CodeReviewCommit> incoming;
-
- public RebaseSorterNew(
- CurrentUser caller,
- CodeReviewRevWalk rw,
- RevCommit initialTip,
- Set<RevCommit> alreadyAccepted,
- RevFlag canMergeFlag,
- Provider<InternalChangeQuery> queryProvider,
- Set<CodeReviewCommit> incoming) {
- this.caller = caller;
- this.rw = rw;
- this.canMergeFlag = canMergeFlag;
- this.initialTip = initialTip;
- this.alreadyAccepted = alreadyAccepted;
- this.queryProvider = queryProvider;
- this.incoming = incoming;
- }
-
- public List<CodeReviewCommit> sort(Collection<CodeReviewCommit> toSort) throws IOException {
- final List<CodeReviewCommit> sorted = new ArrayList<>();
- final Set<CodeReviewCommit> sort = new HashSet<>(toSort);
- final Set<ObjectId> uninterestingParents = new HashSet<>();
- while (!sort.isEmpty()) {
- final CodeReviewCommit n = removeOne(sort);
- collectUninterestingParents(n, uninterestingParents);
-
- rw.resetRetain(canMergeFlag);
- rw.markStart(n);
- if (initialTip != null) {
- rw.markUninteresting(initialTip);
- }
-
- CodeReviewCommit c;
- final List<CodeReviewCommit> contents = new ArrayList<>();
- while ((c = rw.next()) != null) {
- collectUninterestingParents(c, uninterestingParents);
-
- if (!c.has(canMergeFlag) || !incoming.contains(c)) {
- if (isMergedInBranchAsSubmittedChange(c, n.change().getDest())
- || isAlreadyMergedInAnyBranch(c)) {
- rw.markUninteresting(c);
- } else {
- // We cannot merge n as it would bring something we
- // aren't permitted to merge at this time. Drop n.
- //
- n.setStatusCode(CommitMergeStatus.MISSING_DEPENDENCY);
- n.setStatusMessage(
- CommitMergeStatus.createMissingDependencyMessage(
- caller, queryProvider, n.name(), c.name()));
- }
- // Stop RevWalk because c is either a merged commit or a missing
- // dependency. Not need to walk further.
- break;
- }
- contents.add(c);
- }
-
- if (n.getStatusCode() == CommitMergeStatus.MISSING_DEPENDENCY) {
- continue;
- }
-
- sort.removeAll(contents);
- Collections.reverse(contents);
- sorted.removeAll(contents);
- sorted.addAll(contents);
- }
- sorted.removeAll(uninterestingParents);
- return sorted;
- }
-
- /**
- * Rebasing merge commits is done by rebasing their first parent commit, i.e. the first parent is
- * updated to the new base while the second parent stays intact. This means for chains of changes
- * we only need to rebase changes that are reachable via the first parents. Changes that are
- * reachable via second parents do not need to be rebased (since the second parent of merge
- * commits stays intact) which is why we filter them out here by marking them as uninteresting.
- */
- private void collectUninterestingParents(CodeReviewCommit c, Set<ObjectId> uninterestingParents)
- throws IOException {
- if (c.getParentCount() > 0) {
- for (int parent = 1; parent < c.getParentCount(); parent++) {
- uninterestingParents.add(c.getParent(parent));
- rw.markUninteresting(c.getParent(parent));
- }
- }
- }
-
- private boolean isAlreadyMergedInAnyBranch(CodeReviewCommit commit) throws IOException {
- try (CodeReviewRevWalk mirw = CodeReviewCommit.newRevWalk(rw.getObjectReader())) {
- mirw.reset();
- mirw.markStart(commit);
- // check if the commit is merged in other branches
- for (RevCommit accepted : alreadyAccepted) {
- if (mirw.isMergedInto(mirw.parseCommit(commit), mirw.parseCommit(accepted))) {
- logger.atFine().log(
- "Dependency %s merged into branch head %s.", commit.getName(), accepted.getName());
- return true;
- }
- }
- return false;
- } catch (StorageException e) {
- throw new IOException(e);
- }
- }
-
- private boolean isMergedInBranchAsSubmittedChange(CodeReviewCommit commit, BranchNameKey dest) {
- List<ChangeData> changes = queryProvider.get().byBranchCommit(dest, commit.getId().getName());
- for (ChangeData change : changes) {
- if (change.change().isMerged()) {
- logger.atFine().log(
- "Dependency %s associated with merged change %s.", commit.getName(), change.getId());
- return true;
- }
- }
- return false;
- }
-
- private static <T> T removeOne(Collection<T> c) {
- final Iterator<T> i = c.iterator();
- final T r = i.next();
- i.remove();
- return r;
- }
-}
diff --git a/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java b/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
index 9ba1f48..e3d7fc4 100644
--- a/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
+++ b/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
@@ -15,12 +15,9 @@
package com.google.gerrit.server.submit;
import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.ImmutableList.toImmutableList;
-import static com.google.gerrit.server.experiments.ExperimentFeaturesConstants.REBASE_MERGE_COMMITS;
import static com.google.gerrit.server.submit.CommitMergeStatus.EMPTY_COMMIT;
import com.google.common.collect.ImmutableList;
-import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.BooleanProjectConfig;
import com.google.gerrit.entities.PatchSet;
@@ -43,13 +40,10 @@
import java.io.IOException;
import java.util.Collection;
import java.util.List;
-import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
/** This strategy covers RebaseAlways and RebaseIfNecessary ones. */
public class RebaseSubmitStrategy extends SubmitStrategy {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
private final boolean rebaseAlways;
RebaseSubmitStrategy(SubmitStrategy.Arguments args, boolean rebaseAlways) {
@@ -59,55 +53,13 @@
@Override
public ImmutableList<SubmitStrategyOp> buildOps(Collection<CodeReviewCommit> toMerge) {
- boolean rebaseMergeCommits =
- args.experimentFeatures.isFeatureEnabled(REBASE_MERGE_COMMITS, args.destBranch.project());
- logger.atFine().log("rebaseMergeCommits=%s", rebaseMergeCommits);
-
List<CodeReviewCommit> sorted;
try {
- sorted =
- rebaseMergeCommits ? args.rebaseSorterNew.sort(toMerge) : args.rebaseSorter.sort(toMerge);
+ sorted = args.rebaseSorter.sort(toMerge);
} catch (IOException | StorageException e) {
throw new StorageException("Commit sorting failed", e);
}
- if (!rebaseMergeCommits) {
- // We cannot rebase merge commits. This is why we integrate merge changes into the target
- // branch the same way as if MERGE_IF_NECESSARY was the submit strategy. This means if needed
- // we create a merge commit that integrates the merge change into the target branch.
- // If we integrate a change series that consists out of a normal change and a merge change,
- // where the merge change depends on the normal change, we must skip rebasing the normal
- // change, because it already gets integrated by merging the merge change. If the rebasing of
- // the normal change is not skipped, it would appear twice in the history after the submit is
- // done (once through its rebased commit, and once through its original commit which is a
- // parent of the merge change that was merged into the target branch. To skip the rebasing of
- // the normal change, we call MergeUtil#reduceToMinimalMerge, as it excludes commits which
- // will be implicitly integrated by merging the series. Then we use the MergeIfNecessaryOp to
- // integrate the whole series.
- // If on the other hand, we integrate a change series that consists out of a merge change and
- // a normal change, where the normal change depends on the merge change, we can first
- // integrate the merge change by a merge and then integrate the normal change by a rebase. In
- // this case we do not want to call MergeUtil#reduceToMinimalMerge as we are not intending to
- // integrate the whole series by a merge, but rather do the integration of the commits one by
- // one.
- boolean foundNonMerge = false;
- for (CodeReviewCommit c : sorted) {
- if (c.getParentCount() > 1) {
- if (!foundNonMerge) {
- // found a merge change, but it doesn't depend on a normal change, this means we are not
- // required to merge the whole series at once
- continue;
- }
- // found a merge commit that depends on a normal change, this means we are required to
- // merge
- // the whole series at once
- sorted = args.mergeUtil.reduceToMinimalMerge(args.mergeSorter, sorted);
- return sorted.stream().map(n -> new MergeIfNecessaryOp(n)).collect(toImmutableList());
- }
- foundNonMerge = true;
- }
- }
-
ImmutableList.Builder<SubmitStrategyOp> ops =
ImmutableList.builderWithExpectedSize(sorted.size());
boolean first = true;
@@ -119,12 +71,8 @@
ops.add(new FastForwardOp(args, n));
} else if (n.getParentCount() == 0) {
ops.add(new RebaseRootOp(n));
- } else if (rebaseMergeCommits) {
- ops.add(new RebaseOneOp(n));
- } else if (n.getParentCount() == 1) {
- ops.add(new RebaseOneOp(n));
} else {
- ops.add(new MergeIfNecessaryOp(n));
+ ops.add(new RebaseOneOp(n));
}
first = false;
}
@@ -270,49 +218,6 @@
}
}
- private class MergeIfNecessaryOp extends SubmitStrategyOp {
- private MergeIfNecessaryOp(CodeReviewCommit toMerge) {
- super(RebaseSubmitStrategy.this.args, toMerge);
- }
-
- @Override
- public void updateRepoImpl(RepoContext ctx) throws IntegrationConflictException, IOException {
- // There are multiple parents, so this is a merge commit. We don't want
- // to rebase the merge as clients can't easily rebase their history with
- // that merge present and replaced by an equivalent merge with a different
- // first parent. So instead behave as though MERGE_IF_NECESSARY was
- // configured.
- // TODO(tandrii): this is not in spirit of RebaseAlways strategy because
- // the commit messages can not be modified in the process. It's also
- // possible to implement rebasing of merge commits. E.g., the Cherry Pick
- // REST endpoint already supports cherry-picking of merge commits.
- // For now, users of RebaseAlways strategy for whom changed commit footers
- // are important would be well advised to prohibit uploading patches with
- // merge commits.
- MergeTip mergeTip = args.mergeTip;
- if (args.rw.isMergedInto(mergeTip.getCurrentTip(), toMerge)
- && !args.subscriptionGraph.hasSubscription(args.destBranch)) {
- mergeTip.moveTipTo(toMerge, toMerge);
- } else {
- PersonIdent caller = ctx.newCommitterIdent();
- CodeReviewCommit newTip =
- args.mergeUtil.mergeOneCommit(
- caller,
- caller,
- args.rw,
- ctx.getInserter(),
- ctx.getRepoView().getConfig(),
- args.destBranch,
- mergeTip.getCurrentTip(),
- toMerge);
- mergeTip.moveTipTo(amendGitlink(newTip), toMerge);
- }
- args.mergeUtil.markCleanMerges(
- args.rw, args.canMergeFlag, mergeTip.getCurrentTip(), args.alreadyAccepted);
- acceptMergeTip(mergeTip);
- }
- }
-
private void acceptMergeTip(MergeTip mergeTip) {
args.alreadyAccepted.add(mergeTip.getCurrentTip());
}
diff --git a/java/com/google/gerrit/server/submit/SubmitStrategy.java b/java/com/google/gerrit/server/submit/SubmitStrategy.java
index 4b95685..d4dd67a 100644
--- a/java/com/google/gerrit/server/submit/SubmitStrategy.java
+++ b/java/com/google/gerrit/server/submit/SubmitStrategy.java
@@ -38,7 +38,6 @@
import com.google.gerrit.server.change.RebaseChangeOp;
import com.google.gerrit.server.change.SetPrivateOp;
import com.google.gerrit.server.change.TestSubmitInput;
-import com.google.gerrit.server.experiments.ExperimentFeatures;
import com.google.gerrit.server.extensions.events.ChangeMerged;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
@@ -127,7 +126,6 @@
final ProjectConfig.Factory projectConfigFactory;
final SetPrivateOp.Factory setPrivateOpFactory;
final SubmitWithStickyApprovalDiff submitWithStickyApprovalDiff;
- final ExperimentFeatures experimentFeatures;
final BranchNameKey destBranch;
final CodeReviewRevWalk rw;
@@ -145,7 +143,6 @@
final ProjectState project;
final MergeSorter mergeSorter;
final RebaseSorter rebaseSorter;
- final RebaseSorterNew rebaseSorterNew;
final MergeUtil mergeUtil;
final boolean dryrun;
@@ -170,7 +167,6 @@
ProjectConfig.Factory projectConfigFactory,
SetPrivateOp.Factory setPrivateOpFactory,
SubmitWithStickyApprovalDiff submitWithStickyApprovalDiff,
- ExperimentFeatures experimentFeatures,
@Assisted BranchNameKey destBranch,
@Assisted CommitStatus commitStatus,
@Assisted CodeReviewRevWalk rw,
@@ -201,7 +197,6 @@
this.queryProvider = queryProvider;
this.setPrivateOpFactory = setPrivateOpFactory;
this.submitWithStickyApprovalDiff = submitWithStickyApprovalDiff;
- this.experimentFeatures = experimentFeatures;
this.serverIdent = serverIdent;
this.destBranch = destBranch;
@@ -231,15 +226,6 @@
canMergeFlag,
queryProvider,
incoming);
- this.rebaseSorterNew =
- new RebaseSorterNew(
- caller,
- rw,
- mergeTip.getInitialTip(),
- alreadyAccepted,
- canMergeFlag,
- queryProvider,
- incoming);
this.mergeUtil = mergeUtilFactory.create(project);
this.onSubmitValidatorsFactory = onSubmitValidatorsFactory;
}
diff --git a/javatests/com/google/gerrit/acceptance/api/config/ListExperimentsIT.java b/javatests/com/google/gerrit/acceptance/api/config/ListExperimentsIT.java
index a8b3e60..fe3cb00 100644
--- a/javatests/com/google/gerrit/acceptance/api/config/ListExperimentsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/config/ListExperimentsIT.java
@@ -52,7 +52,6 @@
.GERRIT_BACKEND_FEATURE_ALWAYS_REJECT_IMPLICIT_MERGES_ON_MERGE,
ExperimentFeaturesConstants.GERRIT_BACKEND_FEATURE_ATTACH_NONCE_TO_DOCUMENTATION,
ExperimentFeaturesConstants.GERRIT_BACKEND_FEATURE_CHECK_IMPLICIT_MERGES_ON_MERGE,
- ExperimentFeaturesConstants.REBASE_MERGE_COMMITS,
ExperimentFeaturesConstants.GERRIT_BACKEND_FEATURE_REJECT_IMPLICIT_MERGES_ON_MERGE)
.inOrder();
@@ -88,7 +87,6 @@
.GERRIT_BACKEND_FEATURE_ATTACH_NONCE_TO_DOCUMENTATION)
.enabled)
.isFalse();
- assertThat(experiments.get(ExperimentFeaturesConstants.REBASE_MERGE_COMMITS).enabled).isFalse();
}
@Test
diff --git a/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitByCherryPickOrRebaseAlwaysIT.java b/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitByCherryPickOrRebaseAlwaysIT.java
index 78c2786..592220e 100644
--- a/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitByCherryPickOrRebaseAlwaysIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitByCherryPickOrRebaseAlwaysIT.java
@@ -18,11 +18,9 @@
import static com.google.common.truth.TruthJUnit.assume;
import com.google.common.collect.ImmutableMap;
-import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.common.ChangeInfo;
-import com.google.gerrit.server.experiments.ExperimentFeaturesConstants;
import com.google.gerrit.testing.ConfigSuite;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -78,9 +76,6 @@
}
@Test
- @GerritConfig(
- name = "experiments.enabled",
- value = ExperimentFeaturesConstants.REBASE_MERGE_COMMITS)
public void doesntAddContentFromParentForImplicitMergeChange() throws Exception {
gApi.changes().id(implicitMergeChangeId).current().submit();
diff --git a/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitExperimentsIT.java b/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitExperimentsIT.java
index 6739071..d85e613 100644
--- a/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitExperimentsIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/ImplicitMergeOnSubmitExperimentsIT.java
@@ -60,7 +60,9 @@
// uses @RunWith(ConfigSuite.class). Emulate parameters using configs.
ImmutableMap.Builder<String, Config> builder = ImmutableMap.builder();
for (SubmitType submitType : SubmitType.values()) {
- if (submitType == SubmitType.INHERIT || submitType == SubmitType.CHERRY_PICK) {
+ if (submitType == SubmitType.INHERIT
+ || submitType == SubmitType.CHERRY_PICK
+ || submitType == SubmitType.REBASE_ALWAYS) {
continue;
}
Config cfg = new Config();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
index b9c07a2..25af040 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -93,7 +93,6 @@
import com.google.gerrit.server.change.MergeabilityComputationBehavior;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.change.TestSubmitInput;
-import com.google.gerrit.server.experiments.ExperimentFeaturesConstants;
import com.google.gerrit.server.git.validators.OnSubmitValidationListener;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.notedb.ChangeNotes;
@@ -689,36 +688,6 @@
List<RevCommit> log = getRemoteLog();
assertThat(log).contains(stable.getCommit());
- assertThat(log).contains(mergeReview.getCommit());
- }
-
- @Test
- @GerritConfig(
- name = "experiments.enabled",
- value = ExperimentFeaturesConstants.REBASE_MERGE_COMMITS)
- public void submitMergeOfNonChangeBranchTip_withRebasingMergeCommits() throws Throwable {
- // Merge a branch with commits that have not been submitted as
- // changes.
- //
- // M -- mergeCommit (pushed for review and submitted)
- // | \
- // | S -- stable (pushed directly to refs/heads/stable)
- // | /
- // I -- master
- //
- RevCommit master = projectOperations.project(project).getHead("master");
- PushOneCommit stableTip =
- pushFactory.create(admin.newIdent(), testRepo, "Tip of branch stable", "stable.txt", "");
- PushOneCommit.Result stable = stableTip.to("refs/heads/stable");
- PushOneCommit mergeCommit =
- pushFactory.create(admin.newIdent(), testRepo, "The merge commit", "merge.txt", "");
- mergeCommit.setParents(ImmutableList.of(master, stable.getCommit()));
- PushOneCommit.Result mergeReview = mergeCommit.to("refs/for/master");
- approve(mergeReview.getChangeId());
- submit(mergeReview.getChangeId());
-
- List<RevCommit> log = getRemoteLog();
- assertThat(log).contains(stable.getCommit());
if (getSubmitType() == SubmitType.REBASE_ALWAYS) {
// the merge commit has been rebased
@@ -773,53 +742,6 @@
List<RevCommit> log = getRemoteLog();
assertThat(log).contains(s1.getCommit());
- assertThat(log).contains(mergeReview.getCommit());
- }
-
- @Test
- @GerritConfig(
- name = "experiments.enabled",
- value = ExperimentFeaturesConstants.REBASE_MERGE_COMMITS)
- public void submitMergeOfNonChangeBranchNonTip_withRebasingMergeCommits() throws Throwable {
- // Merge a branch with commits that have not been submitted as
- // changes.
- //
- // MC -- merge commit (pushed for review and submitted)
- // |\ S2 -- new stable tip (pushed directly to refs/heads/stable)
- // M \ /
- // | S1 -- stable (pushed directly to refs/heads/stable)
- // | /
- // I -- master
- //
- RevCommit initial = projectOperations.project(project).getHead("master");
- // push directly to stable to S1
- PushOneCommit.Result s1 =
- pushFactory
- .create(admin.newIdent(), testRepo, "new commit into stable", "stable1.txt", "")
- .to("refs/heads/stable");
- // move the stable tip ahead to S2
- pushFactory
- .create(admin.newIdent(), testRepo, "Tip of branch stable", "stable2.txt", "")
- .to("refs/heads/stable");
-
- testRepo.reset(initial);
-
- // move the master ahead
- PushOneCommit.Result m =
- pushFactory
- .create(admin.newIdent(), testRepo, "Move master ahead", "master.txt", "")
- .to("refs/heads/master");
-
- // create merge change
- PushOneCommit mc =
- pushFactory.create(admin.newIdent(), testRepo, "The merge commit", "merge.txt", "");
- mc.setParents(ImmutableList.of(m.getCommit(), s1.getCommit()));
- PushOneCommit.Result mergeReview = mc.to("refs/for/master");
- approve(mergeReview.getChangeId());
- submit(mergeReview.getChangeId());
-
- List<RevCommit> log = getRemoteLog();
- assertThat(log).contains(s1.getCommit());
if (getSubmitType() == SubmitType.REBASE_ALWAYS) {
// the merge commit has been rebased
@@ -1059,81 +981,6 @@
assertMerged(mergeId);
testRepo.git().fetch().call();
RevWalk rw = testRepo.getRevWalk();
- master = rw.parseCommit(projectOperations.project(project).getHead("master"));
- assertThat(rw.isMergedInto(merge, master)).isTrue();
- assertThat(rw.isMergedInto(fix, master)).isTrue();
- }
-
- @Test
- @GerritConfig(
- name = "experiments.enabled",
- value = ExperimentFeaturesConstants.REBASE_MERGE_COMMITS)
- public void submitWithCommitAndItsMergeCommitTogether_withRebasingMergeCommits()
- throws Throwable {
- assume().that(isSubmitWholeTopicEnabled()).isTrue();
-
- RevCommit initialHead = projectOperations.project(project).getHead("master");
-
- // Create a stable branch and bootstrap it.
- gApi.projects().name(project.get()).branch("stable").create(new BranchInput());
- PushOneCommit push =
- pushFactory.create(user.newIdent(), testRepo, "initial commit", "a.txt", "a");
- PushOneCommit.Result change = push.to("refs/heads/stable");
-
- RevCommit stable = projectOperations.project(project).getHead("stable");
- RevCommit master = projectOperations.project(project).getHead("master");
-
- assertThat(master).isEqualTo(initialHead);
- assertThat(stable).isEqualTo(change.getCommit());
-
- testRepo.git().fetch().call();
- testRepo.git().branchCreate().setName("stable").setStartPoint(stable).call();
- testRepo.git().branchCreate().setName("master").setStartPoint(master).call();
-
- // Create a fix in stable branch.
- testRepo.reset(stable);
- RevCommit fix =
- testRepo
- .commit()
- .parent(stable)
- .message("small fix")
- .add("b.txt", "b")
- .insertChangeId()
- .create();
- testRepo.branch("refs/heads/stable").update(fix);
- testRepo
- .git()
- .push()
- .setRefSpecs(new RefSpec("refs/heads/stable:refs/for/stable%topic=" + name("topic")))
- .call();
-
- // Merge the fix into master.
- testRepo.reset(master);
- RevCommit merge =
- testRepo
- .commit()
- .parent(master)
- .parent(fix)
- .message("Merge stable into master")
- .insertChangeId()
- .create();
- testRepo.branch("refs/heads/master").update(merge);
- testRepo
- .git()
- .push()
- .setRefSpecs(new RefSpec("refs/heads/master:refs/for/master%topic=" + name("topic")))
- .call();
-
- // Submit together.
- String fixId = GitUtil.getChangeId(testRepo, fix).get();
- String mergeId = GitUtil.getChangeId(testRepo, merge).get();
- approve(fixId);
- approve(mergeId);
- submit(mergeId);
- assertMerged(fixId);
- assertMerged(mergeId);
- testRepo.git().fetch().call();
- RevWalk rw = testRepo.getRevWalk();
RevCommit newMaster = rw.parseCommit(projectOperations.project(project).getHead("master"));
assertThat(rw.isMergedInto(fix, newMaster)).isTrue();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java
index 4fbdab4..c34625e 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java
@@ -26,7 +26,6 @@
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestProjectInput;
-import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
import com.google.gerrit.entities.BranchNameKey;
@@ -38,7 +37,6 @@
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.server.change.MergeabilityComputationBehavior;
-import com.google.gerrit.server.experiments.ExperimentFeaturesConstants;
import com.google.gerrit.server.project.testing.TestLabels;
import com.google.inject.Inject;
import org.eclipse.jgit.lib.ObjectId;
@@ -173,68 +171,6 @@
@Test
public void submitMergeCommitThatDependsOnNormalChangeViaTheFirstParent() throws Throwable {
/*
- * merge created by Gerrit to integrate change 1 and change 2
- /|
- / |
- | |
- * | change3 (new tip)
- | |
- | * change2 (merge)
- | |\
- | | |
- | * | change1
- \|/
- * initialHead
- */
- RevCommit initialHead = projectOperations.project(project).getHead("master");
- PushOneCommit.Result change1 = createChange("Added a", "a.txt", "");
-
- PushOneCommit change2Push =
- pushFactory.create(admin.newIdent(), testRepo, "Merge to master", "m.txt", "");
- change2Push.setParents(ImmutableList.of(change1.getCommit(), initialHead));
- PushOneCommit.Result change2 = change2Push.to("refs/for/master");
-
- testRepo.reset(initialHead);
- PushOneCommit.Result change3 = createChange("New tip", "b.txt", "");
-
- approve(change3.getChangeId());
- submit(change3.getChangeId());
-
- approve(change1.getChangeId());
- approve(change2.getChangeId());
- submit(change2.getChangeId());
-
- RevCommit newHead = projectOperations.project(project).getHead("master");
- assertThat(newHead.getParentCount()).isEqualTo(2);
-
- RevCommit headParent1 = parse(newHead.getParent(0).getId());
- RevCommit headParent2 = parse(newHead.getParent(1).getId());
-
- if (getSubmitType() == SubmitType.REBASE_ALWAYS) {
- assertCurrentRevision(change3.getChangeId(), 2, headParent1.getId());
- } else {
- assertThat(change3.getCommit().getId()).isEqualTo(headParent1.getId());
- }
- assertThat(headParent1.getParentCount()).isEqualTo(1);
- assertThat(headParent1.getParent(0)).isEqualTo(initialHead);
-
- assertThat(headParent2.getId()).isEqualTo(change2.getCommit().getId());
- assertThat(headParent2.getParentCount()).isEqualTo(2);
-
- RevCommit headGrandparent1 = parse(headParent2.getParent(0).getId());
- RevCommit headGrandparent2 = parse(headParent2.getParent(1).getId());
-
- assertThat(headGrandparent1.getId()).isEqualTo(change1.getCommit().getId());
- assertThat(headGrandparent2.getId()).isEqualTo(initialHead.getId());
- }
-
- @Test
- @GerritConfig(
- name = "experiments.enabled",
- value = ExperimentFeaturesConstants.REBASE_MERGE_COMMITS)
- public void submitMergeCommitThatDependsOnNormalChangeViaTheFirstParent_withRebasingMergeCommits()
- throws Throwable {
- /*
* change2 (merge, rebased)
| \
* \ change1 (rebased)
@@ -290,66 +226,6 @@
@Test
public void submitMergeCommitThatDependsOnNormalChangeViaTheSecondParent() throws Throwable {
/*
- * merge created by Gerrit to integrate change 1 and change 2
- |\
- | * change2 (merge)
- | |\
- | | * change1
- | |/
- * | change3 (new tip)
- |/
- * initialHead
- */
- RevCommit initialHead = projectOperations.project(project).getHead("master");
- PushOneCommit.Result change1 = createChange("Added a", "a.txt", "");
-
- PushOneCommit change2Push =
- pushFactory.create(admin.newIdent(), testRepo, "Merge to master", "m.txt", "");
- change2Push.setParents(ImmutableList.of(initialHead, change1.getCommit()));
- PushOneCommit.Result change2 = change2Push.to("refs/for/master");
-
- testRepo.reset(initialHead);
- PushOneCommit.Result change3 = createChange("New tip", "b.txt", "");
-
- approve(change3.getChangeId());
- submit(change3.getChangeId());
-
- approve(change1.getChangeId());
- approve(change2.getChangeId());
- submit(change2.getChangeId());
-
- RevCommit newHead = projectOperations.project(project).getHead("master");
- assertThat(newHead.getParentCount()).isEqualTo(2);
-
- RevCommit headParent1 = parse(newHead.getParent(0).getId());
- RevCommit headParent2 = parse(newHead.getParent(1).getId());
-
- if (getSubmitType() == SubmitType.REBASE_ALWAYS) {
- assertCurrentRevision(change3.getChangeId(), 2, headParent1.getId());
- } else {
- assertThat(change3.getCommit().getId()).isEqualTo(headParent1.getId());
- }
- assertThat(headParent1.getParentCount()).isEqualTo(1);
- assertThat(headParent1.getParent(0)).isEqualTo(initialHead);
-
- assertThat(headParent2.getId()).isEqualTo(change2.getCommit().getId());
- assertThat(headParent2.getParentCount()).isEqualTo(2);
-
- RevCommit headGrandparent1 = parse(headParent2.getParent(0).getId());
- RevCommit headGrandparent2 = parse(headParent2.getParent(1).getId());
-
- assertThat(headGrandparent1.getId()).isEqualTo(initialHead.getId());
- assertThat(headGrandparent2.getId()).isEqualTo(change1.getCommit().getId());
- }
-
- @Test
- @GerritConfig(
- name = "experiments.enabled",
- value = ExperimentFeaturesConstants.REBASE_MERGE_COMMITS)
- public void
- submitMergeCommitThatDependsOnNormalChangeViaTheSecondParent_withRebasingMergeCommits()
- throws Throwable {
- /*
* change2 (merge, rebased)
| \
* \ change3 (new tip, rebased if 'Rebase Always')