Merge changes I7401c1bc,If420ca31,Ic328c4d6

* changes:
  Add a request listener that sets a logging tag with the project
  TraceIT: Add JavaDoc that explains how the tests are working
  Add extension points that allows to listen to incoming requests
diff --git a/Documentation/config-project-config.txt b/Documentation/config-project-config.txt
index 91a054a..08c26d4 100644
--- a/Documentation/config-project-config.txt
+++ b/Documentation/config-project-config.txt
@@ -157,32 +157,6 @@
 did  what, especially with patches. Default is `INHERIT`, which means that this
 property is inherited from the parent project.
 
-[[receive.requireChangeId]]receive.requireChangeId::
-+
-The `Require Change-Id in commit message` option defines whether a
-link:user-changeid.html[Change-Id] in the commit message is required
-for pushing a commit for review. If this option is set, trying to push
-a commit for review that doesn't contain a Change-Id in the commit
-message fails with link:error-missing-changeid.html[missing Change-Id
-in commit message footer].
-
-It is recommended to set this option and use a
-link:user-changeid.html#create[commit-msg hook] (or other client side
-tooling like EGit) to automatically generate Change-Id's for new
-commits. This way the Change-Id is automatically in place when changes
-are reworked or rebased and uploading new patch sets gets easy.
-
-If this option is not set, commits can be uploaded without a Change-Id,
-but then users have to remember to copy the assigned Change-Id from the
-change screen and insert it manually into the commit message when they
-want to upload a second patch set.
-
-Default is `INHERIT`, which means that this property is inherited from
-the parent project. The global default for new hosts is `true`
-
-This option is deprecated and future releases will behave as if this
-is always `true`.
-
 [[receive.maxObjectSizeLimit]]receive.maxObjectSizeLimit::
 +
 Maximum allowed Git object size that receive-pack will accept. If an object
@@ -321,7 +295,7 @@
 
 - 'action': defines the link:#submit-type[submit type].  Valid
 values are 'fast forward only', 'merge if necessary', 'rebase if necessary',
-'merge always' and 'cherry pick'.  The default is 'merge if necessary'.
+'rebase always', 'merge always' and 'cherry pick'.  The default is 'merge if necessary'.
 
 - 'matchAuthorToCommitterDate': Defines whether to the author date will be changed to match the
 submitter date upon submit, so that git log shows when the change was submitted instead of when the
@@ -494,8 +468,9 @@
 [[fast_forward_only]]
 * Fast Forward Only
 +
-With this method no merge commits are produced. All merges must
-be handled on the client, prior to uploading to Gerrit for review.
+With this method Gerrit does not create merge commits on submitting a
+change. Merge commits may still be submitted, but they must be created
+on the client prior to uploading to Gerrit for review.
 +
 To submit a change, the change must be a strict superset of the
 destination branch.  That is, the change must already contain the
@@ -545,7 +520,7 @@
 branch, then the branch is fast-forwarded to the change.  If not,
 then the change is automatically rebased and then the branch is
 fast-forwarded to the change.
-
++
 When Gerrit tries to do a merge, by default the merge will only
 succeed if there is no path conflict.  A path conflict occurs when
 the same file has also been changed on the other side of the merge.
@@ -557,7 +532,7 @@
 if fast forward is possible AND like Cherry Pick it ensures footers such as
 Change-Id, Reviewed-On, and others are present in resulting commit that is
 merged.
-
++
 Thus, Rebase Always can be considered similar to Cherry Pick, but with
 the important distinction that Rebase Always does not ignore dependencies.
 
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index f69c4ae..1544aae 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -824,11 +824,6 @@
       "configured_value": "INHERIT",
       "inherited_value": false
     },
-    "require_change_id": {
-      "value": false,
-      "configured_value": "FALSE",
-      "inherited_value": true
-    },
     "max_object_size_limit": {
       "value": "15m",
       "configured_value": "15m",
@@ -887,7 +882,6 @@
     "enable_signed_push": "INHERIT",
     "require_signed_push": "INHERIT",
     "reject_implicit_merges": "INHERIT",
-    "require_change_id": "TRUE",
     "max_object_size_limit": "10m",
     "submit_type": "REBASE_IF_NECESSARY",
     "state": "ACTIVE"
@@ -925,11 +919,6 @@
       "configured_value": "INHERIT",
       "inherited_value": false
     },
-    "require_change_id": {
-      "value": true,
-      "configured_value": "TRUE",
-      "inherited_value": true
-    },
     "enable_signed_push": {
       "value": true,
       "configured_value": "INHERIT",
@@ -3094,12 +3083,6 @@
 |`create_new_change_for_all_not_in_target` |optional|
 link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether
 a new change is created for every commit not in target branch.
-|`require_change_id`                       |optional|
-link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether a
-valid link:user-changeid.html[Change-Id] footer in any commit uploaded
-for review is required. This does not apply to commits pushed directly
-to a branch or tag. This property is deprecated and will be removed in
-a future release.
 |`enable_signed_push`|optional, not set if signed push is disabled|
 link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether
 signed push validation is enabled on the project.
@@ -3180,14 +3163,6 @@
 branch. +
 Can be `TRUE`, `FALSE` or `INHERIT`. +
 If not set, this setting is not updated.
-|`require_change_id`                       |optional|
-Whether a valid link:user-changeid.html[Change-Id] footer in any commit
-uploaded for review is required. This does not apply to commits pushed
-directly to a branch or tag. +
-Can be `TRUE`, `FALSE` or `INHERIT`. +
-If not set, this setting is not updated.
-This property is deprecated and will be removed in
-a future release.
 |`reject_implicit_merges`                  |optional|
 Whether a check for implicit merges will be performed when changes
 are pushed for review. +
@@ -3553,11 +3528,6 @@
 Whether content merge should be enabled for the project (`TRUE`,
 `FALSE`, `INHERIT`). +
 `FALSE`, if the `submit_type` is `FAST_FORWARD_ONLY`.
-|`require_change_id`                           |`INHERIT` if not set|
-Whether the usage of Change-Ids is required for the project (`TRUE`,
-`FALSE`, `INHERIT`).
-This property is deprecated and will be removed in
-a future release.
 |`enable_signed_push`                           |`INHERIT` if not set|
 Whether signed push validation is enabled on the project  (`TRUE`,
 `FALSE`, `INHERIT`).
diff --git a/WORKSPACE b/WORKSPACE
index fa72a35..ece7706 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -752,8 +752,8 @@
 # Keep this version of Soy synchronized with the version used in Gitiles.
 maven_jar(
     name = "soy",
-    artifact = "com.google.template:soy:2019-04-18",
-    sha1 = "5750208855562d74f29eee39ee497d5cf6df1490",
+    artifact = "com.google.template:soy:2019-07-14",
+    sha1 = "547dee679bac6011126f3a54619d3aec336216d0",
 )
 
 maven_jar(
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 197a6a3..8818ade 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -888,15 +888,6 @@
     }
   }
 
-  protected void setRequireChangeId(InheritableBoolean value) throws Exception {
-    try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
-      ProjectConfig config = projectConfigFactory.read(md);
-      config.getProject().setBooleanConfig(BooleanProjectConfig.REQUIRE_CHANGE_ID, value);
-      config.commit(md);
-      projectCache.evict(config.getProject());
-    }
-  }
-
   protected PushOneCommit.Result pushTo(String ref) throws Exception {
     PushOneCommit push = pushFactory.create(admin.newIdent(), testRepo);
     return push.to(ref);
diff --git a/java/com/google/gerrit/acceptance/TestProjectInput.java b/java/com/google/gerrit/acceptance/TestProjectInput.java
index 0a3686b..7deb88a 100644
--- a/java/com/google/gerrit/acceptance/TestProjectInput.java
+++ b/java/com/google/gerrit/acceptance/TestProjectInput.java
@@ -43,8 +43,6 @@
 
   InheritableBoolean useContentMerge() default InheritableBoolean.INHERIT;
 
-  InheritableBoolean requireChangeId() default InheritableBoolean.INHERIT;
-
   InheritableBoolean rejectEmptyCommit() default InheritableBoolean.INHERIT;
 
   InheritableBoolean enableSignedPush() default InheritableBoolean.INHERIT;
diff --git a/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java b/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java
index fb2a0fe..eddfb09 100644
--- a/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java
+++ b/java/com/google/gerrit/extensions/api/projects/ConfigInfo.java
@@ -29,7 +29,6 @@
   public InheritedBooleanInfo useContentMerge;
   public InheritedBooleanInfo useSignedOffBy;
   public InheritedBooleanInfo createNewChangeForAllNotInTarget;
-  public InheritedBooleanInfo requireChangeId;
   public InheritedBooleanInfo enableSignedPush;
   public InheritedBooleanInfo requireSignedPush;
   public InheritedBooleanInfo rejectImplicitMerges;
diff --git a/java/com/google/gerrit/extensions/api/projects/ConfigInput.java b/java/com/google/gerrit/extensions/api/projects/ConfigInput.java
index 1a6d77b..44a5258 100644
--- a/java/com/google/gerrit/extensions/api/projects/ConfigInput.java
+++ b/java/com/google/gerrit/extensions/api/projects/ConfigInput.java
@@ -25,7 +25,6 @@
   public InheritableBoolean useContentMerge;
   public InheritableBoolean useSignedOffBy;
   public InheritableBoolean createNewChangeForAllNotInTarget;
-  public InheritableBoolean requireChangeId;
   public InheritableBoolean enableSignedPush;
   public InheritableBoolean requireSignedPush;
   public InheritableBoolean rejectImplicitMerges;
diff --git a/java/com/google/gerrit/extensions/api/projects/ProjectInput.java b/java/com/google/gerrit/extensions/api/projects/ProjectInput.java
index e61d316..2dec2b9 100644
--- a/java/com/google/gerrit/extensions/api/projects/ProjectInput.java
+++ b/java/com/google/gerrit/extensions/api/projects/ProjectInput.java
@@ -31,7 +31,6 @@
   public InheritableBoolean useContributorAgreements;
   public InheritableBoolean useSignedOffBy;
   public InheritableBoolean useContentMerge;
-  public InheritableBoolean requireChangeId;
   public InheritableBoolean createNewChangeForAllNotInTarget;
   public InheritableBoolean rejectEmptyCommit;
   public InheritableBoolean enableSignedPush;
diff --git a/java/com/google/gerrit/httpd/raw/IndexServlet.java b/java/com/google/gerrit/httpd/raw/IndexServlet.java
index 4c9fc3b..a0b41b21 100644
--- a/java/com/google/gerrit/httpd/raw/IndexServlet.java
+++ b/java/com/google/gerrit/httpd/raw/IndexServlet.java
@@ -74,11 +74,7 @@
       ImmutableMap<String, Object> templateData =
           IndexHtmlUtil.templateData(
               gerritApi, canonicalUrl, cdnPath, faviconPath, parameterMap, urlOrdainer);
-      renderer =
-          soySauce
-              .renderTemplate("com.google.gerrit.httpd.raw.Index")
-              .setExpectedContentKind(SanitizedContent.ContentKind.HTML)
-              .setData(templateData);
+      renderer = soySauce.renderTemplate("com.google.gerrit.httpd.raw.Index").setData(templateData);
     } catch (URISyntaxException | RestApiException e) {
       throw new IOException(e);
     }
@@ -87,7 +83,7 @@
     rsp.setContentType("text/html");
     rsp.setStatus(SC_OK);
     try (OutputStream w = rsp.getOutputStream()) {
-      w.write(renderer.render().get().getBytes(UTF_8));
+      w.write(renderer.renderHtml().get().toString().getBytes(UTF_8));
     }
   }
 }
diff --git a/java/com/google/gerrit/reviewdb/client/BooleanProjectConfig.java b/java/com/google/gerrit/reviewdb/client/BooleanProjectConfig.java
index a70d254..bea5abe 100644
--- a/java/com/google/gerrit/reviewdb/client/BooleanProjectConfig.java
+++ b/java/com/google/gerrit/reviewdb/client/BooleanProjectConfig.java
@@ -32,7 +32,6 @@
   USE_CONTRIBUTOR_AGREEMENTS("receive", "requireContributorAgreement"),
   USE_SIGNED_OFF_BY("receive", "requireSignedOffBy"),
   USE_CONTENT_MERGE("submit", "mergeContent"),
-  REQUIRE_CHANGE_ID("receive", "requireChangeId"),
   CREATE_NEW_CHANGE_FOR_ALL_NOT_IN_TARGET("receive", "createNewChangeForAllNotInTarget"),
   ENABLE_SIGNED_PUSH("receive", "enableSignedPush"),
   REQUIRE_SIGNED_PUSH("receive", "requireSignedPush"),
diff --git a/java/com/google/gerrit/server/ApprovalCopier.java b/java/com/google/gerrit/server/ApprovalCopier.java
index 979cc11..85a6079 100644
--- a/java/com/google/gerrit/server/ApprovalCopier.java
+++ b/java/com/google/gerrit/server/ApprovalCopier.java
@@ -73,49 +73,27 @@
 
   Iterable<PatchSetApproval> getForPatchSet(
       ChangeNotes notes, PatchSet.Id psId, @Nullable RevWalk rw, @Nullable Config repoConfig) {
-    return getForPatchSet(notes, psId, rw, repoConfig, Collections.emptyList());
-  }
 
-  Iterable<PatchSetApproval> getForPatchSet(
-      ChangeNotes notes,
-      PatchSet.Id psId,
-      @Nullable RevWalk rw,
-      @Nullable Config repoConfig,
-      Iterable<PatchSetApproval> dontCopy) {
     PatchSet ps = psUtil.get(notes, psId);
     if (ps == null) {
       return Collections.emptyList();
     }
-    return getForPatchSet(notes, ps, rw, repoConfig, dontCopy);
-  }
 
-  private Iterable<PatchSetApproval> getForPatchSet(
-      ChangeNotes notes,
-      PatchSet ps,
-      @Nullable RevWalk rw,
-      @Nullable Config repoConfig,
-      Iterable<PatchSetApproval> dontCopy) {
-    requireNonNull(ps, "ps should not be null");
     ChangeData cd = changeDataFactory.create(notes);
     try {
       ProjectState project = projectCache.checkedGet(cd.change().getDest().project());
       ListMultimap<PatchSet.Id, PatchSetApproval> all = cd.approvals();
       requireNonNull(all, "all should not be null");
 
-      Table<String, Account.Id, PatchSetApproval> wontCopy = HashBasedTable.create();
-      for (PatchSetApproval psa : dontCopy) {
-        wontCopy.put(psa.label(), psa.accountId(), psa);
-      }
-
       Table<String, Account.Id, PatchSetApproval> byUser = HashBasedTable.create();
       for (PatchSetApproval psa : all.get(ps.id())) {
-        if (!wontCopy.contains(psa.label(), psa.accountId())) {
-          byUser.put(psa.label(), psa.accountId(), psa);
-        }
+        byUser.put(psa.label(), psa.accountId(), psa);
       }
 
       TreeMap<Integer, PatchSet> patchSets = getPatchSets(cd);
 
+      Table<String, Account.Id, PatchSetApproval> wontCopy = HashBasedTable.create();
+
       // Walk patch sets strictly less than current in descending order.
       Collection<PatchSet> allPrior =
           patchSets.descendingMap().tailMap(ps.id().get(), false).values();
diff --git a/java/com/google/gerrit/server/DynamicOptions.java b/java/com/google/gerrit/server/DynamicOptions.java
index 90bb50b..44d3493 100644
--- a/java/com/google/gerrit/server/DynamicOptions.java
+++ b/java/com/google/gerrit/server/DynamicOptions.java
@@ -14,12 +14,9 @@
 
 package com.google.gerrit.server;
 
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.common.Nullable;
 import com.google.gerrit.extensions.registration.DynamicMap;
 import com.google.gerrit.server.plugins.DelegatingClassLoader;
 import com.google.gerrit.util.cli.CmdLineParser;
-import com.google.gerrit.util.cli.UnknownOptionHandler;
 import com.google.inject.Injector;
 import com.google.inject.Module;
 import com.google.inject.Provider;
@@ -33,8 +30,6 @@
 
 /** Helper class to define and parse options from plugins on ssh and RestAPI commands. */
 public class DynamicOptions {
-  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
   /**
    * To provide additional options, bind a DynamicBean. For example:
    *
@@ -156,7 +151,7 @@
    * }
    * </pre>
    */
-  public interface BeanReceiver extends UnknownOptionHandler {
+  public interface BeanReceiver {
     void setDynamicBean(String plugin, DynamicBean dynamicBean);
 
     /**
@@ -169,17 +164,6 @@
     default Class<? extends BeanReceiver> getExportedBeanReceiver() {
       return getClass();
     }
-
-    @Override
-    default boolean accept(String name, @Nullable String value) {
-      // Ignore unknown plugin options, so that callers who set a plugin option do not fail if the
-      // plugin is disabled.
-      boolean isPluginOption = UnknownOptionHandler.isPluginOption(name);
-      if (isPluginOption) {
-        logger.atFine().log("Unknown plugin option %s is ignored.", name);
-      }
-      return isPluginOption;
-    }
   }
 
   public interface BeanProvider {
diff --git a/java/com/google/gerrit/server/git/validators/CommitValidators.java b/java/com/google/gerrit/server/git/validators/CommitValidators.java
index a9a1a5d..da051dd 100644
--- a/java/com/google/gerrit/server/git/validators/CommitValidators.java
+++ b/java/com/google/gerrit/server/git/validators/CommitValidators.java
@@ -307,10 +307,8 @@
                   Type.ERROR));
           throw new CommitValidationException(CHANGE_ID_ABOVE_FOOTER_MSG, messages);
         }
-        if (projectState.is(BooleanProjectConfig.REQUIRE_CHANGE_ID)) {
-          messages.add(getMissingChangeIdErrorMsg(MISSING_CHANGE_ID_MSG));
-          throw new CommitValidationException(MISSING_CHANGE_ID_MSG, messages);
-        }
+        messages.add(getMissingChangeIdErrorMsg(MISSING_CHANGE_ID_MSG));
+        throw new CommitValidationException(MISSING_CHANGE_ID_MSG, messages);
       } else if (idList.size() > 1) {
         throw new CommitValidationException(MULTIPLE_CHANGE_ID_MSG, messages);
       } else {
diff --git a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
index 4313473..e56a38f 100644
--- a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
+++ b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
@@ -34,7 +34,7 @@
 import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.validators.OutgoingEmailValidationListener;
 import com.google.gerrit.server.validators.ValidationException;
-import com.google.template.soy.data.SanitizedContent;
+import com.google.template.soy.jbcsrc.api.SoySauce;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
@@ -54,6 +54,7 @@
 
 /** Sends an email to one or more interested parties. */
 public abstract class OutgoingEmail {
+  private static final String SOY_TEMPLATE_NAMESPACE = "com.google.gerrit.server.mail.template.";
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
   protected String messageClass;
@@ -536,21 +537,19 @@
     return args.instanceNameProvider.get();
   }
 
-  private String soyTemplate(String name, SanitizedContent.ContentKind kind) {
-    return args.soySauce
-        .renderTemplate("com.google.gerrit.server.mail.template." + name)
-        .setExpectedContentKind(kind)
-        .setData(soyContext)
-        .render()
-        .get();
-  }
-
+  /** Renders a soy template of kind="text". */
   protected String textTemplate(String name) {
-    return soyTemplate(name, SanitizedContent.ContentKind.TEXT);
+    return configureRenderer(name).renderText().get();
   }
 
+  /** Renders a soy template of kind="html". */
   protected String soyHtmlTemplate(String name) {
-    return soyTemplate(name, SanitizedContent.ContentKind.HTML);
+    return configureRenderer(name).renderHtml().get().toString();
+  }
+
+  /** Configures a soy renderer for the given template name and rendering data map. */
+  private SoySauce.Renderer configureRenderer(String templateName) {
+    return args.soySauce.renderTemplate(SOY_TEMPLATE_NAMESPACE + templateName).setData(soyContext);
   }
 
   protected void removeUser(Account user) {
diff --git a/java/com/google/gerrit/server/permissions/DefaultRefFilter.java b/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
index 5c17be8..858edf2 100644
--- a/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
+++ b/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
@@ -208,7 +208,7 @@
     logger.atFinest().log("Filter refs (refs = %s)", refs);
 
     if (projectState.isAllUsers()) {
-      refs = addUsersSelfSymref(refs);
+      refs = addUsersSelfSymref(repo, refs);
     }
 
     // TODO(hiesel): Remove when optimization is done.
@@ -397,19 +397,24 @@
     return refs;
   }
 
-  private Map<String, Ref> addUsersSelfSymref(Map<String, Ref> refs) {
+  private Map<String, Ref> addUsersSelfSymref(Repository repo, Map<String, Ref> refs)
+      throws PermissionBackendException {
     if (user.isIdentifiedUser()) {
       String refName = RefNames.refsUsers(user.getAccountId());
-      Ref r = refs.get(refName);
-      if (r == null) {
-        logger.atWarning().log("User ref %s not found", refName);
-        return refs;
-      }
+      try {
+        Ref r = repo.exactRef(refName);
+        if (r == null) {
+          logger.atWarning().log("User ref %s not found", refName);
+          return refs;
+        }
 
-      SymbolicRef s = new SymbolicRef(REFS_USERS_SELF, r);
-      refs = new HashMap<>(refs);
-      refs.put(s.getName(), s);
-      logger.atFinest().log("Added %s as alias for user ref %s", REFS_USERS_SELF, refName);
+        SymbolicRef s = new SymbolicRef(REFS_USERS_SELF, r);
+        refs = new HashMap<>(refs);
+        refs.put(s.getName(), s);
+        logger.atFinest().log("Added %s as alias for user ref %s", REFS_USERS_SELF, refName);
+      } catch (IOException e) {
+        throw new PermissionBackendException(e);
+      }
     }
     return refs;
   }
diff --git a/java/com/google/gerrit/server/project/BooleanProjectConfigTransformations.java b/java/com/google/gerrit/server/project/BooleanProjectConfigTransformations.java
index 79eccbb..1328f6b 100644
--- a/java/com/google/gerrit/server/project/BooleanProjectConfigTransformations.java
+++ b/java/com/google/gerrit/server/project/BooleanProjectConfigTransformations.java
@@ -39,9 +39,6 @@
               BooleanProjectConfig.USE_CONTENT_MERGE,
               new Mapper(i -> i.useContentMerge, (i, v) -> i.useContentMerge = v))
           .put(
-              BooleanProjectConfig.REQUIRE_CHANGE_ID,
-              new Mapper(i -> i.requireChangeId, (i, v) -> i.requireChangeId = v))
-          .put(
               BooleanProjectConfig.CREATE_NEW_CHANGE_FOR_ALL_NOT_IN_TARGET,
               new Mapper(
                   i -> i.createNewChangeForAllNotInTarget,
diff --git a/java/com/google/gerrit/server/project/CreateProjectArgs.java b/java/com/google/gerrit/server/project/CreateProjectArgs.java
index 7405df1..9ae3b2c 100644
--- a/java/com/google/gerrit/server/project/CreateProjectArgs.java
+++ b/java/com/google/gerrit/server/project/CreateProjectArgs.java
@@ -33,7 +33,6 @@
   public List<String> branch;
   public InheritableBoolean contentMerge;
   public InheritableBoolean newChangeForAllNotInTarget;
-  public InheritableBoolean changeIdRequired;
   public InheritableBoolean rejectEmptyCommit;
   public InheritableBoolean enableSignedPush;
   public InheritableBoolean requireSignedPush;
@@ -44,7 +43,6 @@
     contributorAgreements = InheritableBoolean.INHERIT;
     signedOffBy = InheritableBoolean.INHERIT;
     contentMerge = InheritableBoolean.INHERIT;
-    changeIdRequired = InheritableBoolean.INHERIT;
     newChangeForAllNotInTarget = InheritableBoolean.INHERIT;
     enableSignedPush = InheritableBoolean.INHERIT;
     requireSignedPush = InheritableBoolean.INHERIT;
diff --git a/java/com/google/gerrit/server/project/ProjectCreator.java b/java/com/google/gerrit/server/project/ProjectCreator.java
index b50b046..d468b44 100644
--- a/java/com/google/gerrit/server/project/ProjectCreator.java
+++ b/java/com/google/gerrit/server/project/ProjectCreator.java
@@ -152,7 +152,6 @@
       newProject.setBooleanConfig(
           BooleanProjectConfig.CREATE_NEW_CHANGE_FOR_ALL_NOT_IN_TARGET,
           args.newChangeForAllNotInTarget);
-      newProject.setBooleanConfig(BooleanProjectConfig.REQUIRE_CHANGE_ID, args.changeIdRequired);
       newProject.setBooleanConfig(BooleanProjectConfig.REJECT_EMPTY_COMMIT, args.rejectEmptyCommit);
       newProject.setMaxObjectSizeLimit(args.maxObjectSizeLimit);
       newProject.setBooleanConfig(BooleanProjectConfig.ENABLE_SIGNED_PUSH, args.enableSignedPush);
diff --git a/java/com/google/gerrit/server/restapi/account/GetCapabilities.java b/java/com/google/gerrit/server/restapi/account/GetCapabilities.java
index 77f1668..9e2f1cf 100644
--- a/java/com/google/gerrit/server/restapi/account/GetCapabilities.java
+++ b/java/com/google/gerrit/server/restapi/account/GetCapabilities.java
@@ -30,7 +30,6 @@
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.RestReadView;
-import com.google.gerrit.json.OutputFormat;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.OptionUtil;
 import com.google.gerrit.server.account.AccountLimits;
@@ -40,7 +39,6 @@
 import com.google.gerrit.server.permissions.GlobalPermission;
 import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gson.reflect.TypeToken;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
@@ -79,7 +77,7 @@
   }
 
   @Override
-  public Object apply(AccountResource resource)
+  public Map<String, Object> apply(AccountResource resource)
       throws RestApiException, PermissionBackendException {
     permissionBackend.checkUsesDefaultCapabilities();
     PermissionBackend.WithUser perm = permissionBackend.currentUser();
@@ -97,9 +95,7 @@
     addRanges(have, limits);
     addPriority(have, limits);
 
-    return OutputFormat.JSON
-        .newGson()
-        .toJsonTree(have, new TypeToken<Map<String, Object>>() {}.getType());
+    return have;
   }
 
   private Set<GlobalOrPluginPermission> permissionsToTest() {
diff --git a/java/com/google/gerrit/server/restapi/change/PutMessage.java b/java/com/google/gerrit/server/restapi/change/PutMessage.java
index db02418..5c36e60 100644
--- a/java/com/google/gerrit/server/restapi/change/PutMessage.java
+++ b/java/com/google/gerrit/server/restapi/change/PutMessage.java
@@ -22,7 +22,6 @@
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.reviewdb.client.BooleanProjectConfig;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.CurrentUser;
@@ -111,10 +110,7 @@
     String sanitizedCommitMessage = CommitMessageUtil.checkAndSanitizeCommitMessage(input.message);
 
     ensureCanEditCommitMessage(resource.getNotes());
-    ensureChangeIdIsCorrect(
-        projectCache.checkedGet(resource.getProject()).is(BooleanProjectConfig.REQUIRE_CHANGE_ID),
-        resource.getChange().getKey().get(),
-        sanitizedCommitMessage);
+    ensureChangeIdIsCorrect(resource.getChange().getKey().get(), sanitizedCommitMessage);
 
     try (Repository repository = repositoryManager.openRepository(resource.getProject());
         RevWalk revWalk = new RevWalk(repository);
@@ -193,8 +189,7 @@
     }
   }
 
-  private static void ensureChangeIdIsCorrect(
-      boolean requireChangeId, String currentChangeId, String newCommitMessage)
+  private static void ensureChangeIdIsCorrect(String currentChangeId, String newCommitMessage)
       throws ResourceConflictException, BadRequestException {
     RevCommit revCommit =
         RevCommit.parse(
@@ -204,7 +199,7 @@
     CommitMessageUtil.checkAndSanitizeCommitMessage(revCommit.getShortMessage());
 
     List<String> changeIdFooters = revCommit.getFooterLines(FooterConstants.CHANGE_ID);
-    if (requireChangeId && changeIdFooters.isEmpty()) {
+    if (changeIdFooters.isEmpty()) {
       throw new ResourceConflictException("missing Change-Id footer");
     }
     if (!changeIdFooters.isEmpty() && !changeIdFooters.get(0).equals(currentChangeId)) {
diff --git a/java/com/google/gerrit/server/restapi/project/CreateProject.java b/java/com/google/gerrit/server/restapi/project/CreateProject.java
index 6844cac..6428435 100644
--- a/java/com/google/gerrit/server/restapi/project/CreateProject.java
+++ b/java/com/google/gerrit/server/restapi/project/CreateProject.java
@@ -147,8 +147,6 @@
     args.newChangeForAllNotInTarget =
         MoreObjects.firstNonNull(
             input.createNewChangeForAllNotInTarget, InheritableBoolean.INHERIT);
-    args.changeIdRequired =
-        MoreObjects.firstNonNull(input.requireChangeId, InheritableBoolean.INHERIT);
     args.rejectEmptyCommit =
         MoreObjects.firstNonNull(input.rejectEmptyCommit, InheritableBoolean.INHERIT);
     args.enableSignedPush =
diff --git a/java/com/google/gerrit/server/schema/AllProjectsInput.java b/java/com/google/gerrit/server/schema/AllProjectsInput.java
index 7231b18..f72bf4d 100644
--- a/java/com/google/gerrit/server/schema/AllProjectsInput.java
+++ b/java/com/google/gerrit/server/schema/AllProjectsInput.java
@@ -33,8 +33,6 @@
   public static final ImmutableMap<BooleanProjectConfig, InheritableBoolean>
       DEFAULT_BOOLEAN_PROJECT_CONFIGS =
           ImmutableMap.of(
-              BooleanProjectConfig.REQUIRE_CHANGE_ID,
-              InheritableBoolean.TRUE,
               BooleanProjectConfig.USE_CONTENT_MERGE,
               InheritableBoolean.TRUE,
               BooleanProjectConfig.USE_CONTRIBUTOR_AGREEMENTS,
diff --git a/java/com/google/gerrit/server/schema/testing/AllProjectsCreatorTestUtil.java b/java/com/google/gerrit/server/schema/testing/AllProjectsCreatorTestUtil.java
index be56782..6c49b22 100644
--- a/java/com/google/gerrit/server/schema/testing/AllProjectsCreatorTestUtil.java
+++ b/java/com/google/gerrit/server/schema/testing/AllProjectsCreatorTestUtil.java
@@ -40,7 +40,6 @@
           "[receive]",
           "  requireContributorAgreement = false",
           "  requireSignedOffBy = false",
-          "  requireChangeId = true",
           "  enableSignedPush = false");
   private static final ImmutableList<String> DEFAULT_ALL_PROJECTS_SUBMIT_SECTION =
       ImmutableList.of("[submit]", "  mergeContent = true");
diff --git a/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java b/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java
index df86d63..56e72e6 100644
--- a/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java
+++ b/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java
@@ -91,9 +91,6 @@
   @Option(name = "--content-merge", usage = "allow automatic conflict resolving within files")
   private InheritableBoolean contentMerge = InheritableBoolean.INHERIT;
 
-  @Option(name = "--change-id", usage = "if change-id is required")
-  private InheritableBoolean requireChangeID = InheritableBoolean.INHERIT;
-
   @Option(name = "--reject-empty-commit", usage = "if empty commits should be rejected on submit")
   private InheritableBoolean rejectEmptyCommit = InheritableBoolean.INHERIT;
 
@@ -124,14 +121,6 @@
   }
 
   @Option(
-      name = "--require-change-id",
-      aliases = {"--id"},
-      usage = "if change-id is required")
-  void setRequireChangeId(@SuppressWarnings("unused") boolean on) {
-    requireChangeID = InheritableBoolean.TRUE;
-  }
-
-  @Option(
       name = "--create-new-change-for-all-not-in-target",
       aliases = {"--ncfa"},
       usage = "if a new change will be created for every commit not in target branch")
@@ -186,7 +175,6 @@
         input.useContributorAgreements = contributorAgreements;
         input.useSignedOffBy = signedOffBy;
         input.useContentMerge = contentMerge;
-        input.requireChangeId = requireChangeID;
         input.createNewChangeForAllNotInTarget = createNewChangeForAllNotInTarget;
         input.branches = branch;
         input.createEmptyCommit = createEmptyCommit;
diff --git a/java/com/google/gerrit/sshd/commands/SetProjectCommand.java b/java/com/google/gerrit/sshd/commands/SetProjectCommand.java
index 8c9fc9f..f145b9e 100644
--- a/java/com/google/gerrit/sshd/commands/SetProjectCommand.java
+++ b/java/com/google/gerrit/sshd/commands/SetProjectCommand.java
@@ -56,9 +56,6 @@
   @Option(name = "--content-merge", usage = "allow automatic conflict resolving within files")
   private InheritableBoolean contentMerge;
 
-  @Option(name = "--change-id", usage = "if change-id is required")
-  private InheritableBoolean requireChangeID;
-
   @Option(
       name = "--use-contributor-agreements",
       aliases = {"--ca"},
@@ -104,22 +101,6 @@
   }
 
   @Option(
-      name = "--require-change-id",
-      aliases = {"--id"},
-      usage = "if change-id is required")
-  void setRequireChangeId(@SuppressWarnings("unused") boolean on) {
-    requireChangeID = InheritableBoolean.TRUE;
-  }
-
-  @Option(
-      name = "--no-change-id",
-      aliases = {"--nid"},
-      usage = "if change-id is not required")
-  void setNoChangeId(@SuppressWarnings("unused") boolean on) {
-    requireChangeID = InheritableBoolean.FALSE;
-  }
-
-  @Option(
       name = "--project-state",
       aliases = {"--ps"},
       usage = "project's visibility state")
@@ -133,7 +114,6 @@
   @Override
   protected void run() throws Failure {
     ConfigInput configInput = new ConfigInput();
-    configInput.requireChangeId = requireChangeID;
     configInput.submitType = submitType;
     configInput.useContentMerge = contentMerge;
     configInput.useContributorAgreements = contributorAgreements;
diff --git a/java/com/google/gerrit/util/cli/CmdLineParser.java b/java/com/google/gerrit/util/cli/CmdLineParser.java
index be043fd..1c430fc 100644
--- a/java/com/google/gerrit/util/cli/CmdLineParser.java
+++ b/java/com/google/gerrit/util/cli/CmdLineParser.java
@@ -41,7 +41,6 @@
 import com.google.common.base.Strings;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Lists;
-import com.google.common.collect.MultimapBuilder;
 import com.google.common.flogger.FluentLogger;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
@@ -313,44 +312,28 @@
     parser.parseArgument(tmp.toArray(new String[tmp.size()]));
   }
 
-  public void parseOptionMap(Map<String, String[]> parameters) throws CmdLineException {
-    ListMultimap<String, String> map = MultimapBuilder.hashKeys().arrayListValues().build();
-    for (Map.Entry<String, String[]> ent : parameters.entrySet()) {
-      for (String val : ent.getValue()) {
-        map.put(ent.getKey(), val);
-      }
-    }
-    parseOptionMap(map);
-  }
-
   public void parseOptionMap(ListMultimap<String, String> params) throws CmdLineException {
     logger.atFinest().log("Command-line parameters: %s", params.keySet());
-    List<String> knownArgs = Lists.newArrayListWithCapacity(2 * params.size());
+    List<String> tmp = Lists.newArrayListWithCapacity(2 * params.size());
     for (String key : params.keySet()) {
       String name = makeOption(key);
 
-      if (isKnownOption(name)) {
-        if (isBooleanOption(name)) {
-          boolean on = false;
-          for (String value : params.get(key)) {
-            on = toBoolean(key, value);
-          }
-          if (on) {
-            knownArgs.add(name);
-          }
-        } else {
-          for (String value : params.get(key)) {
-            knownArgs.add(name);
-            knownArgs.add(value);
-          }
+      if (isBooleanOption(name)) {
+        boolean on = false;
+        for (String value : params.get(key)) {
+          on = toBoolean(key, value);
+        }
+        if (on) {
+          tmp.add(name);
         }
       } else {
         for (String value : params.get(key)) {
-          parser.handleUnknownOption(name, value);
+          tmp.add(name);
+          tmp.add(value);
         }
       }
     }
-    parser.parseArgument(knownArgs.toArray(new String[knownArgs.size()]));
+    parser.parseArgument(tmp.toArray(new String[tmp.size()]));
   }
 
   public void parseWithPrefix(String prefix, Object bean) {
@@ -376,10 +359,6 @@
     return name;
   }
 
-  private boolean isKnownOption(String name) {
-    return findHandler(name) != null;
-  }
-
   @SuppressWarnings("rawtypes")
   private OptionHandler findHandler(String name) {
     if (options == null) {
@@ -447,8 +426,6 @@
   }
 
   public class MyParser extends org.kohsuke.args4j.CmdLineParser {
-    private final Object bean;
-
     boolean help;
 
     @SuppressWarnings("rawtypes")
@@ -476,22 +453,11 @@
 
     MyParser(Object bean) {
       super(bean, ParserProperties.defaults().withAtSyntax(false));
-      this.bean = bean;
       parseAdditionalOptions(bean, new HashSet<>());
       addOptionsWithMetRequirements();
       ensureOptionsInitialized();
     }
 
-    public void handleUnknownOption(String name, String value) throws CmdLineException {
-      if (bean instanceof UnknownOptionHandler
-          && ((UnknownOptionHandler) bean).accept(name, Strings.emptyToNull(value))) {
-        return;
-      }
-
-      // Parse argument to trigger a CmdLineException for the unknown option.
-      parseArgument(name, value);
-    }
-
     public int addOptionsWithMetRequirements() {
       int count = 0;
       for (Iterator<Map.Entry<String, QueuedOption>> it = queuedOptionsByName.entrySet().iterator();
diff --git a/java/com/google/gerrit/util/cli/UnknownOptionHandler.java b/java/com/google/gerrit/util/cli/UnknownOptionHandler.java
deleted file mode 100644
index 8d47765..0000000
--- a/java/com/google/gerrit/util/cli/UnknownOptionHandler.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (C) 2019 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.util.cli;
-
-import com.google.gerrit.common.Nullable;
-
-/**
- * Classes that define command-line options by using the {@link org.kohsuke.args4j.Option}
- * annotation can implement this class to accept and handle unknown options.
- *
- * <p>If a user specifies an unknown option and this unknown option doesn't get accepted, the
- * parsing of the command-line options fails and the user gets an error (this is the default
- * behavior if classes do not implement this interface).
- */
-public interface UnknownOptionHandler {
-  /**
-   * Checks whether the given option name matches the naming pattern of options that are defined by
-   * plugins that were defined by registering a {@link
-   * com.google.gerrit.server.DynamicOptions.DynamicBean}.
-   *
-   * @param optionName name of the option
-   * @return {@code true} if it's a plugin option, otherwise {@code false}
-   */
-  public static boolean isPluginOption(String optionName) {
-    // Options from plugins have the following name pattern: '--<plugin-name>--<option-name>'
-    if (optionName.startsWith("--")) {
-      optionName = optionName.substring(2);
-    }
-    return optionName.contains("--");
-  }
-
-  /**
-   * Whether an unknown option should be accepted.
-   *
-   * <p>If an unknown option is not accepted, the parsing of the command-line options fails and the
-   * user gets an error.
-   *
-   * <p>This method can be used to ignore unknown options (without failure for the user) or to
-   * handle them.
-   *
-   * @param name the name of an unknown option that was provided by the user
-   * @param value the value of the unknown option that was provided by the user
-   * @return whether this unknown options is accepted
-   */
-  boolean accept(String name, @Nullable String value);
-}
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 228f233..5b6acfe 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -131,6 +131,8 @@
 import com.google.gerrit.server.index.account.AccountIndexer;
 import com.google.gerrit.server.index.account.StalenessChecker;
 import com.google.gerrit.server.notedb.Sequences;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
 import com.google.gerrit.server.project.ProjectConfig;
 import com.google.gerrit.server.project.RefPattern;
 import com.google.gerrit.server.query.account.InternalAccountQuery;
@@ -217,6 +219,7 @@
   @Inject private Sequences seq;
   @Inject private StalenessChecker stalenessChecker;
   @Inject private VersionedAuthorizedKeys.Accessor authorizedKeys;
+  @Inject private PermissionBackend permissionBackend;
 
   @Inject protected Emails emails;
 
@@ -1371,6 +1374,19 @@
   }
 
   @Test
+  public void refsUsersSelfIsAdvertised() throws Exception {
+    try (Repository allUsersRepo = repoManager.openRepository(allUsers)) {
+      assertThat(
+              permissionBackend
+                  .currentUser()
+                  .project(allUsers)
+                  .filter(ImmutableList.of(), allUsersRepo, RefFilterOptions.defaults())
+                  .keySet())
+          .containsExactly(RefNames.REFS_USERS_SELF);
+    }
+  }
+
+  @Test
   public void pushToUserBranch() throws Exception {
     TestRepository<InMemoryRepository> allUsersRepo = cloneProject(allUsers);
     fetch(allUsersRepo, RefNames.refsUsers(admin.id()) + ":userRef");
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index c9c139e..118a9ae 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -3777,24 +3777,6 @@
   }
 
   @Test
-  public void changeCommitMessageWithNoChangeIdSucceedsIfChangeIdNotRequired() throws Exception {
-    ConfigInput configInput = new ConfigInput();
-    configInput.requireChangeId = InheritableBoolean.FALSE;
-    gApi.projects().name(project.get()).config(configInput);
-
-    PushOneCommit.Result r = createChange();
-    r.assertOkStatus();
-    assertThat(getCommitMessage(r.getChangeId()))
-        .isEqualTo("test commit\n\nChange-Id: " + r.getChangeId() + "\n");
-
-    String newMessage = "modified commit\n";
-    gApi.changes().id(r.getChangeId()).setMessage(newMessage);
-    RevisionApi rApi = gApi.changes().id(r.getChangeId()).current();
-    assertThat(rApi.files().keySet()).containsExactly("/COMMIT_MSG", "a.txt");
-    assertThat(getCommitMessage(r.getChangeId())).isEqualTo(newMessage);
-  }
-
-  @Test
   public void changeCommitMessageWithNoChangeIdFails() throws Exception {
     PushOneCommit.Result r = createChange();
     assertThat(getCommitMessage(r.getChangeId()))
diff --git a/javatests/com/google/gerrit/acceptance/api/project/CheckProjectIT.java b/javatests/com/google/gerrit/acceptance/api/project/CheckProjectIT.java
index 96ba722..05295ae 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/CheckProjectIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/CheckProjectIT.java
@@ -27,7 +27,6 @@
 import com.google.gerrit.extensions.api.projects.CheckProjectInput.AutoCloseableChangesCheckInput;
 import com.google.gerrit.extensions.api.projects.CheckProjectResultInfo;
 import com.google.gerrit.extensions.client.ChangeStatus;
-import com.google.gerrit.extensions.client.InheritableBoolean;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
@@ -66,7 +65,7 @@
 
   @Test
   public void detectAutoCloseableChangeByCommit() throws Exception {
-    RevCommit commit = pushCommitWithoutChangeIdForReview();
+    RevCommit commit = pushCommitForReview();
     ChangeInfo change =
         Iterables.getOnlyElement(gApi.changes().query("commit:" + commit.name()).get());
 
@@ -90,7 +89,7 @@
 
   @Test
   public void fixAutoCloseableChangeByCommit() throws Exception {
-    RevCommit commit = pushCommitWithoutChangeIdForReview();
+    RevCommit commit = pushCommitForReview();
     ChangeInfo change =
         Iterables.getOnlyElement(gApi.changes().query("commit:" + commit.name()).get());
 
@@ -280,17 +279,18 @@
                 + ProjectsConsistencyChecker.AUTO_CLOSE_MAX_COMMITS_LIMIT);
   }
 
-  private RevCommit pushCommitWithoutChangeIdForReview() throws Exception {
-    setRequireChangeId(InheritableBoolean.FALSE);
+  private RevCommit pushCommitForReview() throws Exception {
     RevCommit commit =
         testRepo
             .branch("HEAD")
             .commit()
             .message("A change")
+            .insertChangeId()
             .author(admin.newIdent())
             .committer(new PersonIdent(admin.newIdent(), testRepo.getDate()))
             .create();
     pushHead(testRepo, "refs/for/master");
+
     return commit;
   }
 
diff --git a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
index a9c7d99..da0cd43 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/ProjectIT.java
@@ -316,7 +316,6 @@
     assertThat(info.useSignedOffBy.configuredValue).isEqualTo(input.useSignedOffBy);
     assertThat(info.createNewChangeForAllNotInTarget.configuredValue)
         .isEqualTo(input.createNewChangeForAllNotInTarget);
-    assertThat(info.requireChangeId.configuredValue).isEqualTo(input.requireChangeId);
     assertThat(info.rejectImplicitMerges.configuredValue).isEqualTo(input.rejectImplicitMerges);
     assertThat(info.enableReviewerByEmail.configuredValue).isEqualTo(input.enableReviewerByEmail);
     assertThat(info.createNewChangeForAllNotInTarget.configuredValue)
@@ -346,7 +345,6 @@
     assertThat(info.useSignedOffBy.configuredValue).isEqualTo(input.useSignedOffBy);
     assertThat(info.createNewChangeForAllNotInTarget.configuredValue)
         .isEqualTo(input.createNewChangeForAllNotInTarget);
-    assertThat(info.requireChangeId.configuredValue).isEqualTo(input.requireChangeId);
     assertThat(info.rejectImplicitMerges.configuredValue).isEqualTo(input.rejectImplicitMerges);
     assertThat(info.enableReviewerByEmail.configuredValue).isEqualTo(input.enableReviewerByEmail);
     assertThat(info.createNewChangeForAllNotInTarget.configuredValue)
@@ -683,7 +681,6 @@
     input.useContentMerge = InheritableBoolean.TRUE;
     input.useSignedOffBy = InheritableBoolean.TRUE;
     input.createNewChangeForAllNotInTarget = InheritableBoolean.TRUE;
-    input.requireChangeId = InheritableBoolean.TRUE;
     input.rejectImplicitMerges = InheritableBoolean.TRUE;
     input.enableReviewerByEmail = InheritableBoolean.TRUE;
     input.createNewChangeForAllNotInTarget = InheritableBoolean.TRUE;
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
index c85aa93..cc99a90 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
@@ -89,7 +89,6 @@
 import com.google.gerrit.git.ObjectIds;
 import com.google.gerrit.mail.Address;
 import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.BooleanProjectConfig;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.ChangeMessage;
 import com.google.gerrit.reviewdb.client.PatchSet;
@@ -124,7 +123,6 @@
 import org.eclipse.jgit.junit.TestRepository;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.RefUpdate;
 import org.eclipse.jgit.lib.RefUpdate.Result;
 import org.eclipse.jgit.lib.Repository;
@@ -459,20 +457,6 @@
   }
 
   @Test
-  public void pushWithoutChangeIdDeprecated() throws Exception {
-    setRequireChangeId(InheritableBoolean.FALSE);
-    testRepo
-        .branch("HEAD")
-        .commit()
-        .message("A change")
-        .author(admin.newIdent())
-        .committer(new PersonIdent(admin.newIdent(), testRepo.getDate()))
-        .create();
-    PushResult result = pushHead(testRepo, "refs/for/master");
-    assertThat(result.getMessages()).contains("warning: pushing without Change-Id is deprecated");
-  }
-
-  @Test
   public void autocloseByChangeId() throws Exception {
     // Create a change
     PushOneCommit.Result r = pushTo("refs/for/master");
@@ -1572,9 +1556,6 @@
     RevCommit c = createCommit(testRepo, "Message without Change-Id");
     assertThat(GitUtil.getChangeId(testRepo, c)).isEmpty();
     pushForReviewRejected(testRepo, "missing Change-Id in message footer");
-
-    setRequireChangeId(InheritableBoolean.FALSE);
-    pushForReviewOk(testRepo);
   }
 
   @Test
@@ -1598,9 +1579,6 @@
                 + "More text, uh oh.\n");
     assertThat(GitUtil.getChangeId(testRepo, c)).isEmpty();
     pushForReviewRejected(testRepo, "Change-Id must be in message footer");
-
-    setRequireChangeId(InheritableBoolean.FALSE);
-    pushForReviewRejected(testRepo, "Change-Id must be in message footer");
   }
 
   @Test
@@ -1637,9 +1615,6 @@
             + "Change-Id: I10f98c2ef76e52e23aa23be5afeb71e40b350e86\n"
             + "Change-Id: Ie9a132e107def33bdd513b7854b50de911edba0a\n");
     pushForReviewRejected(testRepo, "multiple Change-Id lines in message footer");
-
-    setRequireChangeId(InheritableBoolean.FALSE);
-    pushForReviewRejected(testRepo, "multiple Change-Id lines in message footer");
   }
 
   @Test
@@ -1656,9 +1631,6 @@
   private void testpushWithInvalidChangeId() throws Exception {
     createCommit(testRepo, "Message with invalid Change-Id\n\nChange-Id: X\n");
     pushForReviewRejected(testRepo, "invalid Change-Id line format in message footer");
-
-    setRequireChangeId(InheritableBoolean.FALSE);
-    pushForReviewRejected(testRepo, "invalid Change-Id line format in message footer");
   }
 
   @Test
@@ -1680,18 +1652,12 @@
             + "\n"
             + "Change-Id: I0000000000000000000000000000000000000000\n");
     pushForReviewRejected(testRepo, "invalid Change-Id line format in message footer");
-
-    setRequireChangeId(InheritableBoolean.FALSE);
-    pushForReviewRejected(testRepo, "invalid Change-Id line format in message footer");
   }
 
   @Test
   public void pushWithChangeIdInSubjectLine() throws Exception {
     createCommit(testRepo, "Change-Id: I1234000000000000000000000000000000000000");
     pushForReviewRejected(testRepo, "missing subject; Change-Id must be in message footer");
-
-    setRequireChangeId(InheritableBoolean.FALSE);
-    pushForReviewRejected(testRepo, "missing subject; Change-Id must be in message footer");
   }
 
   @Test
@@ -1709,19 +1675,6 @@
         "same Change-Id in multiple changes.\n"
             + "Squash the commits with the same Change-Id or ensure Change-Ids are unique for each"
             + " commit");
-
-    try (ProjectConfigUpdate u = updateProject(project)) {
-      u.getConfig()
-          .getProject()
-          .setBooleanConfig(BooleanProjectConfig.REQUIRE_CHANGE_ID, InheritableBoolean.FALSE);
-      u.save();
-    }
-
-    pushForReviewRejected(
-        testRepo,
-        "same Change-Id in multiple changes.\n"
-            + "Squash the commits with the same Change-Id or ensure Change-Ids are unique for each"
-            + " commit");
   }
 
   @Test
@@ -1735,19 +1688,6 @@
         "same Change-Id in multiple changes.\n"
             + "Squash the commits with the same Change-Id or ensure Change-Ids are unique for each"
             + " commit");
-
-    try (ProjectConfigUpdate u = updateProject(project)) {
-      u.getConfig()
-          .getProject()
-          .setBooleanConfig(BooleanProjectConfig.REQUIRE_CHANGE_ID, InheritableBoolean.FALSE);
-      u.save();
-    }
-
-    pushForReviewRejected(
-        testRepo,
-        "same Change-Id in multiple changes.\n"
-            + "Squash the commits with the same Change-Id or ensure Change-Ids are unique for each"
-            + " commit");
   }
 
   private static RevCommit createCommit(TestRepository<?> testRepo, String message)
diff --git a/javatests/com/google/gerrit/acceptance/git/PushPermissionsIT.java b/javatests/com/google/gerrit/acceptance/git/PushPermissionsIT.java
index 3503675..66af8a4 100644
--- a/javatests/com/google/gerrit/acceptance/git/PushPermissionsIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/PushPermissionsIT.java
@@ -30,10 +30,8 @@
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.common.data.Permission;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
-import com.google.gerrit.extensions.client.InheritableBoolean;
 import com.google.gerrit.extensions.client.ProjectState;
 import com.google.gerrit.extensions.common.ChangeInput;
-import com.google.gerrit.reviewdb.client.BooleanProjectConfig;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.server.project.ProjectConfig;
@@ -61,8 +59,6 @@
   public void setUp() throws Exception {
     try (ProjectConfigUpdate u = updateProject(allProjects)) {
       ProjectConfig cfg = u.getConfig();
-      cfg.getProject()
-          .setBooleanConfig(BooleanProjectConfig.REQUIRE_CHANGE_ID, InheritableBoolean.FALSE);
 
       // Remove push-related permissions, so they can be added back individually by test methods.
       removeAllBranchPermissions(
@@ -255,7 +251,8 @@
         .add(allow(Permission.PUSH).ref("refs/for/refs/heads/*").group(REGISTERED_USERS))
         .update();
 
-    ObjectId commit = testRepo.branch("HEAD").commit().create();
+    ObjectId commit =
+        testRepo.branch("HEAD").commit().message("test commit").insertChangeId().create();
     assertThat(push("HEAD:refs/for/master")).onlyRef("refs/for/master").isOk();
     gApi.changes().id(commit.name()).current().review(ReviewInput.approve());
 
diff --git a/javatests/com/google/gerrit/acceptance/rest/BUILD b/javatests/com/google/gerrit/acceptance/rest/BUILD
index c766934..84887da 100644
--- a/javatests/com/google/gerrit/acceptance/rest/BUILD
+++ b/javatests/com/google/gerrit/acceptance/rest/BUILD
@@ -6,6 +6,5 @@
     labels = ["rest"],
     deps = [
         "//java/com/google/gerrit/server/logging",
-        "//java/com/google/gerrit/util/cli",
     ],
 )
diff --git a/javatests/com/google/gerrit/acceptance/rest/UnknownOptionIT.java b/javatests/com/google/gerrit/acceptance/rest/UnknownOptionIT.java
deleted file mode 100644
index 99c727e..0000000
--- a/javatests/com/google/gerrit/acceptance/rest/UnknownOptionIT.java
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (C) 2019 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.acceptance.rest;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.server.change.ChangeResource.CHANGE_KIND;
-import static org.apache.http.HttpStatus.SC_BAD_REQUEST;
-import static org.apache.http.HttpStatus.SC_OK;
-
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.RestResponse;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.restapi.Response;
-import com.google.gerrit.extensions.restapi.RestApiModule;
-import com.google.gerrit.extensions.restapi.RestReadView;
-import com.google.gerrit.server.change.ChangeResource;
-import com.google.gerrit.util.cli.UnknownOptionHandler;
-import com.google.inject.Module;
-import org.junit.Test;
-
-public class UnknownOptionIT extends AbstractDaemonTest {
-  @Override
-  public Module createModule() {
-    return new RestApiModule() {
-      @Override
-      protected void configure() {
-        get(CHANGE_KIND, "test").to(MyChangeView.class);
-      }
-    };
-  }
-
-  @Test
-  public void unknownOptionIsRejectedIfRestEndpointDoesNotHandleUnknownOptions() throws Exception {
-    RestResponse response = adminRestSession.get("/accounts/self/detail?foo-bar");
-    assertThat(response.getStatusCode()).isEqualTo(SC_BAD_REQUEST);
-  }
-
-  @Test
-  public void unknownOptionIsIgnoredIfRestEndpointAcceptsIt() throws Exception {
-    String changeId = createChange().getChangeId();
-    RestResponse response = adminRestSession.get("/changes/" + changeId + "/test?ignore-foo");
-    assertThat(response.getStatusCode()).isEqualTo(SC_OK);
-  }
-
-  @Test
-  public void unknownOptionCausesFailureIfRestEndpointDoesNotAcceptIt() throws Exception {
-    String changeId = createChange().getChangeId();
-    RestResponse response = adminRestSession.get("/changes/" + changeId + "/test?foo-bar");
-    assertThat(response.getStatusCode()).isEqualTo(SC_BAD_REQUEST);
-  }
-
-  @Test
-  public void unknownPluginOptionIsIgnoredIfRestEndpointSupportsDynamicOptions() throws Exception {
-    String changeId = createChange().getChangeId();
-    RestResponse response = adminRestSession.get("/changes/" + changeId + "?foo--bar");
-    assertThat(response.getStatusCode()).isEqualTo(SC_OK);
-  }
-
-  @Test
-  public void unknownNonPluginOptionCausesFailureIfRestEndpointSupportsDynamicOptions()
-      throws Exception {
-    String changeId = createChange().getChangeId();
-    RestResponse response = adminRestSession.get("/changes/" + changeId + "?foo-bar");
-    assertThat(response.getStatusCode()).isEqualTo(SC_BAD_REQUEST);
-  }
-
-  @Test
-  public void unknownPluginOptionCausesFailureIfRestEndpointDoesNotSupportDynamicOptions()
-      throws Exception {
-    String changeId = createChange().getChangeId();
-    RestResponse response = adminRestSession.get("/changes/" + changeId + "/comments?foo--bar");
-    assertThat(response.getStatusCode()).isEqualTo(SC_BAD_REQUEST);
-  }
-
-  private static class MyChangeView implements RestReadView<ChangeResource>, UnknownOptionHandler {
-    @Override
-    public Response<String> apply(ChangeResource resource) {
-      return Response.ok("OK");
-    }
-
-    @Override
-    public boolean accept(String name, @Nullable String value) {
-      return name.startsWith("--ignore");
-    }
-  }
-}
diff --git a/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java b/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
index 043bde7..b102619 100644
--- a/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/project/CreateProjectIT.java
@@ -218,7 +218,6 @@
     in.useContributorAgreements = InheritableBoolean.TRUE;
     in.useSignedOffBy = InheritableBoolean.TRUE;
     in.useContentMerge = InheritableBoolean.TRUE;
-    in.requireChangeId = InheritableBoolean.TRUE;
     ProjectInfo p = gApi.projects().create(in).get();
     assertThat(p.name).isEqualTo(newProjectName);
     Project project = projectCache.get(Project.nameKey(newProjectName)).getProject();
@@ -231,8 +230,6 @@
         .isEqualTo(in.useSignedOffBy);
     assertThat(project.getBooleanConfig(BooleanProjectConfig.USE_CONTENT_MERGE))
         .isEqualTo(in.useContentMerge);
-    assertThat(project.getBooleanConfig(BooleanProjectConfig.REQUIRE_CHANGE_ID))
-        .isEqualTo(in.requireChangeId);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/server/project/ProjectConfigTest.java b/javatests/com/google/gerrit/server/project/ProjectConfigTest.java
index 75e1cd7..aacd41b 100644
--- a/javatests/com/google/gerrit/server/project/ProjectConfigTest.java
+++ b/javatests/com/google/gerrit/server/project/ProjectConfigTest.java
@@ -16,7 +16,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
-import static com.google.gerrit.reviewdb.client.BooleanProjectConfig.REQUIRE_CHANGE_ID;
+import static com.google.gerrit.reviewdb.client.BooleanProjectConfig.USE_CONTRIBUTOR_AGREEMENTS;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
@@ -612,13 +612,13 @@
   public void readAllProjectsBaseConfigFromSitePaths() throws Exception {
     ProjectConfig cfg = factory.create(ALL_PROJECTS);
     cfg.load(db);
-    assertThat(cfg.getProject().getBooleanConfig(REQUIRE_CHANGE_ID))
+    assertThat(cfg.getProject().getBooleanConfig(USE_CONTRIBUTOR_AGREEMENTS))
         .isEqualTo(InheritableBoolean.INHERIT);
 
-    writeDefaultAllProjectsConfig("[receive]", "requireChangeId = false");
+    writeDefaultAllProjectsConfig("[receive]", "requireContributorAgreement = false");
 
     cfg.load(db);
-    assertThat(cfg.getProject().getBooleanConfig(REQUIRE_CHANGE_ID))
+    assertThat(cfg.getProject().getBooleanConfig(USE_CONTRIBUTOR_AGREEMENTS))
         .isEqualTo(InheritableBoolean.FALSE);
   }
 
@@ -626,17 +626,17 @@
   public void readOtherProjectIgnoresAllProjectsBaseConfig() throws Exception {
     ProjectConfig cfg = factory.create(Project.nameKey("test"));
     cfg.load(db);
-    assertThat(cfg.getProject().getBooleanConfig(REQUIRE_CHANGE_ID))
+    assertThat(cfg.getProject().getBooleanConfig(USE_CONTRIBUTOR_AGREEMENTS))
         .isEqualTo(InheritableBoolean.INHERIT);
 
-    writeDefaultAllProjectsConfig("[receive]", "requireChangeId = false");
+    writeDefaultAllProjectsConfig("[receive]", "requireContributorAgreement = false");
 
     cfg.load(db);
     // If we went through ProjectState, then this would return FALSE, since project.config for
     // All-Projects would inherit from all_projects.config, and this project would inherit from
     // All-Projects. But in ProjectConfig itself, there is no inheritance from All-Projects, so this
     // continues to return the default.
-    assertThat(cfg.getProject().getBooleanConfig(REQUIRE_CHANGE_ID))
+    assertThat(cfg.getProject().getBooleanConfig(USE_CONTRIBUTOR_AGREEMENTS))
         .isEqualTo(InheritableBoolean.INHERIT);
   }
 
diff --git a/plugins/plugin-manager b/plugins/plugin-manager
index a51055a..f681e7e 160000
--- a/plugins/plugin-manager
+++ b/plugins/plugin-manager
@@ -1 +1 @@
-Subproject commit a51055a8f3b71f2ccf634016c42eb5b8086a373b
+Subproject commit f681e7ecb6ddbc52fe9e07cf3672ccdcad7d7d0b
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
index 52f143c..044e1fe 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo.html
@@ -154,21 +154,6 @@
                   </gr-select>
                 </span>
               </section>
-              <section>
-                <span class="title">Require Change-Id in commit message</span>
-                <span class="value">
-                  <gr-select
-                      id="requireChangeIdSelect"
-                      bind-value="{{_repoConfig.require_change_id.configured_value}}">
-                    <select disabled$="[[_readOnly]]">
-                      <template is="dom-repeat"
-                          items="[[_formatBooleanSelect(_repoConfig.require_change_id)]]">
-                        <option value="[[item.value]]">[[item.label]]</option>
-                      </template>
-                    </select>
-                  </gr-select>
-                </span>
-              </section>
               <section
                    id="enableSignedPushSettings"
                    class$="repositorySettings [[_computeRepositoriesClass(_repoConfig.enable_signed_push)]]">
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.html b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.html
index 53db6d5..744ef42 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.html
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.html
@@ -57,10 +57,6 @@
         value: false,
         configured_value: 'FALSE',
       },
-      require_change_id: {
-        value: false,
-        configured_value: 'FALSE',
-      },
       enable_signed_push: {
         value: false,
         configured_value: 'FALSE',
@@ -322,7 +318,6 @@
           use_content_merge: 'TRUE',
           use_signed_off_by: 'TRUE',
           create_new_change_for_all_not_in_target: 'TRUE',
-          require_change_id: 'TRUE',
           enable_signed_push: 'TRUE',
           require_signed_push: 'TRUE',
           reject_implicit_merges: 'TRUE',
@@ -352,8 +347,6 @@
               configInputObj.use_content_merge;
           element.$.newChangeSelect.bindValue =
               configInputObj.create_new_change_for_all_not_in_target;
-          element.$.requireChangeIdSelect.bindValue =
-              configInputObj.require_change_id;
           element.$.enableSignedPush.bindValue =
               configInputObj.enable_signed_push;
           element.$.requireSignedPush.bindValue =
diff --git a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js
index 83f68a1..f247156 100644
--- a/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js
+++ b/polygerrit-ui/app/elements/core/gr-reporting/gr-reporting.js
@@ -201,8 +201,11 @@
       if (type === ERROR.TYPE && category === ERROR.CATEGORY) {
         console.error(eventValue.error || eventName);
       } else {
-        console.log(eventName + (eventValue !== undefined ?
-            (': ' + eventValue) : ''));
+        if (eventValue !== undefined) {
+          console.log(`Reporting: ${eventName}: ${eventValue}`);
+        } else {
+          console.log(`Reporting: ${eventName}`);
+        }
       }
     },
 
diff --git a/polygerrit-ui/app/elements/gr-app-element.js b/polygerrit-ui/app/elements/gr-app-element.js
index af69af8..4d556ae 100644
--- a/polygerrit-ui/app/elements/gr-app-element.js
+++ b/polygerrit-ui/app/elements/gr-app-element.js
@@ -424,8 +424,6 @@
       if (window.VERSION_INFO) {
         console.log(`UI Version Info: ${window.VERSION_INFO}`);
       }
-      const renderTime = new Date(window.performance.timing.loadEventStart);
-      console.log(`Document loaded at: ${renderTime}`);
       console.log(`Please file bugs and feedback at: ${this._feedbackUrl}`);
       console.groupEnd();
     },