diff --git a/lib/workers/branch/index.spec.ts b/lib/workers/branch/index.spec.ts
index 883067782c0fac4e44500338149904eccaa04f3e..d2ef81e49890d8e4d4ff8acaaca6f90aeb5185a3 100644
--- a/lib/workers/branch/index.spec.ts
+++ b/lib/workers/branch/index.spec.ts
@@ -687,6 +687,16 @@ describe('workers/branch', () => {
         localDir: '/localDir',
         allowedPostUpgradeCommands: ['^echo {{{versioning}}}$'],
         allowPostUpgradeCommandTemplating: true,
+        upgrades: [
+          {
+            ...defaultConfig,
+            depName: 'some-dep-name',
+            postUpgradeTasks: {
+              commands: ['echo {{{versioning}}}', 'disallowed task'],
+              fileFilters: ['modified_file', 'deleted_file'],
+            },
+          } as never,
+        ],
       });
 
       expect(result).toEqual(ProcessBranchResult.Done);
@@ -742,6 +752,16 @@ describe('workers/branch', () => {
         localDir: '/localDir',
         allowedPostUpgradeCommands: ['^echo {{{versioning}}}$'],
         allowPostUpgradeCommandTemplating: false,
+        upgrades: [
+          {
+            ...defaultConfig,
+            depName: 'some-dep-name',
+            postUpgradeTasks: {
+              commands: ['echo {{{versioning}}}', 'disallowed task'],
+              fileFilters: ['modified_file', 'deleted_file'],
+            },
+          } as never,
+        ],
       });
 
       expect(result).toEqual(ProcessBranchResult.Done);
@@ -749,5 +769,136 @@ describe('workers/branch', () => {
         cwd: '/localDir',
       });
     });
+
+    it('executes post-upgrade tasks with multiple dependecy in one branch', async () => {
+      const updatedPackageFile: File = {
+        name: 'pom.xml',
+        contents: 'pom.xml file contents',
+      };
+      getUpdated.getUpdatedPackageFiles.mockResolvedValueOnce({
+        updatedPackageFiles: [updatedPackageFile],
+        artifactErrors: [],
+      } as never);
+      npmPostExtract.getAdditionalFiles.mockResolvedValueOnce({
+        artifactErrors: [],
+        updatedArtifacts: [
+          {
+            name: 'yarn.lock',
+            contents: Buffer.from([1, 2, 3]) /* Binary content */,
+          },
+        ],
+      } as never);
+      git.branchExists.mockReturnValueOnce(true);
+      platform.getBranchPr.mockResolvedValueOnce({
+        title: 'rebase!',
+        state: PrState.Open,
+        body: `- [x] <!-- rebase-check -->`,
+      } as never);
+      git.isBranchModified.mockResolvedValueOnce(true);
+      git.getRepoStatus
+        .mockResolvedValueOnce({
+          modified: ['modified_file', 'modified_then_deleted_file'],
+          not_added: [],
+          deleted: ['deleted_file', 'deleted_then_created_file'],
+        } as StatusResult)
+        .mockResolvedValueOnce({
+          modified: ['modified_file', 'deleted_then_created_file'],
+          not_added: [],
+          deleted: ['deleted_file', 'modified_then_deleted_file'],
+        } as StatusResult);
+      global.trustLevel = 'high';
+
+      fs.outputFile.mockReturnValue();
+      fs.readFile
+        .mockResolvedValueOnce(Buffer.from('modified file content'))
+        .mockResolvedValueOnce(Buffer.from('this file will not exists'))
+        .mockResolvedValueOnce(Buffer.from('modified file content again'))
+        .mockResolvedValueOnce(Buffer.from('this file was once deleted'));
+
+      schedule.isScheduledNow.mockReturnValueOnce(false);
+      commit.commitFilesToBranch.mockResolvedValueOnce(null);
+
+      const inconfig = {
+        ...config,
+        postUpgradeTasks: {
+          commands: ['echo {{{depName}}}', 'disallowed task'],
+          fileFilters: [
+            'modified_file',
+            'deleted_file',
+            'deleted_then_created_file',
+            'modified_then_deleted_file',
+          ],
+        },
+        localDir: '/localDir',
+        allowedPostUpgradeCommands: ['^echo {{{depName}}}$'],
+        allowPostUpgradeCommandTemplating: true,
+        upgrades: [
+          {
+            ...defaultConfig,
+            depName: 'some-dep-name-1',
+            postUpgradeTasks: {
+              commands: ['echo {{{depName}}}', 'disallowed task'],
+              fileFilters: [
+                'modified_file',
+                'deleted_file',
+                'deleted_then_created_file',
+                'modified_then_deleted_file',
+              ],
+            },
+          } as never,
+          {
+            ...defaultConfig,
+            depName: 'some-dep-name-2',
+            postUpgradeTasks: {
+              commands: ['echo {{{depName}}}', 'disallowed task'],
+              fileFilters: [
+                'modified_file',
+                'deleted_file',
+                'deleted_then_created_file',
+                'modified_then_deleted_file',
+              ],
+            },
+          } as never,
+        ],
+      };
+
+      const result = await branchWorker.processBranch(inconfig);
+
+      expect(result).toEqual(ProcessBranchResult.Done);
+      expect(exec.exec).toHaveBeenNthCalledWith(1, 'echo some-dep-name-1', {
+        cwd: '/localDir',
+      });
+      expect(exec.exec).toHaveBeenNthCalledWith(2, 'echo some-dep-name-2', {
+        cwd: '/localDir',
+      });
+      expect(exec.exec).toHaveBeenCalledTimes(2);
+      expect(
+        (commit.commitFilesToBranch.mock.calls[0][0].updatedArtifacts.find(
+          (f) => f.name === 'modified_file'
+        ).contents as Buffer).toString()
+      ).toBe('modified file content again');
+      expect(
+        (commit.commitFilesToBranch.mock.calls[0][0].updatedArtifacts.find(
+          (f) => f.name === 'deleted_then_created_file'
+        ).contents as Buffer).toString()
+      ).toBe('this file was once deleted');
+      expect(
+        commit.commitFilesToBranch.mock.calls[0][0].updatedArtifacts.find(
+          (f) =>
+            f.contents === 'deleted_then_created_file' && f.name === '|delete|'
+        )
+      ).toBeUndefined();
+      expect(
+        commit.commitFilesToBranch.mock.calls[0][0].updatedArtifacts.find(
+          (f) => f.name === 'modified_then_deleted_file'
+        )
+      ).toBeUndefined();
+      expect(
+        commit.commitFilesToBranch.mock.calls[0][0].updatedArtifacts.find(
+          (f) =>
+            f.contents === 'modified_then_deleted_file' && f.name === '|delete|'
+        )
+      ).not.toBeUndefined();
+    });
   });
 });
diff --git a/lib/workers/branch/index.ts b/lib/workers/branch/index.ts
index 25d05a5cfdf954f91c00387aee2f98537a227ccb..ee876a14c9ea14a960f95507258a5fd03a22685b 100644
--- a/lib/workers/branch/index.ts
+++ b/lib/workers/branch/index.ts
@@ -12,7 +12,7 @@ import {
   SYSTEM_INSUFFICIENT_DISK_SPACE,
   WORKER_FILE_UPDATE_FAILED,
 } from '../../constants/error-messages';
-import { logger } from '../../logger';
+import { addMeta, logger, removeMeta } from '../../logger';
 import { getAdditionalFiles } from '../../manager/npm/post-update';
 import { Pr, platform } from '../../platform';
 import { BranchStatus, PrState } from '../../types';
@@ -342,97 +342,116 @@ export async function processBranch(
       global.trustLevel === 'high' &&
       is.nonEmptyArray(config.allowedPostUpgradeCommands)
     ) {
-      logger.debug(
-        {
-          tasks: config.postUpgradeTasks,
-          allowedCommands: config.allowedPostUpgradeCommands,
-        },
-        'Checking for post-upgrade tasks'
-      );
-      const commands = config.postUpgradeTasks.commands || [];
-      const fileFilters = config.postUpgradeTasks.fileFilters || [];
+      for (const upgrade of config.upgrades) {
+        addMeta({ dep: upgrade.depName });
+        logger.trace(
+          {
+            tasks: upgrade.postUpgradeTasks,
+            allowedCommands: config.allowedPostUpgradeCommands,
+          },
+          'Checking for post-upgrade tasks'
+        );
+        const commands = upgrade.postUpgradeTasks.commands || [];
+        const fileFilters = upgrade.postUpgradeTasks.fileFilters || [];
 
-      if (is.nonEmptyArray(commands)) {
-        // Persist updated files in file system so any executed commands can see them
-        for (const file of config.updatedPackageFiles.concat(
-          config.updatedArtifacts
-        )) {
-          if (file.name !== '|delete|') {
-            let contents;
-            if (typeof file.contents === 'string') {
-              contents = Buffer.from(file.contents);
-            } else {
-              contents = file.contents;
+        if (is.nonEmptyArray(commands)) {
+          // Persist updated files in file system so any executed commands can see them
+          for (const file of config.updatedPackageFiles.concat(
+            config.updatedArtifacts
+          )) {
+            if (file.name !== '|delete|') {
+              let contents;
+              if (typeof file.contents === 'string') {
+                contents = Buffer.from(file.contents);
+              } else {
+                contents = file.contents;
+              }
+              await writeLocalFile(file.name, contents);
             }
-            await writeLocalFile(file.name, contents);
           }
-        }
 
-        for (const cmd of commands) {
-          if (
-            !config.allowedPostUpgradeCommands.some((pattern) =>
-              regEx(pattern).test(cmd)
-            )
-          ) {
-            logger.warn(
-              {
-                cmd,
-                allowedPostUpgradeCommands: config.allowedPostUpgradeCommands,
-              },
-              'Post-upgrade task did not match any on allowed list'
-            );
-          } else {
-            const compiledCmd = config.allowPostUpgradeCommandTemplating
-              ? template.compile(cmd, config)
-              : cmd;
+          for (const cmd of commands) {
+            if (
+              !config.allowedPostUpgradeCommands.some((pattern) =>
+                regEx(pattern).test(cmd)
+              )
+            ) {
+              logger.warn(
+                {
+                  cmd,
+                  allowedPostUpgradeCommands: config.allowedPostUpgradeCommands,
+                },
+                'Post-upgrade task did not match any on allowed list'
+              );
+            } else {
+              const compiledCmd = config.allowPostUpgradeCommandTemplating
+                ? template.compile(cmd, upgrade)
+                : cmd;
 
-            logger.debug({ cmd: compiledCmd }, 'Executing post-upgrade task');
+              logger.debug({ cmd: compiledCmd }, 'Executing post-upgrade task');
 
-            const execResult = await exec(compiledCmd, {
-              cwd: config.localDir,
-            });
+              const execResult = await exec(compiledCmd, {
+                cwd: config.localDir,
+              });
 
-            logger.debug(
-              { cmd: compiledCmd, ...execResult },
-              'Executed post-upgrade task'
-            );
+              logger.debug(
+                { cmd: compiledCmd, ...execResult },
+                'Executed post-upgrade task'
+              );
+            }
           }
-        }
 
-        const status = await getRepoStatus();
+          const status = await getRepoStatus();
 
-        for (const relativePath of status.modified.concat(status.not_added)) {
-          for (const pattern of fileFilters) {
-            if (minimatch(relativePath, pattern)) {
-              logger.debug(
-                { file: relativePath, pattern },
-                'Post-upgrade file saved'
-              );
-              const existingContent = await readLocalFile(relativePath);
-              config.updatedArtifacts.push({
-                name: relativePath,
-                contents: existingContent,
-              });
+          for (const relativePath of status.modified.concat(status.not_added)) {
+            for (const pattern of fileFilters) {
+              if (minimatch(relativePath, pattern)) {
+                logger.debug(
+                  { file: relativePath, pattern },
+                  'Post-upgrade file saved'
+                );
+                const existingContent = await readLocalFile(relativePath);
+                const existingUpdatedArtifacts = config.updatedArtifacts.find(
+                  (ua) => ua.name === relativePath
+                );
+                if (existingUpdatedArtifacts) {
+                  existingUpdatedArtifacts.contents = existingContent;
+                } else {
+                  config.updatedArtifacts.push({
+                    name: relativePath,
+                    contents: existingContent,
+                  });
+                }
+                // If the file is deleted by a previous post-update command, remove the deletion from updatedArtifacts
+                config.updatedArtifacts = config.updatedArtifacts.filter(
+                  (ua) => ua.name !== '|delete|' || ua.contents !== relativePath
+                );
+              }
             }
           }
-        }
 
-        for (const relativePath of status.deleted || []) {
-          for (const pattern of fileFilters) {
-            if (minimatch(relativePath, pattern)) {
-              logger.debug(
-                { file: relativePath, pattern },
-                'Post-upgrade file removed'
-              );
-              config.updatedArtifacts.push({
-                name: '|delete|',
-                contents: relativePath,
-              });
+          for (const relativePath of status.deleted || []) {
+            for (const pattern of fileFilters) {
+              if (minimatch(relativePath, pattern)) {
+                logger.debug(
+                  { file: relativePath, pattern },
+                  'Post-upgrade file removed'
+                );
+                config.updatedArtifacts.push({
+                  name: '|delete|',
+                  contents: relativePath,
+                });
+                // If the file is created or modified by a previous post-update command, remove the modification from updatedArtifacts
+                config.updatedArtifacts = config.updatedArtifacts.filter(
+                  (ua) => ua.name !== relativePath
+                );
+              }
             }
           }
         }
       }
     }
+    removeMeta(['dep']);
 
     if (config.artifactErrors?.length) {
       if (config.releaseTimestamp) {