diff --git a/lib/workers/repository/updates/branchify.spec.ts b/lib/workers/repository/updates/branchify.spec.ts
index fc7623122806441b5831ed8226336d332b01cf43..7c3812abd0edefec8b19107f7425f0dac26aacd8 100644
--- a/lib/workers/repository/updates/branchify.spec.ts
+++ b/lib/workers/repository/updates/branchify.spec.ts
@@ -38,6 +38,33 @@ describe('workers/repository/updates/branchify', () => {
       expect(res.branches[0].isMinor).toBe(true);
       expect(res.branches[0].upgrades[0].isMinor).toBe(true);
     });
+    it('deduplicates', async () => {
+      flattenUpdates.mockResolvedValueOnce([
+        {
+          depName: 'foo',
+          branchName: 'foo-{{version}}',
+          currentValue: '1.1.0',
+          newValue: '1.3.0',
+          prTitle: 'some-title',
+          updateType: 'minor',
+          packageFile: 'foo/package.json',
+        },
+        {
+          depName: 'foo',
+          branchName: 'foo-{{version}}',
+          currentValue: '1.1.0',
+          newValue: '1.2.0',
+          prTitle: 'some-title',
+          updateType: 'minor',
+          packageFile: 'foo/package.json',
+        },
+      ]);
+      config.repoIsOnboarded = true;
+      const res = await branchifyUpgrades(config, {});
+      expect(Object.keys(res.branches)).toHaveLength(1);
+      expect(res.branches[0].isMinor).toBe(true);
+      expect(res.branches[0].upgrades[0].isMinor).toBe(true);
+    });
     it('uses major/minor/patch slugs', async () => {
       flattenUpdates.mockResolvedValueOnce([
         {
diff --git a/lib/workers/repository/updates/branchify.ts b/lib/workers/repository/updates/branchify.ts
index e70de9771a7ee770d1c8e0e1c2fef8bffaf282a8..686fdde0fc7d3136e05f06a968ac49f09baed45f 100644
--- a/lib/workers/repository/updates/branchify.ts
+++ b/lib/workers/repository/updates/branchify.ts
@@ -117,6 +117,39 @@ export async function branchifyUpgrades(
     for (const upgrade of branchUpgrades[branchName]) {
       upgrade.logJSON = await getChangeLogJSON(upgrade);
     }
+    const seenUpdates = {};
+    // Filter out duplicates
+    branchUpgrades[branchName] = branchUpgrades[branchName].filter(
+      (upgrade) => {
+        const {
+          manager,
+          packageFile,
+          depName,
+          currentValue,
+          newValue,
+        } = upgrade;
+        const upgradeKey = `${packageFile}:${depName}:${currentValue}`;
+        const previousNewValue = seenUpdates[upgradeKey];
+        if (previousNewValue) {
+          if (previousNewValue !== newValue) {
+            logger.info(
+              {
+                manager,
+                packageFile,
+                depName,
+                currentValue,
+                previousNewValue,
+                thisNewValue: newValue,
+              },
+              'Ignoring upgrade collision'
+            );
+          }
+          return false;
+        }
+        seenUpdates[upgradeKey] = newValue;
+        return true;
+      }
+    );
     const branch = generateBranchConfig(branchUpgrades[branchName]);
     branch.branchName = branchName;
     branches.push(branch);