diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts
index d045a2c2e9035669a7ce780fb4b19c04ae67ecb4..47a3158e340a8c72d1684226ed62f896795f26b1 100644
--- a/lib/util/git/index.spec.ts
+++ b/lib/util/git/index.spec.ts
@@ -373,6 +373,30 @@ describe('util/git/index', () => {
       expect(commit).not.toBeNull();
     });
 
+    it('link file', async () => {
+      const file: FileChange = {
+        type: 'addition',
+        path: 'future_link',
+        contents: 'past_file',
+        isSymlink: true,
+      };
+      const commit = await git.commitFiles({
+        branchName: 'renovate/future_branch',
+        files: [file],
+        message: 'Create a link',
+      });
+      expect(commit).toBeString();
+      const tmpGit = Git(tmpDir.path);
+      const lsTree = await tmpGit.raw(['ls-tree', commit!]);
+      const files = lsTree
+        .trim()
+        .split(newlineRegex)
+        .map((x) => x.split(/\s/))
+        .map(([mode, type, _hash, name]) => [mode, type, name]);
+      expect(files).toContainEqual(['100644', 'blob', 'past_file']);
+      expect(files).toContainEqual(['120000', 'blob', 'future_link']);
+    });
+
     it('deletes file', async () => {
       const file: FileChange = {
         type: 'deletion',
diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts
index 783b00fa45df7f2faa4580ab61ea1c87d85e1594..a163b14d0618013a0112254869c18530dbf8fb6a 100644
--- a/lib/util/git/index.ts
+++ b/lib/util/git/index.ts
@@ -862,9 +862,13 @@ export async function prepareCommit({
           }
           // some file systems including Windows don't support the mode
           // so the index should be manually updated after adding the file
-          await fs.outputFile(upath.join(localDir, fileName), contents, {
-            mode: file.isExecutable ? 0o777 : 0o666,
-          });
+          if (file.isSymlink) {
+            await fs.symlink(file.contents, upath.join(localDir, fileName));
+          } else {
+            await fs.outputFile(upath.join(localDir, fileName), contents, {
+              mode: file.isExecutable ? 0o777 : 0o666,
+            });
+          }
         }
         try {
           // istanbul ignore next
diff --git a/lib/util/git/types.ts b/lib/util/git/types.ts
index 0c124e6726899336e9a4072e60fa0d4a4ebf5c1a..f97d002d1d176b417dd4f4b291b65e00366755f0 100644
--- a/lib/util/git/types.ts
+++ b/lib/util/git/types.ts
@@ -52,6 +52,8 @@ export interface FileAddition {
    * The executable bit
    */
   isExecutable?: boolean;
+
+  isSymlink?: boolean;
 }
 
 export interface FileDeletion {