diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md
index 409b6a49dc1b42f4fb23efcb478658830af0f517..bc41af3d0a649fd1fb098baf0c89cd0f8704d6d7 100644
--- a/docs/usage/configuration-options.md
+++ b/docs/usage/configuration-options.md
@@ -2026,19 +2026,31 @@ Example setting source URL for package "dummy":
 
 ### replacementName
 
-This config option only works with the `npm` manager.
+This config option only works with some managers.
 We're working to support more managers, subscribe to issue [renovatebot/renovate#14149](https://github.com/renovatebot/renovate/issues/14149) to follow our progress.
 
-Use this field to define the name of a replacement package.
+Managers which do not support replacement:
+
+- `bazel`
+- `git-submodules`
+- `gomod`
+- `gradle`
+- `hermit`
+- `homebrew`
+- `maven`
+- `regex`
+
+Use the `replacementName` config option to set the name of a replacement package.
 Must be used with `replacementVersion` (see example below).
 You can suggest a new community package rule by editing [the `replacements.ts` file on the Renovate repository](https://github.com/renovatebot/renovate/blob/main/lib/config/presets/internal/replacements.ts) and opening a pull request.
 
 ### replacementVersion
 
-This config option only works with the `npm` manager.
+This config option only works with some managers.
 We're working to support more managers, subscribe to issue [renovatebot/renovate#14149](https://github.com/renovatebot/renovate/issues/14149) to follow our progress.
+For a list of managers which do not support replacement read the `replacementName` config option docs.
 
-Use this field to define the version of a replacement package.
+Use the `replacementVersion` config option to set the version of a replacement package.
 Must be used with `replacementName`.
 For example to replace the npm package `jade` with version `2.0.0` of the package `pug`:
 
diff --git a/lib/workers/repository/update/branch/auto-replace.spec.ts b/lib/workers/repository/update/branch/auto-replace.spec.ts
index 79ded8c0964a8b34edb0dfe9dab0faea3bc4d330..4a1abc13f01151710259408e47e9afc3d82a1492 100644
--- a/lib/workers/repository/update/branch/auto-replace.spec.ts
+++ b/lib/workers/repository/update/branch/auto-replace.spec.ts
@@ -1,5 +1,6 @@
+import { codeBlock } from 'common-tags';
 import { Fixtures } from '../../../../../test/fixtures';
-import { getConfig, partial } from '../../../../../test/util';
+import { getConfig } from '../../../../../test/util';
 import { GlobalConfig } from '../../../../config/global';
 import { WORKER_FILE_UPDATE_FAILED } from '../../../../constants/error-messages';
 import { extractPackageFile } from '../../../../modules/manager/html';
@@ -25,12 +26,10 @@ describe('workers/repository/update/branch/auto-replace', () => {
     });
 
     beforeEach(() => {
-      upgrade = partial<BranchUpgradeConfig>({
-        // TODO: fix types (#7154)
-        ...(getConfig() as any),
-        manager: 'html',
-        packageFile: 'test',
-      });
+      // TODO: fix types (#7154)
+      upgrade = getConfig() as BranchUpgradeConfig;
+      upgrade.packageFile = 'test';
+      upgrade.manager = 'html';
       reuseExistingBranch = false;
     });
 
@@ -233,5 +232,811 @@ describe('workers/repository/update/branch/auto-replace', () => {
       const res = doAutoReplace(upgrade, yml, reuseExistingBranch);
       await expect(res).rejects.toThrow(WORKER_FILE_UPDATE_FAILED);
     });
+
+    it('updates with docker replacement', async () => {
+      const dockerfile = 'FROM bitnami/redis:6.0.8';
+      upgrade.manager = 'dockerfile';
+      upgrade.updateType = 'replacement';
+      upgrade.depName = 'bitnami/redis';
+      upgrade.newName = 'mcr.microsoft.com/oss/bitnami/redis';
+      upgrade.replaceString = 'bitnami/redis:6.0.8';
+      upgrade.packageFile = 'Dockerfile';
+      upgrade.depIndex = 0;
+      upgrade.currentValue = '6.0.8';
+      const res = await doAutoReplace(upgrade, dockerfile, reuseExistingBranch);
+      expect(res).toBe(dockerfile.replace(upgrade.depName, upgrade.newName));
+    });
+
+    it('handles already replaced', async () => {
+      const dockerfile = 'FROM library/ubuntu:20.04';
+      upgrade.manager = 'dockerfile';
+      upgrade.updateType = 'replacement';
+      upgrade.depName = 'library/alpine';
+      upgrade.newName = 'library/ubuntu';
+      upgrade.packageFile = 'Dockerfile';
+      const res = await doAutoReplace(upgrade, dockerfile, reuseExistingBranch);
+      expect(res).toBe(dockerfile);
+    });
+
+    it('handles replacement with depName===newName when replaceString exists', async () => {
+      const yml =
+        'image: "1111111111.dkr.ecr.us-east-1.amazonaws.com/my-repository:1"\n\n';
+      upgrade.manager = 'regex';
+      upgrade.updateType = 'replacement';
+      upgrade.depName =
+        '1111111111.dkr.ecr.us-east-1.amazonaws.com/my-repository';
+      upgrade.currentValue = '1';
+      upgrade.newName =
+        '1111111111.dkr.ecr.us-east-1.amazonaws.com/my-repository';
+      upgrade.depIndex = 0;
+      upgrade.replaceString =
+        'image: "1111111111.dkr.ecr.us-east-1.amazonaws.com/my-repository:1"\n\n';
+      upgrade.packageFile = 'k8s/base/defaults.yaml';
+      upgrade.matchStrings = [
+        'image:\\s*\\\'?\\"?(?<depName>[^:]+):(?<currentValue>[^\\s\\\'\\"]+)\\\'?\\"?\\s*',
+      ];
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(yml);
+    });
+
+    it('updates with terraform replacement', async () => {
+      const hcl = codeBlock`
+        module "foo" {
+          source = "github.com/hashicorp/example?ref=v1.0.0"
+        }
+      `;
+      upgrade.manager = 'terraform';
+      upgrade.updateType = 'replacement';
+      upgrade.depName = 'github.com/hashicorp/example';
+      upgrade.newName = 'github.com/hashicorp/new-example';
+      upgrade.currentValue = 'v1.0.0';
+      upgrade.depIndex = 0;
+      upgrade.packageFile = 'modules.tf';
+      const res = await doAutoReplace(upgrade, hcl, reuseExistingBranch);
+      expect(res).toBe(hcl.replace(upgrade.depName, upgrade.newName));
+    });
+
+    it('updates with ansible replacement', async () => {
+      const yml = codeBlock`
+        - name: Container present
+          docker_container:
+            name: mycontainer
+            state: present
+            image: ubuntu:14.04
+            command: sleep infinity
+      `;
+      upgrade.manager = 'ansible';
+      upgrade.depName = 'ubuntu';
+      upgrade.currentValue = '14.04';
+      upgrade.replaceString = 'ubuntu:14.04';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = 'tasks/main.yaml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with ansible-galaxy roles replacement', async () => {
+      const yml = codeBlock`
+        roles
+          - name: geerlingguy.java
+            version: 1.9.6
+      `;
+      upgrade.manager = 'ansible-galaxy';
+      upgrade.depName = 'geerlingguy.java';
+      upgrade.currentValue = '1.9.6';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'cloudalchemy.node_exporter';
+      upgrade.newValue = '1.0.0';
+      upgrade.packageFile = 'requirements.yaml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with azure-pipeline image replacement', async () => {
+      const yml = codeBlock`
+        resources:
+          containers:
+            - container: linux
+              image: ubuntu:16.04
+      `;
+      upgrade.manager = 'azure-pipelines';
+      upgrade.depName = 'ubuntu';
+      upgrade.currentValue = '16.04';
+      upgrade.replaceString = 'ubuntu:16.04';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = 'azure-pipeline.yml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with batect image replacement', async () => {
+      const yml = codeBlock`
+        containers:
+          my-container:
+            image: ubuntu:16.04
+      `;
+      upgrade.manager = 'batect';
+      upgrade.depName = 'ubuntu';
+      upgrade.currentValue = '16.04';
+      upgrade.replaceString = 'ubuntu:16.04';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = 'batect.yml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with bitbucket-pipelines image replacement', async () => {
+      const yml = 'image: ubuntu:16.04\n';
+      upgrade.manager = 'bitbucket-pipelines';
+      upgrade.depName = 'ubuntu';
+      upgrade.currentValue = '16.04';
+      upgrade.replaceString = 'ubuntu:16.04';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = 'bitbucket-pipelines.yml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with buildkite plugin replacement', async () => {
+      const yml = codeBlock`
+        steps:
+          - command: test.sh
+            plugins:
+              - docker-compose#v3.10.0:
+      `;
+      upgrade.manager = 'buildkite';
+      upgrade.depName = 'docker-compose';
+      upgrade.currentValue = 'v3.10.0';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'buildpipe';
+      upgrade.newValue = 'v0.10.1';
+      upgrade.packageFile = 'buildkite.yml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with bundler gem replacement', async () => {
+      const gemfile = codeBlock`
+        source 'https://rubygems.org'
+
+        gem 'rails', '~>7.0'
+      `;
+      upgrade.manager = 'bundler';
+      upgrade.depName = 'rails';
+      upgrade.currentValue = "'~>7.0'";
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'rack';
+      upgrade.newValue = "'~>2.2'";
+      upgrade.packageFile = 'Gemfile';
+      const res = await doAutoReplace(upgrade, gemfile, reuseExistingBranch);
+      expect(res).toBe(
+        gemfile
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with cake #addin replacement', async () => {
+      const build =
+        '#addin nuget:?package=Microsoft.Extensions.Logging&version=7.0.0-preview.7.22375.6&prerelease\n';
+      upgrade.manager = 'cake';
+      upgrade.depName = 'Microsoft.Extensions.Logging';
+      upgrade.currentValue = '7.0.0-preview.7.22375.6';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'Newtonsoft.Json';
+      upgrade.newValue = '13.0.2-beta1';
+      upgrade.packageFile = 'build.cake';
+      const res = await doAutoReplace(upgrade, build, reuseExistingBranch);
+      expect(res).toBe(
+        build
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with cargo dependency replacement', async () => {
+      const cargo = codeBlock`
+        [dependencies]
+        rand = "0.8.4"
+      `;
+      upgrade.manager = 'cargo';
+      upgrade.depName = 'rand';
+      upgrade.currentValue = '0.8.4';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'syn';
+      upgrade.newValue = '1.0.99';
+      upgrade.packageFile = 'Cargo.toml';
+      const res = await doAutoReplace(upgrade, cargo, reuseExistingBranch);
+      expect(res).toBe(
+        cargo
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with cloudbuild replacement', async () => {
+      const yml = codeBlock`
+        steps:
+        - name: gcr.io/cloud-builders/docker
+        - name: ubuntu:16.04
+      `;
+      upgrade.manager = 'cloudbuild';
+      upgrade.depName = 'ubuntu';
+      upgrade.replaceString = 'ubuntu:16.04';
+      upgrade.currentValue = '16.04';
+      upgrade.depIndex = 1;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = 'cloudbuild.yml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with podfile pod replacement', async () => {
+      const podfile = "pod 'GoogleAnalytics', '3.20.0'";
+      upgrade.manager = 'cocoapods';
+      upgrade.depName = 'GoogleAnalytics';
+      upgrade.currentValue = '3.20.0';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'Docker';
+      upgrade.newValue = '1.3.11';
+      upgrade.packageFile = 'Podfile';
+      const res = await doAutoReplace(upgrade, podfile, reuseExistingBranch);
+      expect(res).toBe(
+        podfile
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with composer require replacement', async () => {
+      const json = codeBlock`
+      {
+          "require": {
+                  "psr/log": "3.0.0"
+          }
+      }
+      `;
+      upgrade.manager = 'composer';
+      upgrade.depName = 'psr/log';
+      upgrade.currentValue = '3.0.0';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'symfony/console';
+      upgrade.newValue = 'v6.1.3';
+      upgrade.packageFile = 'composer.json';
+      const res = await doAutoReplace(upgrade, json, reuseExistingBranch);
+      expect(res).toBe(
+        json
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with edn deps replacement', async () => {
+      const edn = codeBlock`
+      {:deps
+        {com.taoensso/timbre {:mvn/version "5.2.1"}}
+      }
+      `;
+      upgrade.manager = 'deps-edn';
+      upgrade.depName = 'com.taoensso/timbre';
+      upgrade.currentValue = '5.2.1';
+      upgrade.depIndex = 0;
+      upgrade.replaceString = '{:mvn/version \\"5.2.1\\"}';
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'org.clojure-android/tools.nrepl';
+      upgrade.newValue = '0.2.6-lollipop';
+      upgrade.packageFile = 'deps.edn';
+      const res = await doAutoReplace(upgrade, edn, reuseExistingBranch);
+      expect(res).toBe(
+        edn
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with docker-compose image replacement', async () => {
+      const yml = codeBlock`
+        services:
+          test:
+            image: "ubuntu:16.04"
+      `;
+      upgrade.manager = 'docker-compose';
+      upgrade.depName = 'ubuntu';
+      upgrade.replaceString = 'ubuntu:16.04';
+      upgrade.currentValue = '16.04';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = 'docker-compose.yml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with Dockerfile image replacement', async () => {
+      const dockerfile = 'FROM ubuntu:16.04\n';
+      upgrade.manager = 'dockerfile';
+      upgrade.depName = 'ubuntu';
+      upgrade.replaceString = 'ubuntu:16.04';
+      upgrade.currentValue = '16.04';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = 'Dockerfile';
+      const res = await doAutoReplace(upgrade, dockerfile, reuseExistingBranch);
+      expect(res).toBe(
+        dockerfile
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with Dockerfile image replacement with digest', async () => {
+      const dockerfile = 'FROM ubuntu:16.04@q1w2e3r4t5z6u7i8o9p0\n';
+      upgrade.manager = 'dockerfile';
+      upgrade.depName = 'ubuntu';
+      upgrade.replaceString = 'ubuntu:16.04@q1w2e3r4t5z6u7i8o9p0';
+      upgrade.currentValue = '16.04';
+      upgrade.currentDigest = 'q1w2e3r4t5z6u7i8o9p0';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.newDigest = 'p0o9i8u7z6t5r4e3w2q1';
+      upgrade.packageFile = 'Dockerfile';
+      const res = await doAutoReplace(upgrade, dockerfile, reuseExistingBranch);
+      expect(res).toBe(
+        dockerfile
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+          .replace(upgrade.currentDigest, upgrade.newDigest)
+      );
+    });
+
+    it('updates with droneci image replacement', async () => {
+      const yml = codeBlock`
+        steps:
+        - name: test
+          image: ubuntu:16.04
+      `;
+      upgrade.manager = 'droneci';
+      upgrade.depName = 'ubuntu';
+      upgrade.replaceString = 'ubuntu:16.04';
+      upgrade.currentValue = '16.04';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = '.drone.yml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with gitlabci image replacement', async () => {
+      const yml = 'image: "ubuntu:16.04"\n';
+      upgrade.manager = 'gitlabci';
+      upgrade.depName = 'ubuntu';
+      upgrade.replaceString = 'ubuntu:16.04';
+      upgrade.currentValue = '16.04';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = '.gitlab-ci.yml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with helm value image/repository replacement', async () => {
+      const yml = codeBlock`
+        parser:
+          image:
+              repository: docker.io/securecodebox/parser-nmap
+              tag: 3.14.3
+      `;
+      upgrade.manager = 'helm-values';
+      upgrade.depName = 'docker.io/securecodebox/parser-nmap';
+      upgrade.replaceString = '3.14.3';
+      upgrade.currentValue = '3.14.3';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'iteratec/juice-balancer';
+      upgrade.newValue = 'v5.1.0';
+      upgrade.packageFile = 'values.yml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with jenkins plugin replacement', async () => {
+      const txt = 'script-security:1175\n';
+      upgrade.manager = 'jenkins';
+      upgrade.depName = 'script-security';
+      upgrade.currentValue = '1175';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'Mailer';
+      upgrade.newValue = '438.v02c7f0a_12fa_4';
+      upgrade.packageFile = 'plugins.txt';
+      const res = await doAutoReplace(upgrade, txt, reuseExistingBranch);
+      expect(res).toBe(
+        txt
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with meteor npm.depends replacement', async () => {
+      const js = codeBlock`
+        Package.describe({
+          'name': 'test',
+        });
+
+        Npm.depends({
+          'xml2js': '0.2.0'
+        });'
+      `;
+      upgrade.manager = 'meteor';
+      upgrade.depName = 'xml2js';
+      upgrade.currentValue = '0.2.0';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'connect';
+      upgrade.newValue = '2.7.10';
+      upgrade.packageFile = 'package.js';
+      const res = await doAutoReplace(upgrade, js, reuseExistingBranch);
+      expect(res).toBe(
+        js
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('checks for replaceWithoutReplaceString double update', async () => {
+      const js = codeBlock`
+        Package.describe({
+          'name': 'test',
+        });
+
+        Npm.depends({
+          'xml2js': '0.2.0',
+          'xml2js': '0.2.0'
+        });
+      `;
+      upgrade.manager = 'meteor';
+      upgrade.depName = 'xml2js';
+      upgrade.currentValue = '0.2.0';
+      upgrade.depIndex = 1;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'connect';
+      upgrade.newValue = '2.7.10';
+      upgrade.packageFile = 'package.js';
+      const res = await doAutoReplace(upgrade, js, reuseExistingBranch);
+      expect(res).toBe(
+        codeBlock`
+        Package.describe({
+          'name': 'test',
+        });
+
+        Npm.depends({
+          'xml2js': '0.2.0',
+          'connect': '2.7.10'
+        });
+      `
+      );
+    });
+
+    it('updates with mix deps replacement', async () => {
+      const exs = codeBlock`
+        defmodule MyProject.MixProject do
+          use Mix.Project
+
+          def project() do
+            [
+              app: :my_project,
+              version: "0.0.1",
+              elixir: "~> 1.0",
+              deps: deps(),
+            ]
+          end
+
+          def application() do
+            []
+          end
+
+          defp deps() do
+            [
+              {:postgrex, "~> 0.8.1"}
+            ]
+          end
+        end
+      `;
+      upgrade.manager = 'mix';
+      upgrade.depName = 'postgrex';
+      upgrade.currentValue = '~> 0.8.1';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'jason';
+      upgrade.newValue = '~> 1.3.0';
+      upgrade.packageFile = 'mix.exs';
+      const res = await doAutoReplace(upgrade, exs, reuseExistingBranch);
+      expect(res).toBe(
+        exs
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with nuget tools replacement', async () => {
+      const json = codeBlock`
+        {
+          "version": 1,
+          "isRoot": true,
+          "tools": {
+            "Microsoft.Extensions.Logging": {
+              "version": "7.0.0-preview.7.22375.6"
+            }
+          }
+        }
+      `;
+      upgrade.manager = 'nuget';
+      upgrade.depName = 'Microsoft.Extensions.Logging';
+      upgrade.currentValue = '7.0.0-preview.7.22375.6';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'Newtonsoft.Json';
+      upgrade.newValue = '13.0.2-beta1';
+      upgrade.packageFile = 'dotnet-tools.json';
+      const res = await doAutoReplace(upgrade, json, reuseExistingBranch);
+      expect(res).toBe(
+        json
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with pre-commit repo replacement', async () => {
+      const yml = codeBlock`
+        repos:
+        -   repo: https://github.com/pre-commit/pre-commit-hooks
+            rev: v4.3.0
+      `;
+      upgrade.manager = 'pre-commit';
+      upgrade.depName = 'pre-commit/pre-commit-hooks';
+      upgrade.currentValue = 'v4.3.0';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'pre-commit/pygrep-hooks';
+      upgrade.newValue = 'v1.9.0';
+      upgrade.packageFile = '.pre-commit-config.yaml';
+      const res = await doAutoReplace(upgrade, yml, reuseExistingBranch);
+      expect(res).toBe(
+        yml
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with terraform image replacement', async () => {
+      const tf = codeBlock`
+        resource "docker_image" "image" {
+          name = "ubuntu:16.04"
+        }
+      `;
+      upgrade.manager = 'terraform';
+      upgrade.depName = 'ubuntu';
+      upgrade.replaceString = 'ubuntu:16.04';
+      upgrade.currentValue = '16.04';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = 'test.tf';
+      const res = await doAutoReplace(upgrade, tf, reuseExistingBranch);
+      expect(res).toBe(
+        tf
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with terraform module replacement', async () => {
+      const tf = codeBlock`
+        module "vpc" {
+          source  = "terraform-aws-modules/vpc/aws"
+         version = "3.14.2"
+        }
+      `;
+      upgrade.manager = 'terraform';
+      upgrade.depName = 'terraform-aws-modules/vpc/aws';
+      upgrade.currentValue = '3.14.2';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'cloudposse/label/null';
+      upgrade.newValue = '0.25.0';
+      upgrade.packageFile = 'module-test.tf';
+      const res = await doAutoReplace(upgrade, tf, reuseExistingBranch);
+      expect(res).toBe(
+        tf
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with setup-cfg replacement', async () => {
+      const tf = codeBlock`
+        [options]
+        install_requires = sphinx ~=5.1.0
+      `;
+      upgrade.manager = 'setup-cfg';
+      upgrade.depName = 'sphinx';
+      upgrade.currentValue = '~=5.1.0';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'postgres';
+      upgrade.newValue = '~=4.0.0';
+      upgrade.packageFile = 'setup.cfg';
+      const res = await doAutoReplace(upgrade, tf, reuseExistingBranch);
+      expect(res).toBe(
+        tf
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with nvm version replacement', async () => {
+      const tf = '12.3.4';
+      upgrade.manager = 'nvm';
+      upgrade.depName = 'node';
+      upgrade.currentValue = '12.3.4';
+      upgrade.depIndex = 0;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'node';
+      upgrade.newValue = '16.5.4';
+      upgrade.packageFile = '.nvmrc';
+      const res = await doAutoReplace(upgrade, tf, reuseExistingBranch);
+      expect(res).toBe(
+        tf
+          .replace(upgrade.depName, upgrade.newName)
+          .replace(upgrade.currentValue, upgrade.newValue)
+      );
+    });
+
+    it('updates with multiple same name replacement without replaceString', async () => {
+      const dockerfile = codeBlock`
+        FROM ubuntu:16.04
+        FROM ubuntu:20.04
+        FROM ubuntu:18.04
+      `;
+      upgrade.manager = 'dockerfile';
+      upgrade.depName = 'ubuntu';
+      upgrade.currentValue = '18.04';
+      upgrade.depIndex = 2;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = 'Dockerfile';
+      const res = await doAutoReplace(upgrade, dockerfile, reuseExistingBranch);
+      expect(res).toBe(
+        codeBlock`
+          FROM ubuntu:16.04
+          FROM ubuntu:20.04
+          FROM alpine:3.16
+        `
+      );
+    });
+
+    it('updates with multiple same name replacement without replaceString 2', async () => {
+      const dockerfile = codeBlock`
+        FROM ubuntu:16.04
+        FROM ubuntu:20.04
+        FROM ubuntu:18.04
+      `;
+      upgrade.manager = 'dockerfile';
+      upgrade.depName = 'ubuntu';
+      upgrade.currentValue = '20.04';
+      upgrade.depIndex = 1;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = 'Dockerfile';
+      const res = await doAutoReplace(upgrade, dockerfile, reuseExistingBranch);
+      expect(res).toBe(
+        codeBlock`
+          FROM ubuntu:16.04
+          FROM alpine:3.16
+          FROM ubuntu:18.04
+        `
+      );
+    });
+
+    it('updates with multiple same version replacement without replaceString', async () => {
+      const dockerfile = codeBlock`
+        FROM notUbuntu:18.04
+        FROM alsoNotUbuntu:18.04
+        FROM ubuntu:18.04
+      `;
+      upgrade.manager = 'dockerfile';
+      upgrade.depName = 'ubuntu';
+      upgrade.currentValue = '18.04';
+      upgrade.depIndex = 2;
+      upgrade.updateType = 'replacement';
+      upgrade.newName = 'alpine';
+      upgrade.newValue = '3.16';
+      upgrade.packageFile = 'Dockerfile';
+      const res = await doAutoReplace(upgrade, dockerfile, reuseExistingBranch);
+      expect(res).toBe(
+        codeBlock`
+          FROM notUbuntu:18.04
+          FROM alsoNotUbuntu:18.04
+          FROM alpine:3.16
+        `
+      );
+    });
   });
 });
diff --git a/lib/workers/repository/update/branch/auto-replace.ts b/lib/workers/repository/update/branch/auto-replace.ts
index 1b92ed94b95491eec511f83f16c1bb07f4a5082e..c13490eab68b9ec95f9d06916075af10675dfae7 100644
--- a/lib/workers/repository/update/branch/auto-replace.ts
+++ b/lib/workers/repository/update/branch/auto-replace.ts
@@ -1,4 +1,5 @@
 // TODO #7154
+import is from '@sindresorhus/is';
 import { WORKER_FILE_UPDATE_FAILED } from '../../../../constants/error-messages';
 import { logger } from '../../../../logger';
 import { get } from '../../../../modules/manager';
@@ -45,7 +46,10 @@ export async function confirmIfDepUpdated(
     return false;
   }
 
-  if (upgrade.depName !== newUpgrade.depName) {
+  if (
+    upgrade.depName !== newUpgrade.depName &&
+    upgrade.newName !== newUpgrade.depName
+  ) {
     logger.debug(
       {
         manager,
@@ -139,18 +143,36 @@ export async function doAutoReplace(
   const {
     packageFile,
     depName,
+    newName,
     currentValue,
     newValue,
     currentDigest,
     newDigest,
     autoReplaceStringTemplate,
   } = upgrade;
+  /*
+    If replacement support for more managers is added,
+    please also update the list in docs/usage/configuration-options.md
+    at replacementName and replacementVersion
+  */
   if (reuseExistingBranch) {
     return await checkExistingBranch(upgrade, existingContent);
   }
+  const replaceWithoutReplaceString =
+    is.string(newName) &&
+    newName !== depName &&
+    (is.undefined(upgrade.replaceString) ||
+      !upgrade.replaceString?.includes(depName!));
   const replaceString = upgrade.replaceString ?? currentValue;
   logger.trace({ depName, replaceString }, 'autoReplace replaceString');
-  let searchIndex = existingContent.indexOf(replaceString!);
+  let searchIndex: number;
+  if (replaceWithoutReplaceString) {
+    const depIndex = existingContent.indexOf(depName!);
+    const valIndex = existingContent.indexOf(currentValue!);
+    searchIndex = depIndex < valIndex ? depIndex : valIndex;
+  } else {
+    searchIndex = existingContent.indexOf(replaceString!);
+  }
   if (searchIndex === -1) {
     logger.info(
       { packageFile, depName, existingContent, replaceString },
@@ -160,7 +182,7 @@ export async function doAutoReplace(
   }
   try {
     let newString: string;
-    if (autoReplaceStringTemplate) {
+    if (autoReplaceStringTemplate && !newName) {
       newString = compile(autoReplaceStringTemplate, upgrade, false);
     } else {
       newString = replaceString!;
@@ -170,6 +192,12 @@ export async function doAutoReplace(
           newValue
         );
       }
+      if (depName && newName) {
+        newString = newString.replace(
+          regEx(escapeRegExp(depName), 'g'),
+          newName
+        );
+      }
       if (currentDigest && newDigest) {
         newString = newString.replace(
           regEx(escapeRegExp(currentDigest), 'g'),
@@ -189,10 +217,60 @@ export async function doAutoReplace(
       `Starting search at index ${searchIndex}`
     );
     let newContent = existingContent;
+    let nameReplaced = !newName;
+    let valueReplaced = !newValue;
+    let startIndex = searchIndex;
     // Iterate through the rest of the file
     for (; searchIndex < newContent.length; searchIndex += 1) {
       // First check if we have a hit for the old version
-      if (matchAt(existingContent, searchIndex, replaceString!)) {
+      if (replaceWithoutReplaceString) {
+        // look for depName and currentValue
+        if (newName && matchAt(newContent, searchIndex, depName!)) {
+          logger.debug(
+            { packageFile, depName },
+            `Found depName at index ${searchIndex}`
+          );
+          if (nameReplaced) {
+            startIndex += 1;
+            searchIndex = startIndex;
+            await writeLocalFile(upgrade.packageFile!, existingContent);
+            newContent = existingContent;
+            nameReplaced = false;
+            valueReplaced = false;
+            continue;
+          }
+          // replace with newName
+          newContent = replaceAt(newContent, searchIndex, depName!, newName);
+          await writeLocalFile(upgrade.packageFile!, newContent);
+          nameReplaced = true;
+        } else if (
+          newValue &&
+          matchAt(newContent, searchIndex, currentValue!)
+        ) {
+          logger.debug(
+            { packageFile, currentValue },
+            `Found currentValue at index ${searchIndex}`
+          );
+          // Now test if the result matches
+          newContent = replaceAt(
+            newContent,
+            searchIndex,
+            currentValue!,
+            newValue
+          );
+          await writeLocalFile(upgrade.packageFile!, newContent);
+          valueReplaced = true;
+        }
+        if (nameReplaced && valueReplaced) {
+          if (await confirmIfDepUpdated(upgrade, newContent)) {
+            return newContent;
+          }
+          await writeLocalFile(upgrade.packageFile!, existingContent);
+          newContent = existingContent;
+          nameReplaced = false;
+          valueReplaced = false;
+        }
+      } else if (matchAt(newContent, searchIndex, replaceString!)) {
         logger.debug(
           { packageFile, depName },
           `Found match at index ${searchIndex}`
diff --git a/lib/workers/repository/update/branch/get-updated.spec.ts b/lib/workers/repository/update/branch/get-updated.spec.ts
index cb7fe72479ec9a8f94036fba6bcaddaf431bc96c..0f335cf14321546a9b1e9ad17c3b6b8d6c0d01a5 100644
--- a/lib/workers/repository/update/branch/get-updated.spec.ts
+++ b/lib/workers/repository/update/branch/get-updated.spec.ts
@@ -505,6 +505,22 @@ describe('workers/repository/update/branch/get-updated', () => {
       });
     });
 
+    it('handles replacement', async () => {
+      config.upgrades.push({
+        packageFile: 'index.html',
+        manager: 'html',
+        updateType: 'replacement',
+        branchName: undefined!,
+      });
+      autoReplace.doAutoReplace.mockResolvedValueOnce('my-new-dep:1.0.0');
+      const res = await getUpdatedPackageFiles(config);
+      expect(res).toMatchObject({
+        updatedPackageFiles: [
+          { path: 'index.html', contents: 'my-new-dep:1.0.0' },
+        ],
+      });
+    });
+
     describe('when some artifacts have changed and others have not', () => {
       const pushGemUpgrade = (opts: Partial<BranchUpgradeConfig>) =>
         config.upgrades.push({