diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md
index e7516bd06463d38918f45b79d1992c6ef4618431..750e96b8d98c0b1a7bf96ae02f72943924c1e77b 100644
--- a/docs/usage/configuration-options.md
+++ b/docs/usage/configuration-options.md
@@ -173,6 +173,25 @@ Example use:
 }
 ```
 
+## automergeStrategy
+
+This setting is only applicable if you opt-in by configuring `automerge` to `true` and `automergeType` to `pr` for any of your dependencies.
+
+The automerge strategy defaults to `auto`, in which Renovate will make its best guess as to how to merge pull requests.
+This generally results in Renovate respecting the strategy configured in the platform itself for the repository if possible.
+Acceptable values are:
+
+- `auto`, in which the choice is left to Renovate
+- `fast-forward`, which generally involves no new commits in the resultant tree, but "fast-forwarding" the main branch reference
+- `merge-commit`, which generally involves synthesizing a new merge commit
+- `rebase`, which generally involves rewriting history as part of the merge — but usually retaining the individual commits
+- `squash`, which generally involves flattening the commits that are being merged into a single new commit
+
+Not all platforms support all pull request merge strategies.
+In cases where a merge strategy is not supported by the platform, Renovate will hold off on merging instead of silently merging in a way you didn't wish for.
+
+The only platform that supports `automergeStrategy` is Bitbucket Cloud.
+
 ## automergeType
 
 This setting is only applicable if you opt in to configure `automerge` to `true` for any of your dependencies.
diff --git a/lib/config/definitions.ts b/lib/config/definitions.ts
index 2c232094fd336ca26fce7316e7041f39ef7b27b8..26290fa07ebea77a0bdc85188b47bedf3cec170c 100644
--- a/lib/config/definitions.ts
+++ b/lib/config/definitions.ts
@@ -1285,6 +1285,14 @@ const options: RenovateOptions[] = [
     allowedValues: ['branch', 'pr', 'pr-comment'],
     default: 'pr',
   },
+  {
+    name: 'automergeStrategy',
+    description:
+      'The merge strategy to use when automerging PRs. Used only if `automergeType=pr`.',
+    type: 'string',
+    allowedValues: ['auto', 'fast-forward', 'merge-commit', 'rebase', 'squash'],
+    default: 'auto',
+  },
   {
     name: 'automergeComment',
     description:
diff --git a/lib/config/types.ts b/lib/config/types.ts
index 3fa1a645c2a7c7125b0ace70110022546993cc67..fdd56479c4d8e20690d8e4206d8f2cbad9f6619e 100644
--- a/lib/config/types.ts
+++ b/lib/config/types.ts
@@ -21,6 +21,7 @@ export interface GroupConfig extends Record<string, unknown> {
 export interface RenovateSharedConfig {
   $schema?: string;
   automerge?: boolean;
+  automergeStrategy?: MergeStrategy;
   branchPrefix?: string;
   branchName?: string;
   manager?: string;
@@ -229,6 +230,13 @@ export type UpdateType =
 
 export type MatchStringsStrategy = 'any' | 'recursive' | 'combination';
 
+export type MergeStrategy =
+  | 'auto'
+  | 'fast-forward'
+  | 'merge-commit'
+  | 'rebase'
+  | 'squash';
+
 // TODO: Proper typings
 export interface PackageRule
   extends RenovateSharedConfig,
diff --git a/lib/platform/azure/index.md b/lib/platform/azure/index.md
new file mode 100644
index 0000000000000000000000000000000000000000..d8fadac49eb1b228f35e1c16650096f56633bf32
--- /dev/null
+++ b/lib/platform/azure/index.md
@@ -0,0 +1,5 @@
+# Azure DevOps and Azure DevOps Server
+
+## Features awaiting implementation
+
+- The `automergeStrategy` configuration option has not been implemented for this platform, and all values behave as if the value `auto` was used. Renovate will use the merge strategy configured in the Azure Repos repository itself, and this cannot be overridden yet
diff --git a/lib/platform/bitbucket-server/index.md b/lib/platform/bitbucket-server/index.md
index d5ef66a96a7c305334651f318be689b07eb5a445..6937275b2f24ecd3d3780d9616433f996c5fdc7a 100644
--- a/lib/platform/bitbucket-server/index.md
+++ b/lib/platform/bitbucket-server/index.md
@@ -8,6 +8,7 @@
 ## Features awaiting implementation
 
 - Creating issues not implemented yet, used to alert users when there is a config error
+- The `automergeStrategy` configuration option has not been implemented for this platform, and all values behave as if the value `auto` was used. Renovate will implicitly use the merge strategy configured as 'default' in the Bitbucket Server repository itself, and this cannot be overridden yet
 
 ## Testing
 
diff --git a/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap b/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap
index 1bcedd7cb3fc3e7b556a9245bd57579aab4c1270..041ab86b614530613c0ceae6e96f1e40aeeec370 100644
--- a/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap
+++ b/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap
@@ -1254,7 +1254,7 @@ Array [
 
 exports[`platform/bitbucket/index massageMarkdown() returns diff files 1`] = `"**foo**bartext"`;
 
-exports[`platform/bitbucket/index mergePr() posts Merge 1`] = `
+exports[`platform/bitbucket/index mergePr() posts Merge with auto 1`] = `
 Array [
   Object {
     "headers": Object {
@@ -1268,7 +1268,67 @@ Array [
     "url": "https://api.bitbucket.org/2.0/repositories/some/repo",
   },
   Object {
-    "body": "{\\"close_source_branch\\":true,\\"merge_strategy\\":\\"merge_commit\\",\\"message\\":\\"auto merged\\"}",
+    "body": "{\\"close_source_branch\\":true,\\"message\\":\\"auto merged\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Basic YWJjOjEyMw==",
+      "content-length": "52",
+      "content-type": "application/json",
+      "host": "api.bitbucket.org",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "POST",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo/pullrequests/5/merge",
+  },
+]
+`;
+
+exports[`platform/bitbucket/index mergePr() posts Merge with fast-forward 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "api.bitbucket.org",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "GET",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo",
+  },
+  Object {
+    "body": "{\\"close_source_branch\\":true,\\"message\\":\\"auto merged\\",\\"merge_strategy\\":\\"fast_forward\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Basic YWJjOjEyMw==",
+      "content-length": "84",
+      "content-type": "application/json",
+      "host": "api.bitbucket.org",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "POST",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo/pullrequests/5/merge",
+  },
+]
+`;
+
+exports[`platform/bitbucket/index mergePr() posts Merge with merge-commit 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "api.bitbucket.org",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "GET",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo",
+  },
+  Object {
+    "body": "{\\"close_source_branch\\":true,\\"message\\":\\"auto merged\\",\\"merge_strategy\\":\\"merge_commit\\"}",
     "headers": Object {
       "accept": "application/json",
       "accept-encoding": "gzip, deflate, br",
@@ -1284,6 +1344,66 @@ Array [
 ]
 `;
 
+exports[`platform/bitbucket/index mergePr() posts Merge with optional merge strategy 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "api.bitbucket.org",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "GET",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo",
+  },
+  Object {
+    "body": "{\\"close_source_branch\\":true,\\"message\\":\\"auto merged\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Basic YWJjOjEyMw==",
+      "content-length": "52",
+      "content-type": "application/json",
+      "host": "api.bitbucket.org",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "POST",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo/pullrequests/5/merge",
+  },
+]
+`;
+
+exports[`platform/bitbucket/index mergePr() posts Merge with squash 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "api.bitbucket.org",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "GET",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo",
+  },
+  Object {
+    "body": "{\\"close_source_branch\\":true,\\"message\\":\\"auto merged\\",\\"merge_strategy\\":\\"squash\\"}",
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Basic YWJjOjEyMw==",
+      "content-length": "78",
+      "content-type": "application/json",
+      "host": "api.bitbucket.org",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "POST",
+    "url": "https://api.bitbucket.org/2.0/repositories/some/repo/pullrequests/5/merge",
+  },
+]
+`;
+
 exports[`platform/bitbucket/index setBranchStatus() posts status 1`] = `
 Array [
   Object {
diff --git a/lib/platform/bitbucket/index.md b/lib/platform/bitbucket/index.md
index 1f77fc5d65730fec9064365d89e6d464f5c6734c..5655abc9c04c8aae97e4b260734d1cd6b532c7e1 100644
--- a/lib/platform/bitbucket/index.md
+++ b/lib/platform/bitbucket/index.md
@@ -3,6 +3,7 @@
 ## Unsupported platform features/concepts
 
 - Adding assignees to PRs not supported (does not seem to be a Bitbucket concept)
+- `automergeStrategy=rebase` not supported by BitBucket Cloud, see [Jira issue BCLOUD-16610](https://jira.atlassian.com/browse/BCLOUD-16610)
 
 ## Features requiring implementation
 
diff --git a/lib/platform/bitbucket/index.spec.ts b/lib/platform/bitbucket/index.spec.ts
index 435bb242782ea9a1154820ab9455c1cbcd19b6c4..1959e1f1fe328181cc309168bad22ec3823c4cf9 100644
--- a/lib/platform/bitbucket/index.spec.ts
+++ b/lib/platform/bitbucket/index.spec.ts
@@ -812,12 +812,45 @@ describe(getName(), () => {
   });
 
   describe('mergePr()', () => {
-    it('posts Merge', async () => {
+    it('posts Merge with optional merge strategy', async () => {
       const scope = await initRepoMock();
       scope.post('/2.0/repositories/some/repo/pullrequests/5/merge').reply(200);
       await bitbucket.mergePr(5, 'branch');
       expect(httpMock.getTrace()).toMatchSnapshot();
     });
+
+    it('posts Merge with auto', async () => {
+      const scope = await initRepoMock();
+      scope.post('/2.0/repositories/some/repo/pullrequests/5/merge').reply(200);
+      await bitbucket.mergePr(5, 'branch', 'auto');
+      expect(httpMock.getTrace()).toMatchSnapshot();
+    });
+
+    it('posts Merge with merge-commit', async () => {
+      const scope = await initRepoMock();
+      scope.post('/2.0/repositories/some/repo/pullrequests/5/merge').reply(200);
+      await bitbucket.mergePr(5, 'branch', 'merge-commit');
+      expect(httpMock.getTrace()).toMatchSnapshot();
+    });
+
+    it('posts Merge with squash', async () => {
+      const scope = await initRepoMock();
+      scope.post('/2.0/repositories/some/repo/pullrequests/5/merge').reply(200);
+      await bitbucket.mergePr(5, 'branch', 'squash');
+      expect(httpMock.getTrace()).toMatchSnapshot();
+    });
+
+    it('does not post Merge with rebase', async () => {
+      await bitbucket.mergePr(5, 'branch', 'rebase');
+      expect(httpMock.getTrace()).toEqual([]);
+    });
+
+    it('posts Merge with fast-forward', async () => {
+      const scope = await initRepoMock();
+      scope.post('/2.0/repositories/some/repo/pullrequests/5/merge').reply(200);
+      await bitbucket.mergePr(5, 'branch', 'fast-forward');
+      expect(httpMock.getTrace()).toMatchSnapshot();
+    });
   });
 
   describe('getVulnerabilityAlerts()', () => {
diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts
index 972da032e2de1d760f283ea00156a74ba9286539..5699528b541d318fece09114a93edd32817c79cf 100644
--- a/lib/platform/bitbucket/index.ts
+++ b/lib/platform/bitbucket/index.ts
@@ -1,6 +1,7 @@
 import URL from 'url';
 import is from '@sindresorhus/is';
 import parseDiff from 'parse-diff';
+import type { MergeStrategy } from '../../config/types';
 import { REPOSITORY_NOT_FOUND } from '../../constants/error-messages';
 import { PLATFORM_TYPE_BITBUCKET } from '../../constants/platforms';
 import { logger } from '../../logger';
@@ -29,7 +30,7 @@ import { smartTruncate } from '../utils/pr-body';
 import { readOnlyIssueBody } from '../utils/read-only-issue-body';
 import * as comments from './comments';
 import * as utils from './utils';
-import { PrResponse, RepoInfoBody } from './utils';
+import { PrResponse, RepoInfoBody, mergeBodyTransformer } from './utils';
 
 const bitbucketHttp = new BitbucketHttp();
 
@@ -391,7 +392,7 @@ export async function setBranchStatus({
   const sha = await getBranchCommit(branchName);
 
   // TargetUrl can not be empty so default to bitbucket
-  const url = targetUrl || /* istanbul ignore next */ 'http://bitbucket.org';
+  const url = targetUrl || /* istanbul ignore next */ 'https://bitbucket.org';
 
   const body = {
     name: context,
@@ -748,19 +749,22 @@ export async function updatePr({
 
 export async function mergePr(
   prNo: number,
-  branchName: string
+  branchName: string,
+  mergeStrategy: MergeStrategy
 ): Promise<boolean> {
-  logger.debug(`mergePr(${prNo}, ${branchName})`);
+  logger.debug(`mergePr(${prNo}, ${branchName}, ${mergeStrategy})`);
+
+  // Bitbucket Cloud does not support a rebase-alike; https://jira.atlassian.com/browse/BCLOUD-16610
+  if (mergeStrategy === 'rebase') {
+    logger.warn('Bitbucket Cloud does not support a "rebase" strategy.');
+    return false;
+  }
 
   try {
     await bitbucketHttp.postJson(
       `/2.0/repositories/${config.repository}/pullrequests/${prNo}/merge`,
       {
-        body: {
-          close_source_branch: true,
-          merge_strategy: 'merge_commit',
-          message: 'auto merged',
-        },
+        body: mergeBodyTransformer(mergeStrategy),
       }
     );
     logger.debug('Automerging succeeded');
diff --git a/lib/platform/bitbucket/types.ts b/lib/platform/bitbucket/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9e3bb0c16788ee83c499d8d7c7cce92bd55224f6
--- /dev/null
+++ b/lib/platform/bitbucket/types.ts
@@ -0,0 +1,7 @@
+export type BitbucketMergeStrategy = 'fast_forward' | 'merge_commit' | 'squash';
+
+export interface MergeRequestBody {
+  close_source_branch?: boolean;
+  message: string;
+  merge_strategy?: BitbucketMergeStrategy;
+}
diff --git a/lib/platform/bitbucket/utils.ts b/lib/platform/bitbucket/utils.ts
index 1f7c07f65d2d66d460371c425076072f05ed1904..c20b2ec28c92395aba71a713abf66521ab9e9e61 100644
--- a/lib/platform/bitbucket/utils.ts
+++ b/lib/platform/bitbucket/utils.ts
@@ -1,8 +1,10 @@
 import url from 'url';
+import type { MergeStrategy } from '../../config/types';
 import { BranchStatus, PrState } from '../../types';
 import { HttpOptions, HttpPostOptions, HttpResponse } from '../../util/http';
 import { BitbucketHttp } from '../../util/http/bitbucket';
 import type { Pr } from '../types';
+import type { BitbucketMergeStrategy, MergeRequestBody } from './types';
 
 const bitbucketHttp = new BitbucketHttp();
 
@@ -56,6 +58,29 @@ export function repoInfoTransformer(repoInfoBody: RepoInfoBody): RepoInfo {
   };
 }
 
+const bitbucketMergeStrategies: Map<MergeStrategy, BitbucketMergeStrategy> =
+  new Map([
+    ['squash', 'squash'],
+    ['merge-commit', 'merge_commit'],
+    ['fast-forward', 'fast_forward'],
+  ]);
+
+export function mergeBodyTransformer(
+  mergeStrategy: MergeStrategy
+): MergeRequestBody {
+  const body: MergeRequestBody = {
+    close_source_branch: true,
+    message: 'auto merged',
+  };
+
+  // The `auto` strategy will use the strategy configured inside Bitbucket.
+  if (mergeStrategy !== 'auto') {
+    body.merge_strategy = bitbucketMergeStrategies.get(mergeStrategy);
+  }
+
+  return body;
+}
+
 export const prStates = {
   open: ['OPEN'],
   notOpen: ['MERGED', 'DECLINED', 'SUPERSEDED'],
diff --git a/lib/platform/gitea/index.md b/lib/platform/gitea/index.md
index e9cd63ea62fa71a9549f4dcbc2c3a7176f95e55f..3a45af107fe621d86a726c42685f9963c6bc3668 100644
--- a/lib/platform/gitea/index.md
+++ b/lib/platform/gitea/index.md
@@ -3,3 +3,7 @@
 ## Unsupported platform features/concepts
 
 - **Adding reviewers to PRs not supported**: Gitea versions older than v1.14.0 do not have the required API.
+
+## Features awaiting implementation
+
+- The `automergeStrategy` configuration option has not been implemented for this platform, and all values behave as if the value `auto` was used. Renovate will use the merge strategy configured in the Gitea repository itself, and this cannot be overridden yet
diff --git a/lib/platform/github/index.md b/lib/platform/github/index.md
new file mode 100644
index 0000000000000000000000000000000000000000..b0f378dba227aa8ad1592c54cdebb067b7a2771d
--- /dev/null
+++ b/lib/platform/github/index.md
@@ -0,0 +1,5 @@
+# GitHub and GitHub Enterprise
+
+## Features awaiting implementation
+
+- The `automergeStrategy` configuration option has not been implemented for this platform, and all values behave as if the value `auto` was used. Renovate will use the merge strategy configured in the GitHub repository itself, and this cannot be overridden yet
diff --git a/lib/platform/gitlab/index.md b/lib/platform/gitlab/index.md
new file mode 100644
index 0000000000000000000000000000000000000000..cd05a459cd99dc72bb608a49677b89cf08222be3
--- /dev/null
+++ b/lib/platform/gitlab/index.md
@@ -0,0 +1,5 @@
+# GitLab
+
+## Features awaiting implementation
+
+- The `automergeStrategy` configuration option has not been implemented for this platform, and all values behave as if the value `auto` was used. Renovate will accept the Merge Request without further configuration, and respect the strategy defined in the Merge Request, and this cannot be overridden yet
diff --git a/lib/platform/types.ts b/lib/platform/types.ts
index 150e6d1818e40636dfd06a23f5bd76ff9382037d..121245f42f8b7330a1a81f706885086c6fe407a7 100644
--- a/lib/platform/types.ts
+++ b/lib/platform/types.ts
@@ -1,3 +1,4 @@
+import type { MergeStrategy } from '../config/types';
 import type { BranchStatus, PrState, VulnerabilityAlert } from '../types';
 
 type VulnerabilityKey = string;
@@ -152,7 +153,11 @@ export interface Platform {
   ): Promise<EnsureIssueResult | null>;
   massageMarkdown(prBody: string): string;
   updatePr(prConfig: UpdatePrConfig): Promise<void>;
-  mergePr(number: number, branchName: string): Promise<boolean>;
+  mergePr(
+    number: number,
+    branchName: string,
+    mergeStrategy?: MergeStrategy
+  ): Promise<boolean>;
   addReviewers(number: number, reviewers: string[]): Promise<void>;
   addAssignees(number: number, assignees: string[]): Promise<void>;
   createPr(prConfig: CreatePRConfig): Promise<Pr>;
diff --git a/lib/workers/pr/automerge.ts b/lib/workers/pr/automerge.ts
index d3d86a4ef0f3cc121d5412aebcd292892e6349b4..b1c5af8fc132955afe248d1ed24c46cab62cac52 100644
--- a/lib/workers/pr/automerge.ts
+++ b/lib/workers/pr/automerge.ts
@@ -28,6 +28,7 @@ export async function checkAutoMerge(
   const {
     branchName,
     automergeType,
+    automergeStrategy,
     automergeComment,
     requiredStatusChecks,
     rebaseRequested,
@@ -99,14 +100,16 @@ export async function checkAutoMerge(
   // Let's merge this
   // istanbul ignore if
   if (getAdminConfig().dryRun) {
-    logger.info(`DRY-RUN: Would merge PR #${pr.number}`);
+    logger.info(
+      `DRY-RUN: Would merge PR #${pr.number} with strategy "${automergeStrategy}"`
+    );
     return {
       automerged: false,
       prAutomergeBlockReason: PrAutomergeBlockReason.DryRun,
     };
   }
-  logger.debug(`Automerging #${pr.number}`);
-  const res = await platform.mergePr(pr.number, branchName);
+  logger.debug(`Automerging #${pr.number} with strategy ${automergeStrategy}`);
+  const res = await platform.mergePr(pr.number, branchName, automergeStrategy);
   if (res) {
     logger.info({ pr: pr.number, prTitle: pr.title }, 'PR automerged');
     let branchRemoved = false;