diff --git a/lib/config/__snapshots__/migration.spec.ts.snap b/lib/config/__snapshots__/migration.spec.ts.snap
index 56fcc4411705dee76aa2571fc6ab0c7fee3eb0bc..3f435e0a8d20768679fff0e6b75e55f122bc3235 100644
--- a/lib/config/__snapshots__/migration.spec.ts.snap
+++ b/lib/config/__snapshots__/migration.spec.ts.snap
@@ -199,6 +199,15 @@ Object {
       "respectLatest": false,
       "schedule": "before 5am on Monday",
     },
+    Object {
+      "automerge": true,
+      "matchDepTypes": Array [
+        "bar",
+      ],
+      "matchPackageNames": Array [
+        "foo",
+      ],
+    },
   ],
   "patch": Object {
     "automerge": true,
diff --git a/lib/config/migration.spec.ts b/lib/config/migration.spec.ts
index 176aade6904eebd3516c885a578c7723c55c141d..ba28db45b97da7269c68a65053b75476a04173f6 100644
--- a/lib/config/migration.spec.ts
+++ b/lib/config/migration.spec.ts
@@ -104,6 +104,15 @@ describe('config/migration', () => {
             packageNames: ['guava'],
             versionScheme: 'maven',
           },
+          {
+            packageNames: ['foo'],
+            packageRules: [
+              {
+                depTypeList: ['bar'],
+                automerge: true,
+              },
+            ],
+          },
         ],
         exposeEnv: true,
         lockFileMaintenance: {
@@ -144,7 +153,7 @@ describe('config/migration', () => {
       expect(isMigrated).toBe(true);
       expect(migratedConfig.depTypes).not.toBeDefined();
       expect(migratedConfig.automerge).toEqual(false);
-      expect(migratedConfig.packageRules).toHaveLength(8);
+      expect(migratedConfig.packageRules).toHaveLength(9);
       expect(migratedConfig.hostRules).toHaveLength(1);
     });
     it('migrates before and after schedules', () => {
diff --git a/lib/config/migration.ts b/lib/config/migration.ts
index 69ad69d8eec1d9ae3e095b97c87d40e741eb5247..3b9bb544987baa574b906cd23cfe4b0da2c1fe09 100644
--- a/lib/config/migration.ts
+++ b/lib/config/migration.ts
@@ -6,6 +6,7 @@ import type { HostRule } from '../types';
 import { clone } from '../util/clone';
 import { getOptions } from './definitions';
 import type { PackageRule, RenovateConfig, RenovateOptions } from './types';
+import { mergeChildConfig } from './utils';
 
 const options = getOptions();
 
@@ -549,6 +550,34 @@ export function migrateConfig(
         }
       }
     }
+    // Migrate nested packageRules
+    if (is.nonEmptyArray(migratedConfig.packageRules)) {
+      for (const packageRule of migratedConfig.packageRules) {
+        if (is.array(packageRule.packageRules)) {
+          logger.debug('Flattening nested packageRules');
+          // merge each subrule and add to the parent list
+          for (const subrule of packageRule.packageRules) {
+            const combinedRule = mergeChildConfig(packageRule, subrule);
+            delete combinedRule.packageRules;
+            migratedConfig.packageRules.push(combinedRule);
+          }
+          // delete the nested packageRules
+          delete packageRule.packageRules;
+          // mark the original rule for deletion if it's now pointless
+          if (
+            !Object.keys(packageRule).some(
+              (key) => !key.startsWith('match') && !key.startsWith('exclude')
+            )
+          ) {
+            packageRule._delete = true;
+          }
+        }
+      }
+      // filter out any rules which were marked for deletion in the previous step
+      migratedConfig.packageRules = migratedConfig.packageRules.filter(
+        (rule) => !rule._delete
+      );
+    }
     const isMigrated = !dequal(config, migratedConfig);
     if (isMigrated) {
       // recursive call in case any migrated configs need further migrating
diff --git a/lib/workers/repository/init/__snapshots__/flatten.spec.ts.snap b/lib/workers/repository/init/__snapshots__/flatten.spec.ts.snap
deleted file mode 100644
index 10f08a6cf98a6c968788202dfbbccec3d49eb8da..0000000000000000000000000000000000000000
--- a/lib/workers/repository/init/__snapshots__/flatten.spec.ts.snap
+++ /dev/null
@@ -1,20 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`workers/repository/init/flatten flattenPackageRules() flattens some and returns others 1`] = `
-Array [
-  Object {
-    "a": 1,
-  },
-  Object {
-    "a": 2,
-    "b": 1,
-  },
-  Object {
-    "a": 2,
-    "b": 2,
-  },
-  Object {
-    "b": 3,
-  },
-]
-`;
diff --git a/lib/workers/repository/init/config.ts b/lib/workers/repository/init/config.ts
index 3c055fa863136b9852f3f706558c65de806c4917..6f782f6cdfee7eb208e4d5275baa083635b897bb 100644
--- a/lib/workers/repository/init/config.ts
+++ b/lib/workers/repository/init/config.ts
@@ -20,7 +20,6 @@ import { getFileList } from '../../../util/git';
 import * as hostRules from '../../../util/host-rules';
 import { checkOnboardingBranch } from '../onboarding/branch';
 import { RepoFileConfig } from './common';
-import { flattenPackageRules } from './flatten';
 import { detectSemanticCommits } from './semantic';
 
 export async function detectRepoFileConfig(): Promise<RepoFileConfig> {
@@ -222,7 +221,6 @@ export async function mergeRenovateConfig(
   }
   returnConfig = mergeChildConfig(returnConfig, resolvedConfig);
   returnConfig.renovateJsonPresent = true;
-  returnConfig.packageRules = flattenPackageRules(returnConfig.packageRules);
   // istanbul ignore if
   if (returnConfig.ignorePaths?.length) {
     logger.debug(
diff --git a/lib/workers/repository/init/flatten.spec.ts b/lib/workers/repository/init/flatten.spec.ts
deleted file mode 100644
index 0f10d39f962b7c5401fce818653b4241399d2188..0000000000000000000000000000000000000000
--- a/lib/workers/repository/init/flatten.spec.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import { flattenPackageRules } from './flatten';
-
-describe('workers/repository/init/flatten', () => {
-  describe('flattenPackageRules()', () => {
-    it('returns empty', () => {
-      expect(flattenPackageRules([])).toEqual([]);
-    });
-    it('flattens some and returns others', () => {
-      const packageRules = [
-        {
-          a: 1,
-        },
-        {
-          a: 2,
-          packageRules: [
-            {
-              b: 1,
-            },
-            {
-              b: 2,
-            },
-          ],
-        },
-        {
-          b: 3,
-        },
-      ];
-      const res = flattenPackageRules(packageRules);
-      expect(res).toMatchSnapshot();
-      expect(res).toHaveLength(4);
-      expect(res[0].a).toBeDefined();
-      expect(res[0].b).toBeUndefined();
-      expect(res[1].a).toBeDefined();
-      expect(res[1].b).toBeDefined();
-      expect(res[2].a).toBeDefined();
-      expect(res[2].b).toBeDefined();
-      expect(res[3].a).toBeUndefined();
-      expect(res[3].b).toBeDefined();
-    });
-  });
-});
diff --git a/lib/workers/repository/init/flatten.ts b/lib/workers/repository/init/flatten.ts
deleted file mode 100644
index 9699673204457d0d4742cf8665641a8434e2ff1b..0000000000000000000000000000000000000000
--- a/lib/workers/repository/init/flatten.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { PackageRule, mergeChildConfig } from '../../../config';
-import { logger } from '../../../logger';
-
-export function flattenPackageRules(
-  packageRules: PackageRule[]
-): PackageRule[] {
-  const res: PackageRule[] = [];
-  if (!packageRules?.length) {
-    return res;
-  }
-  for (const rule of packageRules) {
-    if (rule.packageRules?.length) {
-      logger.debug('Flattening nested packageRules');
-      for (const subrule of rule.packageRules) {
-        const combinedRule = mergeChildConfig(rule, subrule);
-        delete combinedRule.packageRules;
-        res.push(combinedRule);
-      }
-    } else {
-      res.push(rule);
-    }
-  }
-  return res;
-}