@Override
    public PatchSet updateChangeImpl(ChangeContext ctx)
        throws NoSuchChangeException, ResourceConflictException, OrmException, IOException {
      if (rebaseOp == null) {
        // Took the fast-forward option, nothing to do.
        return null;
      }

      rebaseOp.updateChange(ctx);
      ctx.getChange()
          .setCurrentPatchSet(
              args.patchSetInfoFactory.get(args.rw, newCommit, rebaseOp.getPatchSetId()));
      newCommit.setControl(ctx.getControl());
      return rebaseOp.getPatchSet();
    }
    @Override
    public void updateRepoImpl(RepoContext ctx)
        throws IntegrationException, InvalidChangeOperationException, RestApiException, IOException,
            OrmException {
      // TODO(dborowitz): args.rw is needed because it's a CodeReviewRevWalk.
      // When hoisting BatchUpdate into MergeOp, we will need to teach
      // BatchUpdate how to produce CodeReviewRevWalks.
      if (args.mergeUtil.canFastForward(
          args.mergeSorter, args.mergeTip.getCurrentTip(), args.rw, toMerge)) {
        toMerge.setStatusCode(CommitMergeStatus.CLEAN_MERGE);
        args.mergeTip.moveTipTo(toMerge, toMerge);
        acceptMergeTip(args.mergeTip);
        return;
      }

      // Stale read of patch set is ok; see comments in RebaseChangeOp.
      PatchSet origPs =
          args.psUtil.get(ctx.getDb(), toMerge.getControl().getNotes(), toMerge.getPatchsetId());
      rebaseOp =
          args.rebaseFactory
              .create(toMerge.getControl(), origPs, args.mergeTip.getCurrentTip().name())
              .setRunHooks(false)
              // Bypass approval copier since SubmitStrategyOp copy all approvals
              // later anyway.
              .setCopyApprovals(false)
              .setValidatePolicy(CommitValidators.Policy.NONE);
      try {
        rebaseOp.updateRepo(ctx);
      } catch (MergeConflictException | NoSuchChangeException e) {
        toMerge.setStatusCode(CommitMergeStatus.REBASE_MERGE_CONFLICT);
        throw new IntegrationException(
            "Cannot rebase " + toMerge.name() + ": " + e.getMessage(), e);
      }
      newCommit = args.rw.parseCommit(rebaseOp.getRebasedCommit());
      newCommit.copyFrom(toMerge);
      newCommit.setStatusCode(CommitMergeStatus.CLEAN_REBASE);
      newCommit.setPatchsetId(rebaseOp.getPatchSetId());
      args.mergeTip.moveTipTo(newCommit, newCommit);
      args.commits.put(args.mergeTip.getCurrentTip());
      acceptMergeTip(args.mergeTip);
    }