diff --git a/docs/configuration.md b/docs/configuration.md
index f843b839a..ba978ef30 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -585,6 +585,7 @@ _(unset)_|Windows: `wincredman`, macOS: `keychain`, Linux: _(none)_|-
`gpg`|Use GPG to store encrypted files that are compatible with the [pass][pass] (requires GPG and `pass` to initialize the store).|macOS, Linux
`cache`|Git's built-in [credential cache][credential-cache].|macOS, Linux
`plaintext`|Store credentials in plaintext files (**UNSECURE**). Customize the plaintext store location with [`credential.plaintextStorePath`][credential-plaintextstorepath].|Windows, macOS, Linux
+`none`|Do not store credentials via GCM.|Windows, macOS, Linux
#### Example
diff --git a/docs/credstores.md b/docs/credstores.md
index 2964f5645..43811dc30 100644
--- a/docs/credstores.md
+++ b/docs/credstores.md
@@ -9,6 +9,7 @@ There are several options for storing credentials that GCM supports:
- GPG/[`pass`][passwordstore] compatible files
- Git's built-in [credential cache][credential-cache]
- Plaintext files
+- Passthrough/no-op (no credential store)
The default credential stores on macOS and Windows are the macOS Keychain and
the Windows Credential Manager, respectively.
@@ -251,6 +252,31 @@ permissions on this directory such that no other users or applications can
access files within. If possible, use a path that exists on an external volume
that you take with you and use full-disk encryption.
+## Passthrough/no-op (no credential store)
+
+**Available on:** _Windows, macOS, Linux_
+
+**:warning: .**
+
+```batch
+SET GCM_CREDENTIAL_STORE="none"
+```
+
+or
+
+```shell
+git config --global credential.credentialStore none
+```
+
+This option disables the internal credential store. All operations to store or
+retrieve credentials will do nothing, and will return success. This is useful if
+you want to use a different credential store, chained in sequence via Git
+configuration, and don't want GCM to store credentials.
+
+Note that you'll want to ensure that another credential helper is placed before
+GCM in the `credential.helper` Git configuration or else you will be prompted to
+enter your credentials every time you interact with a remote repository.
+
[access-windows-credential-manager]: https://support.microsoft.com/en-us/windows/accessing-credential-manager-1b5c916a-6a16-889f-8581-fc16e8165ac0
[aws-cloudshell]: https://aws.amazon.com/cloudshell/
[azure-cloudshell]: https://docs.microsoft.com/azure/cloud-shell/overview
diff --git a/docs/environment.md b/docs/environment.md
index 1973132ea..f321caa6c 100644
--- a/docs/environment.md
+++ b/docs/environment.md
@@ -716,6 +716,7 @@ _(unset)_|Windows: `wincredman`, macOS: `keychain`, Linux: _(none)_|-
`gpg`|Use GPG to store encrypted files that are compatible with the [`pass` utility][passwordstore] (requires GPG and `pass` to initialize the store).|macOS, Linux
`cache`|Git's built-in [credential cache][git-credential-cache].|Windows, macOS, Linux
`plaintext`|Store credentials in plaintext files (**UNSECURE**). Customize the plaintext store location with [`GCM_PLAINTEXT_STORE_PATH`][gcm-plaintext-store-path].|Windows, macOS, Linux
+`none`|Do not store credentials via GCM.|Windows, macOS, Linux
#### Windows
diff --git a/src/shared/Core/Constants.cs b/src/shared/Core/Constants.cs
index 41ccb990c..191fcc83d 100644
--- a/src/shared/Core/Constants.cs
+++ b/src/shared/Core/Constants.cs
@@ -38,6 +38,7 @@ public static class CredentialStoreNames
public const string SecretService = "secretservice";
public const string Plaintext = "plaintext";
public const string Cache = "cache";
+ public const string None = "none";
}
public static class RegexPatterns
diff --git a/src/shared/Core/CredentialStore.cs b/src/shared/Core/CredentialStore.cs
index 83f915d1e..11dc83818 100644
--- a/src/shared/Core/CredentialStore.cs
+++ b/src/shared/Core/CredentialStore.cs
@@ -100,6 +100,10 @@ private void EnsureBackingStore()
_backingStore = new PlaintextCredentialStore(_context.FileSystem, plainStoreRoot, ns);
break;
+ case StoreNames.None:
+ _backingStore = new NullCredentialStore();
+ break;
+
default:
var sb = new StringBuilder();
sb.AppendLine(string.IsNullOrWhiteSpace(credStoreName)
@@ -168,6 +172,9 @@ private static void AppendAvailableStoreList(StringBuilder sb)
sb.AppendFormat(" {1,-13} : store credentials in plain-text files (UNSECURE){0}",
Environment.NewLine, StoreNames.Plaintext);
+
+ sb.AppendFormat(" {1, -13} : disable internal credential storage{0}",
+ Environment.NewLine, StoreNames.None);
}
private void ValidateWindowsCredentialManager()
diff --git a/src/shared/Core/NullCredentialStore.cs b/src/shared/Core/NullCredentialStore.cs
new file mode 100644
index 000000000..fac92f47c
--- /dev/null
+++ b/src/shared/Core/NullCredentialStore.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+
+namespace GitCredentialManager;
+
+///
+/// Credential store that does nothing. This is useful when you want to disable internal credential storage
+/// and only use another helper configured in Git to store credentials.
+///
+public class NullCredentialStore : ICredentialStore
+{
+ public IList GetAccounts(string service) => Array.Empty();
+
+ public ICredential Get(string service, string account) => null;
+
+ public void AddOrUpdate(string service, string account, string secret) { }
+
+ public bool Remove(string service, string account) => false;
+}