Option to create a new change for every commit not in target

One not-so-well-known feature of gerrit is that, you can set a
%base for the RevWalk in ReceiveCommits when pushing changes to
Gerrit. This makes it possible to push a commit for review and
override Gerrits default algorithm for creating new changes on
push to refs/for/*. For instance, one could submit a commit in
a private branch and, afterward, push the same commit to a
release branch.

Specifying the tip of the destination branch as the %base would
have an effect of creating a new change for every commit reachable
from the pushed commit and not reachable from the target branch.
This behavior seems to be wanted by some Gerrit users and is
implemented as a project config option by this change (although
it contradicts the Gerrit's philosophy of reviewing one commit once).
If a %base is explicitly set on during uploading changes,
new-change-for-all-not-in-target is ignored.

To avoid incidental pushes with merges,
new-change-for-all-not-in-target rejects uploads if changes
contain merge commits. In such cases to push a merge commit, you
need to explicitly set the %base parameter as described in
Uploading Changes / Selecting Merge Base documentation.

Bug: issue 1195
Change-Id: Ifa90184352c912885e52d2060356fcc039d0ef03
diff --git a/Documentation/cmd-create-project.txt b/Documentation/cmd-create-project.txt
index d747852..89e10da 100644
--- a/Documentation/cmd-create-project.txt
+++ b/Documentation/cmd-create-project.txt
@@ -15,6 +15,7 @@
   [--use-contributor-agreements | --ca]
   [--use-signed-off-by | --so]
   [--use-content-merge]
+  [--create-new-change-for-all-not-in-target]
   [--require-change-id | --id]
   [[--branch <REF> | -b <REF>] ...]
   [--empty-commit]
@@ -134,6 +135,15 @@
 	from either the author or the uploader in the commit message.
 	Disabled by default.
 
+--create-new-change-for-all-not-in-target::
+--ncfa:
+	If enabled, a new change is created for every commit not in
+	target branch. If the pushed commit is merge commit, this flag is
+	ignored for that push. This option also does not accept merge
+	commits in commit chain to avoid accidental creation of a large
+	number of open changes.
+	Disabled by default.
+
 --require-change-id::
 --id::
 	Require a valid link:user-changeid.html[Change-Id] footer
diff --git a/Documentation/project-configuration.txt b/Documentation/project-configuration.txt
index 4b755f3..439fbc5 100644
--- a/Documentation/project-configuration.txt
+++ b/Documentation/project-configuration.txt
@@ -150,6 +150,25 @@
 are not able to see the project even if they have read permissions
 granted on the project.
 
+=== Use target branch when determining new changes to open
+
+The `create-new-change-for-all-not-in-target` option provides a
+convenience for selecting link:user-upload.html#base[the merge base]
+by setting it automatically to the target branch's tip so you can
+create new changes for all commits not in the target branch.
+
+This option is disabled if the tip of the push is a merge commit.
+
+This option also only works if there are no merge commits in the
+commit chain, in such cases it fails warning the user that such
+pushes can only be performed by manually specifying
+link:user-upload.html#base[bases]
+
+This option is useful if you want to push a change to your personal
+branch first and for review to another branch for example. Or in cases
+where a commit is already merged into a branch and you want to create
+a new open change for that commit on another branch.
+
 === Require Change-Id
 
 The `Require Change-Id in commit message` option defines whether a
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 4d9e02c..ccc50ed 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -671,6 +671,11 @@
       "configured_value": "INHERIT",
       "inherited_value": false
     },
+    "create_new_change_for_all_not_in_target": {
+      "value": false,
+      "configured_value": "INHERIT",
+      "inherited_value": false
+    },
     "require_change_id": {
       "value": false,
       "configured_value": "FALSE",
@@ -725,6 +730,7 @@
     "use_contributor_agreements": "FALSE",
     "use_content_merge": "INHERIT",
     "use_signed_off_by": "INHERIT",
+    "create_new_change_for_all_not_in_target": "INHERIT",
     "require_change_id": "TRUE",
     "max_object_size_limit": "10m",
     "submit_type": "REBASE_IF_NECESSARY",
@@ -758,6 +764,11 @@
       "configured_value": "INHERIT",
       "inherited_value": false
     },
+    "create_new_change_for_all_not_in_target": {
+      "value": true,
+      "configured_value": "INHERIT",
+      "inherited_value": false
+    },
     "require_change_id": {
       "value": true,
       "configured_value": "TRUE",
@@ -1622,25 +1633,28 @@
 configuration.
 
 [options="header",width="50%",cols="1,^2,4"]
-|=========================================
-|Field Name                  ||Description
-|`description`               |optional|
+|=======================================================
+|Field Name                                ||Description
+|`description`                             |optional|
 The description of the project.
-|`use_contributor_agreements`|optional|
+|`use_contributor_agreements`              |optional|
 link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether
 authors must complete a contributor agreement on the site before
 pushing any commits or changes to this project.
-|`use_content_merge`         |optional|
+|`use_content_merge`                       |optional|
 link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether
 Gerrit will try to perform a 3-way merge of text file content when a
 file has been modified by both the destination branch and the change
 being submitted. This option only takes effect if submit type is not
 FAST_FORWARD_ONLY.
-|`use_signed_off_by`         |optional|
+|`use_signed_off_by`                       |optional|
 link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether
 each change must contain a Signed-off-by line from either the author or
 the uploader in the commit message.
-|`require_change_id`         |optional|
+|`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
@@ -1662,14 +1676,14 @@
 configuration, which has the same format as the
 link:config-gerrit.html#_a_id_commentlink_a_section_commentlink[
 commentlink section] of `gerrit.config`.
-|`theme`                     |optional|
+|`theme`                                   |optional|
 The theme that is configured for the project as a link:#theme-info[
 ThemeInfo] entity.
-|`plugin_config`             |optional|
+|`plugin_config`                           |optional|
 Plugin configuration as map which maps the plugin name to a map of
 parameter names to link:#config-parameter-info[ConfigParameterInfo]
 entities.
-|`actions`                   |optional|
+|`actions`                                 |optional|
 Actions the caller might be able to perform on this project. The
 information is a map of view names to
 link:rest-api-changes.html#action-info[ActionInfo] entities.
@@ -1680,50 +1694,55 @@
 The `ConfigInput` entity describes a new project configuration.
 
 [options="header",width="50%",cols="1,^2,4"]
-|=========================================
-|Field Name                  ||Description
-|`description`               |optional|
+|======================================================
+|Field Name                               ||Description
+|`description`                            |optional|
 The new description of the project. +
 If not set, the description is removed.
-|`use_contributor_agreements`|optional|
+|`use_contributor_agreements`             |optional|
 Whether authors must complete a contributor agreement on the site
 before pushing any commits or changes to this project. +
 Can be `TRUE`, `FALSE` or `INHERIT`. +
 If not set, this setting is not updated.
-|`use_content_merge`         |optional|
+|`use_content_merge`                       |optional|
 Whether Gerrit will try to perform a 3-way merge of text file content
 when a file has been modified by both the destination branch and the
 change being submitted. This option only takes effect if submit type is
 not FAST_FORWARD_ONLY. +
 Can be `TRUE`, `FALSE` or `INHERIT`. +
 If not set, this setting is not updated.
-|`use_signed_off_by`         |optional|
+|`use_signed_off_by`                       |optional|
 Whether each change must contain a Signed-off-by line from either the
 author or the uploader in the commit message. +
 Can be `TRUE`, `FALSE` or `INHERIT`. +
 If not set, this setting is not updated.
-|`require_change_id`         |optional|
+|`create_new_change_for_all_not_in_target` |optional|
+Whether a new change will be created for every commit not in target
+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.
-|`max_object_size_limit`     |optional|
+|`max_object_size_limit`                   |optional|
 The link:config-gerrit.html#receive.maxObjectSizeLimit[max object size
 limit] of this project as a link:#max-object-size-limit-info[
 MaxObjectSizeLimitInfo] entity. +
 If set to `0`, the max object size limit is removed. +
 If not set, this setting is not updated.
-|`submit_type`               |optional|
+|`submit_type`                             |optional|
 The default submit type of the project, can be `MERGE_IF_NECESSARY`,
 `FAST_FORWARD_ONLY`, `REBASE_IF_NECESSARY`, `MERGE_ALWAYS` or
 `CHERRY_PICK`. +
 If not set, the submit type is not updated.
-|`state`                     |optional|
+|`state`                                   |optional|
 The state of the project, can be `ACTIVE`, `READ_ONLY` or `HIDDEN`. +
 Not set if the project state is `ACTIVE`. +
 If not set, the project state is not updated.
-|`plugin_config_values`      |optional|
+|`plugin_config_values`                    |optional|
 Plugin configuration values as map which maps the plugin name to a map
 of parameter names to values.
 |=========================================
@@ -1970,17 +1989,20 @@
 If not set, the link:config-gerrit.html#repository.name.ownerGroup[
 groups that are configured as default owners] are set as project
 owners.
-|`use_contributor_agreements`|`INHERIT` if not set|
+|`use_contributor_agreements`                  |`INHERIT` if not set|
 Whether contributor agreements should be used for the project  (`TRUE`,
 `FALSE`, `INHERIT`).
-|`use_signed_off_by`         |`INHERIT` if not set|
+|`use_signed_off_by`                           |`INHERIT` if not set|
 Whether the usage of 'Signed-Off-By' footers is required for the
 project (`TRUE`, `FALSE`, `INHERIT`).
-|`use_content_merge`         |`INHERIT` if not set|
+|`create_new_change_for_all_not_in_target`     |`INHERIT` if not set|
+Whether a new change is created for every commit not in target branch
+for the project (`TRUE`, `FALSE`, `INHERIT`).
+|`use_content_merge`                           |`INHERIT` if not set|
 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|
+|`require_change_id`                           |`INHERIT` if not set|
 Whether the usage of Change-Ids is required for the project (`TRUE`,
 `FALSE`, `INHERIT`).
 |`max_object_size_limit`     |optional|
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ProjectInput.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ProjectInput.java
index 74b2be87..daa5de7 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ProjectInput.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/projects/ProjectInput.java
@@ -33,6 +33,7 @@
   public InheritableBoolean useSignedOffBy;
   public InheritableBoolean useContentMerge;
   public InheritableBoolean requireChangeId;
+  public InheritableBoolean createNewChangeForAllNotInTarget;
   public String maxObjectSizeLimit;
   public Map<String, Map<String, ConfigValue>> pluginConfigValues;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
index c64620f..e8f07e6 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.java
@@ -41,6 +41,7 @@
   String useContentMerge();
   String useContributorAgreements();
   String useSignedOffBy();
+  String createNewChangeForAllNotInTarget();
   String requireChangeID();
   String headingMaxObjectSizeLimit();
   String headingGroupOptions();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
index 1bb0386e..f9cba41 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AdminConstants.properties
@@ -23,6 +23,7 @@
 useContentMerge = Automatically resolve conflicts
 useContributorAgreements = Require a valid contributor agreement to upload
 useSignedOffBy = Require <code>Signed-off-by</code> in commit message
+createNewChangeForAllNotInTarget = Create a new change for every commit not in the target branch
 requireChangeID = Require <code>Change-Id</code> in commit message
 headingMaxObjectSizeLimit = Maximum Git object size limit
 headingGroupOptions = Group Options
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
index 24ee27d..69d7c9e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java
@@ -79,6 +79,7 @@
   private ListBox submitType;
   private ListBox state;
   private ListBox contentMerge;
+  private ListBox newChangeForAllNotInTarget;
   private NpTextBox maxObjectSizeLimit;
   private Label effectiveMaxObjectSizeLimit;
   private Map<String, Map<String, HasEnabled>> pluginConfigWidgets;
@@ -157,6 +158,7 @@
     state.setEnabled(isOwner);
     submitType.setEnabled(isOwner);
     setEnabledForUseContentMerge();
+    newChangeForAllNotInTarget.setEnabled(isOwner);
     descTxt.setEnabled(isOwner);
     contributorAgreements.setEnabled(isOwner);
     signedOffBy.setEnabled(isOwner);
@@ -213,6 +215,10 @@
     saveEnabler.listenTo(contentMerge);
     grid.add(Util.C.useContentMerge(), contentMerge);
 
+    newChangeForAllNotInTarget = newInheritedBooleanBox();
+    saveEnabler.listenTo(newChangeForAllNotInTarget);
+    grid.add(Util.C.createNewChangeForAllNotInTarget(), newChangeForAllNotInTarget);
+
     requireChangeID = newInheritedBooleanBox();
     saveEnabler.listenTo(requireChangeID);
     grid.addHtml(Util.C.requireChangeID(), requireChangeID);
@@ -338,6 +344,7 @@
     setBool(contributorAgreements, result.use_contributor_agreements());
     setBool(signedOffBy, result.use_signed_off_by());
     setBool(contentMerge, result.use_content_merge());
+    setBool(newChangeForAllNotInTarget, result.create_new_change_for_all_not_in_target());
     setBool(requireChangeID, result.require_change_id());
     setSubmitType(result.submit_type());
     setState(result.state());
@@ -569,7 +576,7 @@
     saveProject.setEnabled(false);
     ProjectApi.setConfig(getProjectKey(), descTxt.getText().trim(),
         getBool(contributorAgreements), getBool(contentMerge),
-        getBool(signedOffBy), getBool(requireChangeID),
+        getBool(signedOffBy), getBool(newChangeForAllNotInTarget), getBool(requireChangeID),
         maxObjectSizeLimit.getText().trim(),
         SubmitType.valueOf(submitType.getValue(submitType.getSelectedIndex())),
         ProjectState.valueOf(state.getValue(state.getSelectedIndex())),
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
index e3c77b8..58d8f00 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ConfigInfo.java
@@ -44,6 +44,9 @@
   public final native InheritedBooleanInfo use_contributor_agreements()
   /*-{ return this.use_contributor_agreements; }-*/;
 
+  public final native InheritedBooleanInfo create_new_change_for_all_not_in_target()
+  /*-{ return this.create_new_change_for_all_not_in_target; }-*/;
+
   public final native InheritedBooleanInfo use_signed_off_by()
   /*-{ return this.use_signed_off_by; }-*/;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java
index 4762027..45c26de 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/projects/ProjectApi.java
@@ -85,6 +85,7 @@
   public static void setConfig(Project.NameKey name, String description,
       InheritableBoolean useContributorAgreements,
       InheritableBoolean useContentMerge, InheritableBoolean useSignedOffBy,
+      InheritableBoolean createNewChangeForAllNotInTarget,
       InheritableBoolean requireChangeId, String maxObjectSizeLimit,
       SubmitType submitType, ProjectState state,
       Map<String, Map<String, ConfigParameterValue>> pluginConfigValues,
@@ -95,6 +96,7 @@
     in.setUseContentMerge(useContentMerge);
     in.setUseSignedOffBy(useSignedOffBy);
     in.setRequireChangeId(requireChangeId);
+    in.setCreateNewChangeForAllNotInTarget(createNewChangeForAllNotInTarget);
     in.setMaxObjectSizeLimit(maxObjectSizeLimit);
     in.setSubmitType(submitType);
     in.setState(state);
@@ -209,6 +211,12 @@
     private final native void setRequireChangeIdRaw(String v)
     /*-{ if(v)this.require_change_id=v; }-*/;
 
+    final void setCreateNewChangeForAllNotInTarget(InheritableBoolean v) {
+      setCreateNewChangeForAllNotInTargetRaw(v.name());
+    }
+    private final native void setCreateNewChangeForAllNotInTargetRaw(String v)
+    /*-{ if(v)this.create_new_change_for_all_not_in_target=v; }-*/;
+
     final native void setMaxObjectSizeLimit(String l)
     /*-{ if(l)this.max_object_size_limit=l; }-*/;
 
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Project.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Project.java
index 1114813..a17f908 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Project.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Project.java
@@ -94,6 +94,8 @@
 
   protected String themeName;
 
+  protected InheritableBoolean createNewChangeForAllNotInTarget;
+
   protected Project() {
   }
 
@@ -105,6 +107,7 @@
     useSignedOffBy = InheritableBoolean.INHERIT;
     requireChangeID = InheritableBoolean.INHERIT;
     useContentMerge = InheritableBoolean.INHERIT;
+    createNewChangeForAllNotInTarget = InheritableBoolean.INHERIT;
   }
 
   public Project.NameKey getNameKey() {
@@ -159,6 +162,15 @@
     requireChangeID = cid;
   }
 
+  public InheritableBoolean getCreateNewChangeForAllNotInTarget() {
+    return createNewChangeForAllNotInTarget;
+  }
+
+  public void setCreateNewChangeForAllNotInTarget(
+      InheritableBoolean useAllNotInTarget) {
+    this.createNewChangeForAllNotInTarget = useAllNotInTarget;
+  }
+
   public void setMaxObjectSizeLimit(final String limit) {
     maxObjectSizeLimit = limit;
   }
@@ -212,6 +224,7 @@
     submitType = update.submitType;
     state = update.state;
     maxObjectSizeLimit = update.maxObjectSizeLimit;
+    createNewChangeForAllNotInTarget = update.createNewChangeForAllNotInTarget;
   }
 
   /**
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
index f8229ea..8b902bd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ProjectConfig.java
@@ -115,6 +115,8 @@
   private static final String RECEIVE = "receive";
   private static final String KEY_REQUIRE_SIGNED_OFF_BY = "requireSignedOffBy";
   private static final String KEY_REQUIRE_CHANGE_ID = "requireChangeId";
+  private static final String KEY_USE_ALL_NOT_IN_TARGET =
+      "createNewChangeForAllNotInTarget";
   private static final String KEY_MAX_OBJECT_SIZE_LIMIT = "maxObjectSizeLimit";
   private static final String KEY_REQUIRE_CONTRIBUTOR_AGREEMENT =
       "requireContributorAgreement";
@@ -419,6 +421,7 @@
     p.setUseContributorAgreements(getEnum(rc, RECEIVE, null, KEY_REQUIRE_CONTRIBUTOR_AGREEMENT, InheritableBoolean.INHERIT));
     p.setUseSignedOffBy(getEnum(rc, RECEIVE, null, KEY_REQUIRE_SIGNED_OFF_BY, InheritableBoolean.INHERIT));
     p.setRequireChangeID(getEnum(rc, RECEIVE, null, KEY_REQUIRE_CHANGE_ID, InheritableBoolean.INHERIT));
+    p.setCreateNewChangeForAllNotInTarget(getEnum(rc, RECEIVE, null, KEY_USE_ALL_NOT_IN_TARGET, InheritableBoolean.INHERIT));
     p.setMaxObjectSizeLimit(rc.getString(RECEIVE, null, KEY_MAX_OBJECT_SIZE_LIMIT));
 
     p.setSubmitType(getEnum(rc, SUBMIT, null, KEY_ACTION, defaultSubmitAction));
@@ -818,6 +821,7 @@
     set(rc, RECEIVE, null, KEY_REQUIRE_CONTRIBUTOR_AGREEMENT, p.getUseContributorAgreements(), InheritableBoolean.INHERIT);
     set(rc, RECEIVE, null, KEY_REQUIRE_SIGNED_OFF_BY, p.getUseSignedOffBy(), InheritableBoolean.INHERIT);
     set(rc, RECEIVE, null, KEY_REQUIRE_CHANGE_ID, p.getRequireChangeID(), InheritableBoolean.INHERIT);
+    set(rc, RECEIVE, null, KEY_USE_ALL_NOT_IN_TARGET, p.getCreateNewChangeForAllNotInTarget(), InheritableBoolean.INHERIT);
     set(rc, RECEIVE, null, KEY_MAX_OBJECT_SIZE_LIMIT, validMaxObjectSizeLimit(p.getMaxObjectSizeLimit()));
 
     set(rc, SUBMIT, null, KEY_ACTION, p.getSubmitType(), defaultSubmitAction);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index 938c9e6..6fe0f02 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -311,6 +311,7 @@
   private final ReceivePack rp;
   private final NoteMap rejectCommits;
   private MagicBranchInput magicBranch;
+  private boolean newChangeForAllNotInTarget;
 
   private List<CreateRequest> newChanges = Collections.emptyList();
   private final Map<Change.Id, ReplaceRequest> replaceByChange =
@@ -428,6 +429,7 @@
 
     ProjectState ps = projectControl.getProjectState();
 
+    this.newChangeForAllNotInTarget = ps.isCreateNewChangeForAllNotInTarget();
     rp.setAllowCreates(true);
     rp.setAllowDeletes(true);
     rp.setAllowNonFastForwards(true);
@@ -1293,6 +1295,21 @@
     }
 
     RevWalk walk = rp.getRevWalk();
+    RevCommit tip;
+    try {
+      tip = walk.parseCommit(magicBranch.cmd.getNewId());
+    } catch (IOException ex) {
+      magicBranch.cmd.setResult(REJECTED_MISSING_OBJECT);
+      log.error("Invalid pack upload; one or more objects weren't sent", ex);
+      return;
+    }
+
+    // If tip is a merge commit or %base was specified,
+    // ignore newChangeForAllNotInTarget
+    if (tip.getParentCount() > 1 || magicBranch.base != null) {
+      newChangeForAllNotInTarget = false;
+    }
+
     if (magicBranch.base != null) {
       magicBranch.baseCommit = Lists.newArrayListWithCapacity(
           magicBranch.base.size());
@@ -1313,6 +1330,18 @@
           return;
         }
       }
+    } else if (newChangeForAllNotInTarget) {
+      String destBranch = magicBranch.dest.get();
+      try {
+        ObjectId baseHead = repo.getRef(destBranch).getObjectId();
+        magicBranch.baseCommit =
+            Collections.singletonList(walk.parseCommit(baseHead));
+      } catch (IOException ex) {
+        log.warn(String.format("Project %s cannot read %s", project.getName(),
+            destBranch), ex);
+        reject(cmd, "internal server error");
+        return;
+      }
     }
 
     // Validate that the new commits are connected with the target
@@ -1321,7 +1350,6 @@
     // commits and the target branch head.
     //
     try {
-      final RevCommit tip = walk.parseCommit(magicBranch.cmd.getNewId());
       Ref targetRef = rp.getAdvertisedRefs().get(magicBranch.ctl.getRefName());
       if (targetRef == null || targetRef.getObjectId() == null) {
         // The destination branch does not yet exist. Assume the
@@ -1462,6 +1490,13 @@
           return Collections.emptyList();
         }
 
+        // Don't allow merges to be uploaded in commit chain via all-not-in-target
+        if (newChangeForAllNotInTarget && c.getParentCount() > 1) {
+          reject(magicBranch.cmd,
+              "Pushing merges in commit chains with 'all not in target' is not allowed,\n"
+            + "to override please set the base manually");
+        }
+
         Change.Key changeKey = new Change.Key("I" + c.name());
         final List<String> idList = c.getFooterLines(CHANGE_ID);
         if (idList.isEmpty()) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ConfigInfo.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ConfigInfo.java
index 358e023..47a313f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ConfigInfo.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ConfigInfo.java
@@ -43,6 +43,7 @@
   public InheritedBooleanInfo useContributorAgreements;
   public InheritedBooleanInfo useContentMerge;
   public InheritedBooleanInfo useSignedOffBy;
+  public InheritedBooleanInfo createNewChangeForAllNotInTarget;
   public InheritedBooleanInfo requireChangeId;
   public MaxObjectSizeLimitInfo maxObjectSizeLimit;
   public SubmitType submitType;
@@ -68,17 +69,23 @@
     InheritedBooleanInfo useSignedOffBy = new InheritedBooleanInfo();
     InheritedBooleanInfo useContentMerge = new InheritedBooleanInfo();
     InheritedBooleanInfo requireChangeId = new InheritedBooleanInfo();
+    InheritedBooleanInfo createNewChangeForAllNotInTarget =
+        new InheritedBooleanInfo();
 
     useContributorAgreements.value = projectState.isUseContributorAgreements();
     useSignedOffBy.value = projectState.isUseSignedOffBy();
     useContentMerge.value = projectState.isUseContentMerge();
     requireChangeId.value = projectState.isRequireChangeID();
+    createNewChangeForAllNotInTarget.value =
+        projectState.isCreateNewChangeForAllNotInTarget();
 
     useContributorAgreements.configuredValue =
         p.getUseContributorAgreements();
     useSignedOffBy.configuredValue = p.getUseSignedOffBy();
     useContentMerge.configuredValue = p.getUseContentMerge();
     requireChangeId.configuredValue = p.getRequireChangeID();
+    createNewChangeForAllNotInTarget.configuredValue =
+        p.getCreateNewChangeForAllNotInTarget();
 
     ProjectState parentState = Iterables.getFirst(projectState
         .parents(), null);
@@ -88,12 +95,15 @@
       useSignedOffBy.inheritedValue = parentState.isUseSignedOffBy();
       useContentMerge.inheritedValue = parentState.isUseContentMerge();
       requireChangeId.inheritedValue = parentState.isRequireChangeID();
+      createNewChangeForAllNotInTarget.inheritedValue =
+          parentState.isCreateNewChangeForAllNotInTarget();
     }
 
     this.useContributorAgreements = useContributorAgreements;
     this.useSignedOffBy = useSignedOffBy;
     this.useContentMerge = useContentMerge;
     this.requireChangeId = requireChangeId;
+    this.createNewChangeForAllNotInTarget = createNewChangeForAllNotInTarget;
 
     MaxObjectSizeLimitInfo maxObjectSizeLimit = new MaxObjectSizeLimitInfo();
     maxObjectSizeLimit.value =
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
index 43b736d..be7c272 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
@@ -124,6 +124,9 @@
             ? InheritableBoolean.FALSE : MoreObjects.firstNonNull(
                 input.useContentMerge,
                 InheritableBoolean.INHERIT);
+    args.newChangeForAllNotInTarget =
+        MoreObjects.firstNonNull(input.createNewChangeForAllNotInTarget,
+            InheritableBoolean.INHERIT);
     args.changeIdRequired =
         MoreObjects.firstNonNull(input.requireChangeId, InheritableBoolean.INHERIT);
     try {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProjectArgs.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProjectArgs.java
index e937e0f..428c7b2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProjectArgs.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProjectArgs.java
@@ -33,6 +33,7 @@
   public boolean permissionsOnly;
   public List<String> branch;
   public InheritableBoolean contentMerge;
+  public InheritableBoolean newChangeForAllNotInTarget;
   public InheritableBoolean changeIdRequired;
   public boolean createEmptyCommit;
   public String maxObjectSizeLimit;
@@ -42,6 +43,7 @@
     signedOffBy = InheritableBoolean.INHERIT;
     contentMerge = InheritableBoolean.INHERIT;
     changeIdRequired = InheritableBoolean.INHERIT;
+    newChangeForAllNotInTarget = InheritableBoolean.INHERIT;
     submitType = SubmitType.MERGE_IF_NECESSARY;
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PerformCreateProject.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PerformCreateProject.java
index c20480b..111385c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PerformCreateProject.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PerformCreateProject.java
@@ -193,6 +193,7 @@
           .setUseContributorAgreements(createProjectArgs.contributorAgreements);
       newProject.setUseSignedOffBy(createProjectArgs.signedOffBy);
       newProject.setUseContentMerge(createProjectArgs.contentMerge);
+      newProject.setCreateNewChangeForAllNotInTarget(createProjectArgs.newChangeForAllNotInTarget);
       newProject.setRequireChangeID(createProjectArgs.changeIdRequired);
       newProject.setMaxObjectSizeLimit(createProjectArgs.maxObjectSizeLimit);
       if (createProjectArgs.newParent != null) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
index 715419d..df48993 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
@@ -404,6 +404,15 @@
     });
   }
 
+  public boolean isCreateNewChangeForAllNotInTarget() {
+    return getInheritableBoolean(new Function<Project, InheritableBoolean>() {
+      @Override
+      public InheritableBoolean apply(Project input) {
+        return input.getCreateNewChangeForAllNotInTarget();
+      }
+    });
+  }
+
   public LabelTypes getLabelTypes() {
     Map<String, LabelType> types = Maps.newLinkedHashMap();
     for (ProjectState s : treeInOrder()) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
index e584b2e..7c7b966 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
@@ -66,6 +66,7 @@
     public InheritableBoolean useContributorAgreements;
     public InheritableBoolean useContentMerge;
     public InheritableBoolean useSignedOffBy;
+    public InheritableBoolean createNewChangeForAllNotInTarget;
     public InheritableBoolean requireChangeId;
     public String maxObjectSizeLimit;
     public SubmitType submitType;
@@ -146,6 +147,11 @@
       if (input.useSignedOffBy != null) {
         p.setUseSignedOffBy(input.useSignedOffBy);
       }
+
+      if (input.createNewChangeForAllNotInTarget != null) {
+        p.setCreateNewChangeForAllNotInTarget(input.createNewChangeForAllNotInTarget);
+      }
+
       if (input.requireChangeId != null) {
         p.setRequireChangeID(input.requireChangeId);
       }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java
index fb39dee5..624d4e5 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/CreateProjectCommand.java
@@ -87,6 +87,9 @@
   @Option(name = "--change-id", usage = "if change-id is required")
   private InheritableBoolean requireChangeID = InheritableBoolean.INHERIT;
 
+  @Option(name = "--new-change-for-all-not-in-target", usage = "if a new change will be created for every commit not in target branch")
+  private InheritableBoolean createNewChangeForAllNotInTarget = InheritableBoolean.INHERIT;
+
   @Option(name = "--use-contributor-agreements", aliases = {"--ca"}, usage = "if contributor agreement is required")
   void setUseContributorArgreements(boolean on) {
     contributorAgreements = InheritableBoolean.TRUE;
@@ -107,6 +110,11 @@
     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")
+  void setNewChangeForAllNotInTarget(boolean on) {
+    createNewChangeForAllNotInTarget = InheritableBoolean.TRUE;
+  }
+
   @Option(name = "--branch", aliases = {"-b"}, metaVar = "BRANCH", usage = "initial branch name\n"
       + "(default: master)")
   private List<String> branch;
@@ -166,6 +174,7 @@
         input.useSignedOffBy = signedOffBy;
         input.useContentMerge = contentMerge;
         input.requireChangeId = requireChangeID;
+        input.createNewChangeForAllNotInTarget = createNewChangeForAllNotInTarget;
         input.branches = branch;
         input.createEmptyCommit = createEmptyCommit;
         input.maxObjectSizeLimit = maxObjectSizeLimit;