diff --git a/lib/globals.d.ts b/lib/globals.d.ts
index eef15fbf1826df8aed78f800a647a58527745637..8cd937df0d0887690eb5d26090dd9ec98e8af4bc 100644
--- a/lib/globals.d.ts
+++ b/lib/globals.d.ts
@@ -9,12 +9,6 @@ declare interface Error {
   validationMessage?: string;
 }
 
-declare namespace NodeJS {
-  interface Global {
-    gitAuthor?: { name: string; email: string };
-  }
-}
-
 // can't use `resolveJsonModule` because it will copy json files and change dist path
 
 declare module '*/package.json' {
diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts
index 27efa594855b81a7da9944541e26518cd1e14513..d91f5aa485fe2dfea8d98d01149dd60ee3a427f6 100644
--- a/lib/platform/azure/index.ts
+++ b/lib/platform/azure/index.ts
@@ -180,8 +180,6 @@ export async function initRepo({
     ...config,
     url,
     extraCloneOpts: getStorageExtraCloneOpts(opts),
-    gitAuthorName: global.gitAuthor?.name,
-    gitAuthorEmail: global.gitAuthor?.email,
     cloneSubmodules,
   });
   const repoConfig: RepoResult = {
diff --git a/lib/platform/bitbucket-server/index.spec.ts b/lib/platform/bitbucket-server/index.spec.ts
index 1002b9aafa27195fd908a305b4a4908f9d334749..9ca7dba1e8353c2c3b3b5cc6e31dbd84697afb2e 100644
--- a/lib/platform/bitbucket-server/index.spec.ts
+++ b/lib/platform/bitbucket-server/index.spec.ts
@@ -1311,18 +1311,13 @@ describe('platform/bitbucket-server/index', () => {
             .twice()
             .reply(200, { conflicted: false });
 
-          const author = global.gitAuthor;
-          try {
-            expect(await bitbucket.getPr(3)).toMatchSnapshot();
+          expect(await bitbucket.getPr(3)).toMatchSnapshot();
 
-            expect(await bitbucket.getPr(5)).toMatchSnapshot();
+          expect(await bitbucket.getPr(5)).toMatchSnapshot();
 
-            expect(await bitbucket.getPr(5)).toMatchSnapshot();
+          expect(await bitbucket.getPr(5)).toMatchSnapshot();
 
-            expect(httpMock.getTrace()).toMatchSnapshot();
-          } finally {
-            global.gitAuthor = author;
-          }
+          expect(httpMock.getTrace()).toMatchSnapshot();
         });
 
         it('gets a closed PR', async () => {
diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts
index 44bc93d61a6a4f32b52702c8de711391f6192e49..711be02aa8b476e973dff5cb1d3b0d1ace195668 100644
--- a/lib/platform/bitbucket-server/index.ts
+++ b/lib/platform/bitbucket-server/index.ts
@@ -214,8 +214,6 @@ export async function initRepo({
     await git.initRepo({
       ...config,
       url: gitUrl,
-      gitAuthorName: global.gitAuthor?.name,
-      gitAuthorEmail: global.gitAuthor?.email,
       cloneSubmodules,
     });
 
diff --git a/lib/platform/bitbucket/index.spec.ts b/lib/platform/bitbucket/index.spec.ts
index 2711cf3cc7a9988321fb7f246a7d7ae938b11c21..2d8508446e5942c71096ad31c82b2aebf1b1faaf 100644
--- a/lib/platform/bitbucket/index.spec.ts
+++ b/lib/platform/bitbucket/index.spec.ts
@@ -726,7 +726,6 @@ describe('platform/bitbucket/index', () => {
 
     it('canRebase', async () => {
       expect.assertions(4);
-      const author = global.gitAuthor;
       const scope = await initRepoMock();
       scope
         .get('/2.0/repositories/some/repo/pullrequests/3')
@@ -747,22 +746,13 @@ describe('platform/bitbucket/index', () => {
         .get('/2.0/repositories/some/repo/pullrequests/5/diff')
         .twice()
         .reply(200, diff);
-      try {
-        expect(await bitbucket.getPr(3)).toMatchSnapshot();
-
-        global.gitAuthor = {
-          email: 'renovate@whitesourcesoftware.com',
-          name: 'bot',
-        };
-        expect(await bitbucket.getPr(5)).toMatchSnapshot();
-
-        global.gitAuthor = { email: 'jane@example.com', name: 'jane' };
-        expect(await bitbucket.getPr(5)).toMatchSnapshot();
-
-        expect(httpMock.getTrace()).toMatchSnapshot();
-      } finally {
-        global.gitAuthor = author;
-      }
+      expect(await bitbucket.getPr(3)).toMatchSnapshot();
+
+      expect(await bitbucket.getPr(5)).toMatchSnapshot();
+
+      expect(await bitbucket.getPr(5)).toMatchSnapshot();
+
+      expect(httpMock.getTrace()).toMatchSnapshot();
     });
   });
 
diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts
index 98471047aa87f74c7206056e6f39e637ec070c1d..7f2cc28fc5f21920b3a1ec239c39b91bb11340c8 100644
--- a/lib/platform/bitbucket/index.ts
+++ b/lib/platform/bitbucket/index.ts
@@ -179,8 +179,6 @@ export async function initRepo({
   await git.initRepo({
     ...config,
     url,
-    gitAuthorName: global.gitAuthor?.name,
-    gitAuthorEmail: global.gitAuthor?.email,
     cloneSubmodules,
   });
   const repoConfig: RepoResult = {
diff --git a/lib/platform/gitea/index.spec.ts b/lib/platform/gitea/index.spec.ts
index 2c41ac96a9cd02f9485ec376c406e2ecccefe7a8..1cd6325da00ce1be94a2d891dedd5f06749192f3 100644
--- a/lib/platform/gitea/index.spec.ts
+++ b/lib/platform/gitea/index.spec.ts
@@ -176,8 +176,6 @@ describe('platform/gitea/index', () => {
     gitvcs.isBranchStale.mockResolvedValue(false);
     gitvcs.getBranchCommit.mockReturnValue(mockCommitHash);
 
-    global.gitAuthor = { name: 'Renovate', email: 'renovate@example.com' };
-
     setBaseUrl('https://gitea.renovatebot.com/api/v1');
   });
 
@@ -574,7 +572,9 @@ describe('platform/gitea/index', () => {
         partial<ght.Branch>({
           commit: {
             id: mockCommitHash,
-            author: partial<ght.CommitUser>({ email: global.gitAuthor.email }),
+            author: partial<ght.CommitUser>({
+              email: 'renovate@whitesourcesoftware.com',
+            }),
           },
         })
       );
diff --git a/lib/platform/gitea/index.ts b/lib/platform/gitea/index.ts
index c7d831e6b007a71cf091153916c6c69d4b4def71..a72082431d3995bca9e6e8cfcb5fa8f7b238639c 100644
--- a/lib/platform/gitea/index.ts
+++ b/lib/platform/gitea/index.ts
@@ -297,8 +297,6 @@ const platform: Platform = {
     await git.initRepo({
       ...config,
       url: URL.format(gitEndpoint),
-      gitAuthorName: global.gitAuthor?.name,
-      gitAuthorEmail: global.gitAuthor?.email,
     });
 
     // Reset cached resources
diff --git a/lib/platform/github/index.spec.ts b/lib/platform/github/index.spec.ts
index 3d0c716cff4a53358d749b1c9352e9f89671a8b0..ff04c1f864f4d3a186085da9c42286cb99932584 100644
--- a/lib/platform/github/index.spec.ts
+++ b/lib/platform/github/index.spec.ts
@@ -30,7 +30,6 @@ describe('platform/github/index', () => {
     git.getBranchCommit.mockReturnValue(
       '0d9c7726c3d628b7e28af234595cfd20febdbf8e'
     );
-    delete global.gitAuthor;
     hostRules.find.mockReturnValue({
       token: 'abc123',
     });
@@ -1900,10 +1899,6 @@ describe('platform/github/index', () => {
       const scope = httpMock.scope(githubApiHost);
       initRepoMock(scope, 'some/repo');
       scope.post('/graphql').reply(200, graphqlOpenPullRequests);
-      global.gitAuthor = {
-        name: 'Renovate Bot',
-        email: 'renovate@whitesourcesoftware.com',
-      };
       await github.initRepo({
         repository: 'some/repo',
       } as any);
diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts
index 7b3af04531fc11a556fbe365e47b5b2a7ae6a8b1..f45144e82a77c8d878c1526d5939dc5bef3c9a0e 100644
--- a/lib/platform/github/index.ts
+++ b/lib/platform/github/index.ts
@@ -420,8 +420,6 @@ export async function initRepo({
   await git.initRepo({
     ...config,
     url,
-    gitAuthorName: global.gitAuthor?.name,
-    gitAuthorEmail: global.gitAuthor?.email,
   });
   const repoConfig: RepoResult = {
     defaultBranch: config.defaultBranch,
diff --git a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap
index 2a334d52630101e52a81976f643e31a1bfe0736f..9fffb450cdf82f890966c7d9db267cccc2f24b43 100644
--- a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap
+++ b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap
@@ -2653,63 +2653,12 @@ Array [
 ]
 `;
 
-exports[`platform/gitlab/index initRepo should use ssh_url_to_repo if gitUrl is set to ssh 1`] = `
-Array [
-  Object {
-    "headers": Object {
-      "accept": "application/json",
-      "accept-encoding": "gzip, deflate, br",
-      "authorization": "Bearer abc123",
-      "host": "gitlab.com",
-      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
-    },
-    "method": "GET",
-    "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject",
-  },
-]
-`;
-
-exports[`platform/gitlab/index initRepo should use ssh_url_to_repo if gitUrl is set to ssh 2`] = `
-Array [
-  Array [
-    Object {
-      "cloneSubmodules": undefined,
-      "defaultBranch": "master",
-      "gitAuthorEmail": undefined,
-      "gitAuthorName": undefined,
-      "ignorePrAuthor": undefined,
-      "mergeMethod": "merge",
-      "repository": "some%2Frepo%2Fproject",
-      "url": "ssh://git@gitlab.com/some%2Frepo%2Fproject.git",
-    },
-  ],
-]
-`;
-
-exports[`platform/gitlab/index initRepo should throw if ssh_url_to_repo is not present but gitUrl is set to ssh 1`] = `
-Array [
-  Object {
-    "headers": Object {
-      "accept": "application/json",
-      "accept-encoding": "gzip, deflate, br",
-      "authorization": "Bearer abc123",
-      "host": "gitlab.com",
-      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
-    },
-    "method": "GET",
-    "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject",
-  },
-]
-`;
-
 exports[`platform/gitlab/index initRepo should fall back respecting when GITLAB_IGNORE_REPO_URL is set 1`] = `
 Array [
   Array [
     Object {
       "cloneSubmodules": undefined,
       "defaultBranch": "master",
-      "gitAuthorEmail": undefined,
-      "gitAuthorName": undefined,
       "ignorePrAuthor": undefined,
       "mergeMethod": "merge",
       "repository": "some%2Frepo%2Fproject",
@@ -2869,6 +2818,53 @@ Array [
 ]
 `;
 
+exports[`platform/gitlab/index initRepo should throw if ssh_url_to_repo is not present but gitUrl is set to ssh 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Bearer abc123",
+      "host": "gitlab.com",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject",
+  },
+]
+`;
+
+exports[`platform/gitlab/index initRepo should use ssh_url_to_repo if gitUrl is set to ssh 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate, br",
+      "authorization": "Bearer abc123",
+      "host": "gitlab.com",
+      "user-agent": "RenovateBot/0.0.0-semantic-release (https://github.com/renovatebot/renovate)",
+    },
+    "method": "GET",
+    "url": "https://gitlab.com/api/v4/projects/some%2Frepo%2Fproject",
+  },
+]
+`;
+
+exports[`platform/gitlab/index initRepo should use ssh_url_to_repo if gitUrl is set to ssh 2`] = `
+Array [
+  Array [
+    Object {
+      "cloneSubmodules": undefined,
+      "defaultBranch": "master",
+      "ignorePrAuthor": undefined,
+      "mergeMethod": "merge",
+      "repository": "some%2Frepo%2Fproject",
+      "url": "ssh://git@gitlab.com/some%2Frepo%2Fproject.git",
+    },
+  ],
+]
+`;
+
 exports[`platform/gitlab/index massageMarkdown(input) returns updated pr body 1`] = `
 "https://github.com/foo/bar/issues/5 plus also [a link](https://github.com/foo/bar/issues/5
 
diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts
index 688437f3cc6d36dc4cb1125c10f599e45c08f30d..6fdbccf431239427a6a47aa243a0a81ea165187f 100644
--- a/lib/platform/gitlab/index.ts
+++ b/lib/platform/gitlab/index.ts
@@ -286,8 +286,6 @@ export async function initRepo({
     await git.initRepo({
       ...config,
       url,
-      gitAuthorName: global.gitAuthor?.name,
-      gitAuthorEmail: global.gitAuthor?.email,
     });
   } catch (err) /* istanbul ignore next */ {
     logger.debug({ err }, 'Caught initRepo error');
diff --git a/lib/platform/index.ts b/lib/platform/index.ts
index 5436884fda69edf11442b9fe30a03009a599750e..df48461baedd083b86d6d57eacf92d695bc4dc59 100644
--- a/lib/platform/index.ts
+++ b/lib/platform/index.ts
@@ -3,8 +3,7 @@ import type { AllConfig } from '../config/types';
 import { PLATFORM_NOT_FOUND } from '../constants/error-messages';
 import { logger } from '../logger';
 import type { HostRule } from '../types';
-import { setNoVerify, setPrivateKey } from '../util/git';
-import { parseGitAuthor } from '../util/git/author';
+import { setGitAuthor, setNoVerify, setPrivateKey } from '../util/git';
 import * as hostRules from '../util/host-rules';
 import platforms from './api';
 import type { Platform } from './types';
@@ -46,30 +45,15 @@ export async function initPlatform(config: AllConfig): Promise<AllConfig> {
   // TODO: types
   const platformInfo = await platform.initPlatform(config);
   const returnConfig: any = { ...config, ...platformInfo };
-  let gitAuthor: string;
   // istanbul ignore else
   if (config?.gitAuthor) {
     logger.debug(`Using configured gitAuthor (${config.gitAuthor})`);
-    gitAuthor = config.gitAuthor;
+    returnConfig.gitAuthor = config.gitAuthor;
   } else if (platformInfo?.gitAuthor) {
     logger.debug(`Using platform gitAuthor: ${String(platformInfo.gitAuthor)}`);
-    gitAuthor = platformInfo.gitAuthor;
-  } else {
-    logger.debug(
-      'Using default gitAuthor: Renovate Bot <renovate@whitesourcesoftware.com>'
-    );
-    gitAuthor = 'Renovate Bot <renovate@whitesourcesoftware.com>';
-  }
-  const gitAuthorParsed = parseGitAuthor(gitAuthor);
-  // istanbul ignore if
-  if (!gitAuthorParsed) {
-    throw new Error('Init: gitAuthor is not parsed as valid RFC5322 format');
+    returnConfig.gitAuthor = platformInfo.gitAuthor;
   }
-  global.gitAuthor = {
-    name: gitAuthorParsed.name,
-    email: gitAuthorParsed.address,
-  };
-
+  setGitAuthor(returnConfig.gitAuthor);
   const platformRule: HostRule = {
     hostType: returnConfig.platform,
     matchHost: URL.parse(returnConfig.endpoint).hostname,
diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts
index c9232b60f58fa9feb97730bfaf61b41ac0ad7245..36a3136e7453b0ad48dd54a76f68ca17d0a73e4b 100644
--- a/lib/util/git/index.spec.ts
+++ b/lib/util/git/index.spec.ts
@@ -3,6 +3,7 @@ import Git from 'simple-git';
 import SimpleGit from 'simple-git/src/git';
 import tmp from 'tmp-promise';
 import { setGlobalConfig } from '../../config/global';
+import { CONFIG_VALIDATION } from '../../constants/error-messages';
 import * as git from '.';
 import { GitNoVerifyOption, setNoVerify } from '.';
 
@@ -73,10 +74,9 @@ describe('util/git/index', () => {
     setGlobalConfig({ localDir: tmpDir.path });
     await git.initRepo({
       url: origin.path,
-      gitAuthorName: 'Jest',
-      gitAuthorEmail: 'Jest@example.com',
     });
     await git.setUserRepoConfig({ branchPrefix: 'renovate/' });
+    git.setGitAuthor('Jest <Jest@example.com>');
     setNoVerify([]);
     await git.syncGit();
     // override some local git settings for better testing
@@ -548,4 +548,9 @@ describe('util/git/index', () => {
       expect(res).toBe('test-extra-config-value');
     });
   });
+  describe('setGitAuthor()', () => {
+    it('throws for invalid', () => {
+      expect(() => git.setGitAuthor('invalid')).toThrow(CONFIG_VALIDATION);
+    });
+  });
 });
diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts
index 5194853076ac0a82c82720ecd57957c5a4836488..2bc8597d3cb089bb794e6af4fc0c816870bd9268 100644
--- a/lib/util/git/index.ts
+++ b/lib/util/git/index.ts
@@ -24,6 +24,7 @@ import { logger } from '../../logger';
 import { ExternalHostError } from '../../types/errors/external-host-error';
 import { GitOptions, GitProtocol } from '../../types/git';
 import { Limit, incLimitedValue } from '../../workers/global/limits';
+import { parseGitAuthor } from './author';
 import { GitNoVerifyOption, getNoVerify } from './config';
 import { configSigningKey, writePrivateKey } from './private-key';
 
@@ -44,8 +45,6 @@ interface StorageConfig {
   currentBranch?: string;
   url: string;
   extraCloneOpts?: GitOptions;
-  gitAuthorName?: string;
-  gitAuthorEmail?: string;
   cloneSubmodules?: boolean;
 }
 
@@ -57,6 +56,8 @@ interface LocalConfig extends StorageConfig {
   branchIsModified: Record<string, boolean>;
   branchPrefix: string;
   ignoredAuthors: string[];
+  gitAuthorName?: string;
+  gitAuthorEmail?: string;
 }
 
 // istanbul ignore next
@@ -234,6 +235,21 @@ async function setBranchPrefix(branchPrefix: string): Promise<void> {
   }
 }
 
+export function setGitAuthor(gitAuthor: string): void {
+  const gitAuthorParsed = parseGitAuthor(
+    gitAuthor || 'Renovate Bot <renovate@whitesourcesoftware.com>'
+  );
+  if (!gitAuthorParsed) {
+    const error = new Error(CONFIG_VALIDATION);
+    error.validationSource = 'None';
+    error.validationError = 'Invalid gitAuthor';
+    error.validationMessage = `gitAuthor is not parsed as valid RFC5322 format: ${gitAuthor}`;
+    throw error;
+  }
+  config.gitAuthorName = gitAuthorParsed.name;
+  config.gitAuthorEmail = gitAuthorParsed.address;
+}
+
 export async function writeGitAuthor(): Promise<void> {
   const { gitAuthorName, gitAuthorEmail } = config;
   try {