Merge "Prefer creating new patch sets with previous patch set's committer email"
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index ce736c0..844f4c6 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -986,6 +986,10 @@
 MergePatchSetInput and add a new patch set to the change corresponding
 to the new merge commit.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the current patch set, the same email will be used as the committer email in the
+new patch set; otherwise, the user's preferred email will be used.
+
 .Request
 ----
   POST /changes/test~master~Ic5466d107c5294414710935a8ef3b0180fb848dc/merge  HTTP/1.0
@@ -1039,6 +1043,10 @@
 
 Creates a new patch set with a new commit message.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the current patch set, the same email will be used as the committer email in the
+new patch set; otherwise, the user's preferred email will be used.
+
 The new commit message must be provided in the request body inside a
 link:#commit-message-input[CommitMessageInput] entity. If a Change-Id
 footer is specified, it must match the current Change-Id footer. If
@@ -1314,6 +1322,10 @@
 
 Rebases a change.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the current patch set, the same email will be used as the committer email in the
+new patch set; otherwise, the user's preferred email will be used.
+
 Optionally, the parent revision can be changed to another patch set through the
 link:#rebase-input[RebaseInput] entity.
 
@@ -1440,6 +1452,10 @@
 
 Rebases an ancestry chain of changes.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the current patch set, the same email will be used as the committer email in the
+new patch set; otherwise, the user's preferred email will be used.
+
 The operated change is treated as the chain tip. All unsubmitted ancestors are rebased.
 
 Requires a linear ancestry relation (single parenting throughout the chain).
@@ -1919,6 +1935,11 @@
 
 Submits a change.
 
+If the submission results in a new patch set (due to a rebase or cherry-pick merge method), the
+committer email will remain the same as the one used in the previous commit, provided that one of
+the secondary emails associated with the user performing the operation was used as the committer
+email in the previous commit. Otherwise, the user's preferred email will be used.
+
 The request body only needs to include a link:#submit-input[
 SubmitInput] entity if submitting on behalf of another user.
 
@@ -2276,6 +2297,10 @@
 
 Creates a new patch set on a destination change from the provided patch.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the current patch set, the same email will be used as the committer email in the
+new patch set; otherwise, the user's preferred email will be used.
+
 The patch must be provided in the request body, inside a
 link:#applypatchpatchset-input[ApplyPatchPatchSetInput] entity.
 
@@ -3183,11 +3208,15 @@
 [[put-edit-file]]
 === Change file content in Change Edit
 --
-'PUT /changes/link:#change-id[\{change-id\}]/edit/path%2fto%2ffile
+'PUT /changes/link:#change-id[\{change-id\}]/edit/path%2fto%2ffile'
 --
 
 Put content of a file to a change edit.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the latest patch set, the same email will be used as the committer email in the
+new change edit commit; otherwise, the user's preferred email will be used.
+
 .Request
 ----
   PUT /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/edit/foo HTTP/1.0
@@ -3234,7 +3263,7 @@
 [[post-edit]]
 === Restore file content or rename files in Change Edit
 --
-'POST /changes/link:#change-id[\{change-id\}]/edit
+'POST /changes/link:#change-id[\{change-id\}]/edit'
 --
 
 Creates empty change edit, restores file content or renames files in change
@@ -3242,6 +3271,10 @@
 link:#change-edit-input[ChangeEditInput] entity when a file within change
 edit should be restored or old and new file names to rename a file.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the latest patch set, the same email will be used as the committer email in the
+new change edit commit; otherwise, the user's preferred email will be used.
+
 .Request
 ----
   POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/edit HTTP/1.0
@@ -3278,13 +3311,17 @@
 [[put-change-edit-message]]
 === Change commit message in Change Edit
 --
-'PUT /changes/link:#change-id[\{change-id\}]/edit:message
+'PUT /changes/link:#change-id[\{change-id\}]/edit:message'
 --
 
 Modify commit message. The request body needs to include a
 link:#change-edit-message-input[ChangeEditMessageInput]
 entity.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the latest patch set, the same email will be used as the committer email in the
+new change edit commit; otherwise, the user's preferred email will be used.
+
 .Request
 ----
   PUT /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/edit:message HTTP/1.0
@@ -3313,6 +3350,10 @@
 completely. This is not the same as reverting or restoring a file to its
 previous contents.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the latest patch set, the same email will be used as the committer email in the
+new change edit commit; otherwise, the user's preferred email will be used.
+
 .Request
 ----
   DELETE /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/edit/foo HTTP/1.0
@@ -3480,11 +3521,15 @@
 [[rebase-edit]]
 === Rebase Change Edit
 --
-'POST /changes/link:#change-id[\{change-id\}]/edit:rebase
+'POST /changes/link:#change-id[\{change-id\}]/edit:rebase'
 --
 
 Rebases change edit on top of latest patch set.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the latest patch set, the same email will be used as the committer email in the
+new change edit commit; otherwise, the user's preferred email will be used.
+
 .Request
 ----
   POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/edit:rebase HTTP/1.0
@@ -5594,6 +5639,10 @@
 exists and the fix refers to the current patch set, or the fix refers to the
 patch set on which the change edit is based.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the current patch set, the same email will be used as the committer email in the
+new change edit commit; otherwise, the user's preferred email will be used.
+
 .Request
 ----
   POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/revisions/674ac754f91e64a0efb8087e59a176484bd534d1/fixes/8f605a55_f6aa4ecc/apply HTTP/1.0
@@ -5660,6 +5709,10 @@
 application of the fixes creates a new change edit. `Apply Provided Fix` can only be applied on the current
 patchset.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the current patch set, the same email will be used as the committer email in the
+new change edit commit; otherwise, the user's preferred email will be used.
+
 .Request
 ----
   POST /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/revisions/674ac754f91e64a0efb8087e59a176484bd534d1/fix:apply HTTP/1.0
@@ -6315,6 +6368,10 @@
 
 Cherry picks a revision to a destination branch.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the original revision, the same email will be used as the committer email
+in the new patch set; otherwise, the user's preferred email will be used.
+
 To cherry pick a commit with no change-id associated with it, see
 link:rest-api-projects.html#cherry-pick-commit[CherryPickCommit].
 
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 528be41..73fac68 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -2667,6 +2667,10 @@
 
 Cherry-picks a commit of a project to a destination branch.
 
+If one of the secondary emails associated with the user performing the operation was used as the
+committer email in the original commit, the same email will be used as the committer email in the
+new patch set; otherwise, the user's preferred email will be used.
+
 To cherry pick a change revision, see link:rest-api-changes.html#cherry-pick[CherryPick].
 
 The destination branch must be provided in the request body inside a
diff --git a/java/com/google/gerrit/server/IdentifiedUser.java b/java/com/google/gerrit/server/IdentifiedUser.java
index 36d7888..d45d329 100644
--- a/java/com/google/gerrit/server/IdentifiedUser.java
+++ b/java/com/google/gerrit/server/IdentifiedUser.java
@@ -468,9 +468,7 @@
 
   public PersonIdent newCommitterIdent(Instant when, ZoneId zoneId) {
     final Account ua = getAccount();
-    String name = ua.fullName();
     String email = ua.preferredEmail();
-
     if (email == null || email.isEmpty()) {
       // No preferred email is configured. Use a generic identity so we
       // don't leak an address the user may have given us, but doesn't
@@ -491,19 +489,18 @@
 
       email = user + "@" + host;
     }
-
-    if (name == null || name.isEmpty()) {
-      final int at = email.indexOf('@');
-      if (0 < at) {
-        name = email.substring(0, at);
-      } else {
-        name = anonymousCowardName;
-      }
-    }
-
+    String name = getCommitterName(ua, email);
     return new PersonIdent(name, email, when, zoneId);
   }
 
+  public Optional<PersonIdent> newCommitterIdent(String email, Instant when, ZoneId zoneId) {
+    if (!hasEmailAddress(email)) {
+      return Optional.empty();
+    }
+    String name = getCommitterName(getAccount(), email);
+    return Optional.of(new PersonIdent(name, email, when, zoneId));
+  }
+
   @Override
   public String toString() {
     return "IdentifiedUser[account " + getAccountId() + "]";
@@ -551,4 +548,17 @@
   public boolean hasSameAccountId(CurrentUser other) {
     return getAccountId().get() == other.getAccountId().get();
   }
+
+  protected String getCommitterName(Account ua, String email) {
+    String name = ua.fullName();
+    if (name == null || name.isEmpty()) {
+      final int at = email.indexOf('@');
+      if (0 < at) {
+        name = email.substring(0, at);
+      } else {
+        name = anonymousCowardName;
+      }
+    }
+    return name;
+  }
 }
diff --git a/java/com/google/gerrit/server/change/RebaseChangeOp.java b/java/com/google/gerrit/server/change/RebaseChangeOp.java
index 540e438..f46196f 100644
--- a/java/com/google/gerrit/server/change/RebaseChangeOp.java
+++ b/java/com/google/gerrit/server/change/RebaseChangeOp.java
@@ -58,6 +58,7 @@
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import org.eclipse.jgit.diff.Sequence;
 import org.eclipse.jgit.dircache.DirCache;
 import org.eclipse.jgit.lib.CommitBuilder;
@@ -504,7 +505,11 @@
     if (committerIdent != null) {
       cb.setCommitter(committerIdent);
     } else {
-      cb.setCommitter(ctx.newCommitterIdent());
+      PersonIdent committerIdent =
+          Optional.ofNullable(original.getCommitterIdent())
+              .map(ident -> ctx.newCommitterIdent(ident.getEmailAddress(), ctx.getIdentifiedUser()))
+              .orElseGet(ctx::newCommitterIdent);
+      cb.setCommitter(committerIdent);
     }
     if (matchAuthorToCommitterDate) {
       cb.setAuthor(
diff --git a/java/com/google/gerrit/server/edit/ChangeEditModifier.java b/java/com/google/gerrit/server/edit/ChangeEditModifier.java
index 4c15a7e..68569f0 100644
--- a/java/com/google/gerrit/server/edit/ChangeEditModifier.java
+++ b/java/com/google/gerrit/server/edit/ChangeEditModifier.java
@@ -535,7 +535,7 @@
       builder.setTreeId(tree);
       builder.setParentIds(basePatchsetCommit.getParents());
       builder.setAuthor(basePatchsetCommit.getAuthorIdent());
-      builder.setCommitter(getCommitterIdent(timestamp));
+      builder.setCommitter(getCommitterIdent(basePatchsetCommit, timestamp));
       builder.setMessage(commitMessage);
       ObjectId newCommitId = objectInserter.insert(builder);
       objectInserter.flush();
@@ -543,9 +543,14 @@
     }
   }
 
-  private PersonIdent getCommitterIdent(Instant commitTimestamp) {
+  private PersonIdent getCommitterIdent(RevCommit basePatchsetCommit, Instant commitTimestamp) {
     IdentifiedUser user = currentUser.get().asIdentifiedUser();
-    return user.newCommitterIdent(commitTimestamp, zoneId);
+    return Optional.ofNullable(basePatchsetCommit.getCommitterIdent())
+        .map(
+            ident ->
+                user.newCommitterIdent(ident.getEmailAddress(), commitTimestamp, zoneId)
+                    .orElseGet(() -> user.newCommitterIdent(commitTimestamp, zoneId)))
+        .orElseGet(() -> user.newCommitterIdent(commitTimestamp, zoneId));
   }
 
   /**
diff --git a/java/com/google/gerrit/server/restapi/change/ApplyPatch.java b/java/com/google/gerrit/server/restapi/change/ApplyPatch.java
index 75eaacf..6adde99 100644
--- a/java/com/google/gerrit/server/restapi/change/ApplyPatch.java
+++ b/java/com/google/gerrit/server/restapi/change/ApplyPatch.java
@@ -65,6 +65,7 @@
 import java.time.Instant;
 import java.time.ZoneId;
 import java.util.List;
+import java.util.Optional;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.lib.ObjectId;
@@ -188,7 +189,14 @@
       ObjectId treeId = applyResult.getTreeId();
 
       Instant now = TimeUtil.now();
-      PersonIdent committerIdent = user.get().newCommitterIdent(now, serverZoneId);
+      PersonIdent committerIdent =
+          Optional.ofNullable(latestPatchset.getCommitterIdent())
+              .map(
+                  ident ->
+                      user.get()
+                          .newCommitterIdent(ident.getEmailAddress(), now, serverZoneId)
+                          .orElseGet(() -> user.get().newCommitterIdent(now, serverZoneId)))
+              .orElseGet(() -> user.get().newCommitterIdent(now, serverZoneId));
       PersonIdent authorIdent =
           input.author == null
               ? committerIdent
diff --git a/java/com/google/gerrit/server/restapi/change/CherryPickChange.java b/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
index 1bfb6bd..8b99e1c 100644
--- a/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
+++ b/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
@@ -74,6 +74,7 @@
 import java.time.ZoneId;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.ObjectId;
@@ -306,8 +307,15 @@
       CodeReviewCommit cherryPickCommit;
       ProjectState projectState =
           projectCache.get(dest.project()).orElseThrow(noSuchProject(dest.project()));
-      PersonIdent committerIdent = identifiedUser.newCommitterIdent(timestamp, serverZoneId);
-
+      PersonIdent committerIdent =
+          Optional.ofNullable(commitToCherryPick.getCommitterIdent())
+              .map(
+                  ident ->
+                      identifiedUser
+                          .newCommitterIdent(ident.getEmailAddress(), timestamp, serverZoneId)
+                          .orElseGet(
+                              () -> identifiedUser.newCommitterIdent(timestamp, serverZoneId)))
+              .orElseGet(() -> identifiedUser.newCommitterIdent(timestamp, serverZoneId));
       try {
         MergeUtil mergeUtil;
         if (input.allowConflicts) {
diff --git a/java/com/google/gerrit/server/restapi/change/CreateMergePatchSet.java b/java/com/google/gerrit/server/restapi/change/CreateMergePatchSet.java
index ff21916..989dc7a 100644
--- a/java/com/google/gerrit/server/restapi/change/CreateMergePatchSet.java
+++ b/java/com/google/gerrit/server/restapi/change/CreateMergePatchSet.java
@@ -74,6 +74,7 @@
 import java.time.Instant;
 import java.time.ZoneId;
 import java.util.List;
+import java.util.Optional;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.ObjectReader;
@@ -182,11 +183,18 @@
 
       Instant now = TimeUtil.now();
       IdentifiedUser me = user.get().asIdentifiedUser();
-      PersonIdent committer = me.newCommitterIdent(now, serverZoneId);
       PersonIdent author =
           in.author == null
-              ? committer
+              ? me.newCommitterIdent(now, serverZoneId)
               : new PersonIdent(in.author.name, in.author.email, now, serverZoneId);
+      RevCommit commit = rw.parseCommit(ps.commitId());
+      PersonIdent committer =
+          Optional.ofNullable(commit.getCommitterIdent())
+              .map(
+                  ident ->
+                      me.newCommitterIdent(ident.getEmailAddress(), now, serverZoneId)
+                          .orElseGet(() -> me.newCommitterIdent(now, serverZoneId)))
+              .orElseGet(() -> me.newCommitterIdent(now, serverZoneId));
       CodeReviewCommit newCommit =
           createMergeCommit(
               in,
diff --git a/java/com/google/gerrit/server/restapi/change/PutMessage.java b/java/com/google/gerrit/server/restapi/change/PutMessage.java
index 4eca1f3..3717e02 100644
--- a/java/com/google/gerrit/server/restapi/change/PutMessage.java
+++ b/java/com/google/gerrit/server/restapi/change/PutMessage.java
@@ -30,6 +30,7 @@
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.GerritPersonIdent;
+import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.PatchSetUtil;
 import com.google.gerrit.server.change.ChangeResource;
 import com.google.gerrit.server.change.NotifyResolver;
@@ -51,6 +52,7 @@
 import java.io.IOException;
 import java.time.Instant;
 import java.time.ZoneId;
+import java.util.Optional;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.CommitBuilder;
 import org.eclipse.jgit.lib.ObjectId;
@@ -175,8 +177,15 @@
     builder.setTreeId(basePatchSetCommit.getTree());
     builder.setParentIds(basePatchSetCommit.getParents());
     builder.setAuthor(basePatchSetCommit.getAuthorIdent());
-    builder.setCommitter(
-        userProvider.get().asIdentifiedUser().newCommitterIdent(timestamp, zoneId));
+    IdentifiedUser user = userProvider.get().asIdentifiedUser();
+    PersonIdent committer =
+        Optional.ofNullable(basePatchSetCommit.getCommitterIdent())
+            .map(
+                ident ->
+                    user.newCommitterIdent(ident.getEmailAddress(), timestamp, zoneId)
+                        .orElseGet(() -> user.newCommitterIdent(timestamp, zoneId)))
+            .orElseGet(() -> user.newCommitterIdent(timestamp, zoneId));
+    builder.setCommitter(committer);
     builder.setMessage(commitMessage);
     ObjectId newCommitId = objectInserter.insert(builder);
     objectInserter.flush();
diff --git a/java/com/google/gerrit/server/submit/CherryPick.java b/java/com/google/gerrit/server/submit/CherryPick.java
index 0471b67..7fe5e69 100644
--- a/java/com/google/gerrit/server/submit/CherryPick.java
+++ b/java/com/google/gerrit/server/submit/CherryPick.java
@@ -34,6 +34,7 @@
 import java.io.IOException;
 import java.util.Collection;
 import java.util.List;
+import java.util.Optional;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.revwalk.RevCommit;
@@ -102,8 +103,10 @@
       RevCommit mergeTip = args.mergeTip.getCurrentTip();
       args.rw.parseBody(mergeTip);
       String cherryPickCmtMsg = args.mergeUtil.createCommitMessageOnSubmit(toMerge, mergeTip);
-
-      PersonIdent committer = ctx.newCommitterIdent(args.caller);
+      PersonIdent committer =
+          Optional.ofNullable(toMerge.getCommitterIdent())
+              .map(ident -> ctx.newCommitterIdent(ident.getEmailAddress(), args.caller))
+              .orElseGet(() -> ctx.newCommitterIdent(args.caller));
       try {
         newCommit =
             args.mergeUtil.createCherryPickFromCommit(
diff --git a/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java b/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
index 5f58a74..87de810 100644
--- a/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
+++ b/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
@@ -41,6 +41,7 @@
 import java.io.IOException;
 import java.util.Collection;
 import java.util.List;
+import java.util.Optional;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
@@ -167,7 +168,10 @@
         RevCommit mergeTip = args.mergeTip.getCurrentTip();
         args.rw.parseBody(mergeTip);
         String cherryPickCmtMsg = args.mergeUtil.createCommitMessageOnSubmit(toMerge, mergeTip);
-        PersonIdent committer = ctx.newCommitterIdent(args.caller);
+        PersonIdent committer =
+            Optional.ofNullable(toMerge.getCommitterIdent())
+                .map(ident -> ctx.newCommitterIdent(ident.getEmailAddress(), args.caller))
+                .orElseGet(() -> ctx.newCommitterIdent(args.caller));
         try {
           newCommit =
               args.mergeUtil.createCherryPickFromCommit(
diff --git a/java/com/google/gerrit/server/update/Context.java b/java/com/google/gerrit/server/update/Context.java
index aa41d90..4e5d73f 100644
--- a/java/com/google/gerrit/server/update/Context.java
+++ b/java/com/google/gerrit/server/update/Context.java
@@ -164,4 +164,16 @@
   default PersonIdent newCommitterIdent(IdentifiedUser user) {
     return user.newCommitterIdent(getWhen(), getZoneId());
   }
+
+  /**
+   * Creates a committer {@link PersonIdent} for the given user. The identity will be created with
+   * the given email if the user is allowed to use it, otherwise fallback to preferred email.
+   *
+   * @param user user for which a committer {@link PersonIdent} should be created
+   * @param email committer email of the source commit
+   * @return the created committer {@link PersonIdent}
+   */
+  default PersonIdent newCommitterIdent(String email, IdentifiedUser user) {
+    return user.newCommitterIdent(email, getWhen(), getZoneId()).orElseGet(this::newCommitterIdent);
+  }
 }
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ApplyPatchIT.java b/javatests/com/google/gerrit/acceptance/api/change/ApplyPatchIT.java
index b1cc866..d8c2aae 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ApplyPatchIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ApplyPatchIT.java
@@ -113,7 +113,7 @@
     in.responseFormatOptions = ImmutableList.of(CURRENT_REVISION, CURRENT_COMMIT);
     ChangeInfo result = gApi.changes().id(change.get()).applyPatch(in);
 
-    assertThat(result.getCurrentRevision().commit.committer.email).isEqualTo(emailTwo);
+    assertThat(result.getCurrentRevision().commit.committer.email).isEqualTo(emailOne);
   }
 
   private static final String MODIFIED_FILE_NAME = "modified_file.txt";
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index 97ec978..c920843 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -3920,7 +3920,7 @@
     gApi.changes().id(change.get()).setMessage(msg);
 
     assertThat(gApi.changes().id(change.get()).get().getCurrentRevision().commit.committer.email)
-        .isEqualTo(emailTwo);
+        .isEqualTo(emailOne);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/change/CreateMergePatchSetIT.java b/javatests/com/google/gerrit/acceptance/api/change/CreateMergePatchSetIT.java
index 771935a..502f286 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/CreateMergePatchSetIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/CreateMergePatchSetIT.java
@@ -188,7 +188,7 @@
     gApi.changes().id(change.get()).createMergePatchSet(in);
 
     assertThat(gApi.changes().id(change.get()).get().getCurrentRevision().commit.committer.email)
-        .isEqualTo(emailTwo);
+        .isEqualTo(emailOne);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/change/RebaseChainOnBehalfOfUploaderIT.java b/javatests/com/google/gerrit/acceptance/api/change/RebaseChainOnBehalfOfUploaderIT.java
index 7fe79e4..7d1ddfc 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/RebaseChainOnBehalfOfUploaderIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/RebaseChainOnBehalfOfUploaderIT.java
@@ -257,7 +257,7 @@
                 .commit
                 .committer
                 .email)
-        .isEqualTo(uploaderEmailTwo);
+        .isEqualTo(uploaderEmailOne);
     assertThat(
             gApi.changes()
                 .id(changeToBeRebased2.get())
@@ -266,7 +266,7 @@
                 .commit
                 .committer
                 .email)
-        .isEqualTo(uploaderEmailTwo);
+        .isEqualTo(uploaderEmailOne);
     assertThat(
             gApi.changes()
                 .id(changeToBeRebased3.get())
@@ -275,7 +275,7 @@
                 .commit
                 .committer
                 .email)
-        .isEqualTo(uploaderEmailTwo);
+        .isEqualTo(uploaderEmailOne);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java b/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java
index 152d9dd..d9b079a 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/RebaseIT.java
@@ -237,7 +237,7 @@
       // Rebase the second change
       gApi.changes().id(c2.get()).rebase();
       assertThat(gApi.changes().id(c2.get()).get().getCurrentRevision().commit.committer.email)
-          .isEqualTo(emailTwo);
+          .isEqualTo(emailOne);
     }
 
     @Test
@@ -461,6 +461,12 @@
       String changeId = r2.getChangeId();
       requestScopeOperations.setApiUser(user.id());
       rebaseCall.call(changeId);
+
+      // Verify that the committer has been updated
+      GitPerson committer =
+          gApi.changes().id(r2.getChangeId()).get().getCurrentRevision().commit.committer;
+      assertThat(committer.name).isEqualTo(user.fullName());
+      assertThat(committer.email).isEqualTo(user.email());
     }
 
     @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/change/RebaseOnBehalfOfUploaderIT.java b/javatests/com/google/gerrit/acceptance/api/change/RebaseOnBehalfOfUploaderIT.java
index 3456012..968c1f7 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/RebaseOnBehalfOfUploaderIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/RebaseOnBehalfOfUploaderIT.java
@@ -282,7 +282,7 @@
                 .commit
                 .committer
                 .email)
-        .isEqualTo(uploaderEmailTwo);
+        .isEqualTo(uploaderEmailOne);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/project/CommitIT.java b/javatests/com/google/gerrit/acceptance/api/project/CommitIT.java
index e4dc0e83..84a4a40 100644
--- a/javatests/com/google/gerrit/acceptance/api/project/CommitIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/project/CommitIT.java
@@ -228,7 +228,7 @@
     input.message = "cherry-pick to foo branch";
     ChangeInfo cherryPickResult =
         gApi.projects().name(project.get()).commit(commit).cherryPick(input).get();
-    assertThat(cherryPickResult.getCurrentRevision().commit.committer.email).isEqualTo(emailTwo);
+    assertThat(cherryPickResult.getCurrentRevision().commit.committer.email).isEqualTo(emailOne);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/ApplyProvidedFixIT.java b/javatests/com/google/gerrit/acceptance/api/revision/ApplyProvidedFixIT.java
index fa4f568..b9ef0bf 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/ApplyProvidedFixIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/ApplyProvidedFixIT.java
@@ -128,7 +128,7 @@
     gApi.changes().id(change.get()).current().applyFix(applyProvidedFixInput);
 
     EditInfo editInfo = gApi.changes().id(change.get()).edit().get().orElseThrow();
-    assertThat(editInfo.commit.committer.email).isEqualTo(emailTwo);
+    assertThat(editInfo.commit.committer.email).isEqualTo(emailOne);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
index cdcd044..b3db99f 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
@@ -385,7 +385,7 @@
     input.message = "cherry-pick to foo branch";
     ChangeInfo changeInfo =
         gApi.changes().id(changeId.get()).revision(commit).cherryPick(input).get();
-    assertThat(changeInfo.getCurrentRevision().commit.committer.email).isEqualTo(emailTwo);
+    assertThat(changeInfo.getCurrentRevision().commit.committer.email).isEqualTo(emailOne);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
index 1ab74fb..b31d35c 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
@@ -796,7 +796,7 @@
     gApi.changes().id(change.get()).current().applyFix(fixId);
 
     EditInfo editInfo = gApi.changes().id(change.get()).edit().get().orElseThrow();
-    assertThat(editInfo.commit.committer.email).isEqualTo(emailTwo);
+    assertThat(editInfo.commit.committer.email).isEqualTo(emailOne);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java b/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
index 6bff0be..9c691ae 100644
--- a/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
+++ b/javatests/com/google/gerrit/acceptance/edit/ChangeEditIT.java
@@ -291,7 +291,7 @@
     gApi.changes().id(change.get()).edit().rebase();
 
     EditInfo editInfo = gApi.changes().id(change.get()).edit().get().orElseThrow();
-    assertThat(editInfo.commit.committer.email).isEqualTo(emailTwo);
+    assertThat(editInfo.commit.committer.email).isEqualTo(emailOne);
   }
 
   @Test
@@ -365,7 +365,7 @@
     gApi.changes().id(change.get()).edit().modifyFile(FILE_NAME, RawInputUtil.create(CONTENT_NEW));
 
     EditInfo editInfo = gApi.changes().id(change.get()).edit().get().orElseThrow();
-    assertThat(editInfo.commit.committer.email).isEqualTo(emailTwo);
+    assertThat(editInfo.commit.committer.email).isEqualTo(emailOne);
   }
 
   @Test
@@ -530,7 +530,7 @@
     gApi.changes().id(change.get()).edit().modifyCommitMessage(msg);
 
     EditInfo editInfo = gApi.changes().id(change.get()).edit().get().orElseThrow();
-    assertThat(editInfo.commit.committer.email).isEqualTo(emailTwo);
+    assertThat(editInfo.commit.committer.email).isEqualTo(emailOne);
   }
 
   @Test
@@ -703,7 +703,7 @@
     gApi.changes().id(change.get()).edit().deleteFile(FILE_NAME);
 
     EditInfo editInfo = gApi.changes().id(change.get()).edit().get().orElseThrow();
-    assertThat(editInfo.commit.committer.email).isEqualTo(emailTwo);
+    assertThat(editInfo.commit.committer.email).isEqualTo(emailOne);
   }
 
   @Test
@@ -738,7 +738,7 @@
     gApi.changes().id(change.get()).edit().renameFile(FILE_NAME, FILE_NAME3);
 
     EditInfo editInfo = gApi.changes().id(change.get()).edit().get().orElseThrow();
-    assertThat(editInfo.commit.committer.email).isEqualTo(emailTwo);
+    assertThat(editInfo.commit.committer.email).isEqualTo(emailOne);
   }
 
   @Test
@@ -800,7 +800,7 @@
     gApi.changes().id(change.get()).edit().restoreFile(FILE_NAME);
 
     EditInfo editInfo = gApi.changes().id(change.get()).edit().get().orElseThrow();
-    assertThat(editInfo.commit.committer.email).isEqualTo(emailTwo);
+    assertThat(editInfo.commit.committer.email).isEqualTo(emailOne);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java
index 73e0d17..37684de 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java
@@ -144,7 +144,7 @@
     revision.review(ReviewInput.approve());
     revision.submit();
     assertThat(gApi.changes().id(changeId.get()).get().getCurrentRevision().commit.committer.email)
-        .isEqualTo(emailTwo);
+        .isEqualTo(emailOne);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByRebaseAlwaysIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByRebaseAlwaysIT.java
index a03a5b5..80fbe99 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByRebaseAlwaysIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByRebaseAlwaysIT.java
@@ -146,7 +146,7 @@
     revision.review(ReviewInput.approve());
     revision.submit();
     assertThat(gApi.changes().id(changeId.get()).get().getCurrentRevision().commit.committer.email)
-        .isEqualTo(emailTwo);
+        .isEqualTo(emailOne);
   }
 
   @Test