All the information up to now (2020-01) are useful, but IMHO are a little bit messy, and no post sums them up to a clean solution.
So here are my solutions. If you are lucky with your current solution, then you are free to ignore this post.
Overall Premise:
Solution for *nix-based OS.
Tested on Debian-based OS, but should work on other *nix-based OS.
Overall Prerequisites:
- Separate identity files (keys) for different hosts and/or users available, e.g. generated via 
ssh-keygen -f <filename> ... 
Goals:
- Use a specific identity file (key) per repository (optional: per host)
 
- Works with any host: GitHub, GitLab, BitBucket, etc
 
- Simple to use and to adopt
 
- Prefer not messing around with URLs and use them as-is
 
- Prefer to use normal configuration of git and ssh
 
- (nice-to-have) Working in shell and gui tools
 
- (nice-to-have) Works with any tool: git, ssh, svn, rsync, etc.
 
Solutions:
- Convenient tool ssh-ident
 
- Just normal git and ssh, with a minor portion of shell magic
 
- Host renaming (also works with Putty/Pageant/Plink)
 
Note: A Match Path feature for OpenSSH would not help here, see https://marc.info/?l=openssh-unix-dev&m=141833748901966&w=2
Solution #1 - Tool ssh-ident
Notes:
- Currently (as of 2025-03) I link my own fork of the original ssh-ident, as it gives more flexibility to argument and key filename matching, plus includes some fixes.
 
- See docstring inside ssh-ident for how to use
 
Prerequisites:
Download and prepare
Configure ssh-ident and the identities
- Prepare files and directories
MYCONFIGDIR="${XDG_CONFIG_HOME:-${HOME}/.config}/ssh-ident"
[ -d "${MYCONFIGDIR}" ] || mkdir -vp "${MYCONFIGDIR}"
[ -f "${MYCONFIGDIR}/ssh-ident1" ] || printf -- '\n' >"${MYCONFIGDIR}/ssh-ident1"
MYEXTRAIDENTITIES='1 gh2 dummy'
for MYIDENTITY in ${MYEXTRAIDENTITIES}; do
  echo "${MYIDENTITY}"
  [ -d ~/.ssh/identities/"${MYIDENTITY}" ] || mkdir -vp ~/.ssh/identities/"${MYIDENTITY}"
done
chmod -v -R u=rwX,go= ~/.ssh/identities
unset -v MYCONFIGDIR MYEXTRAIDENTITIES MYIDENTITY
 
- Maintain configuration of ssh-ident to detect GitHub repositories
Example: ~/.ssh-ident
...
MATCH_ARGV = [
  (r"\s(git@)?github\.com\s.*'my-git-user-1\/dummy\.git'", "dummy"),
  (r"\s(git@)?github\.com\s.*'my-git-user-1\/.+\.git'", "1"),
  (r"\s(git@)?github\.com\s.*'my-git-user-2\/.+\.git'", "gh2"),
  ...
  #
  (r"\s(git@)?gist\.github\.com\s.*'abcdef01234567890fedcba912345678\.git'", "1"),
  ...
]
...
 
- Copy private keys plus their public keys(!) to the corresponding identity directory
 
- Optionally create a per-identity ssh config file
Example: ~/.ssh/identities/1/config
Host github.com,gist.github.com
    IdentitiesOnly yes
    IdentityFile ~/.ssh/identities/1/github-user1.key
    User git
 
Enable ssh-ident
Solution #2 - Just normal git and ssh
Prerequisites:
Concept:
Use OpenSSH client config's Match Exec functionality to check for an environment variable (e.g. SSHGITUSER) to select a specific identity file (key).
Fail when environment variable is not set or contains an unknown user id.
Allows for the following options:
- One account on host: use 
Host block in OpenSSH client config to directly define the IdentityFile = pure vanilla ssh standard, no environment variable needed 
- Multiple accounts on a host: pass the environment variable to the OpenSSH client, so it can react on it within 
Match blocks
- Either set the environment variable directly in front of the git call (e.g. 
SSHGITUSER='<id>' git ...)
- Has to be used when cloning a git repository (e.g. 
SSHGITUSER='<id>' git clone ...) 
- Works also for remotes that need different identity files (e.g. 
SSHGITUSER='<id>' git fetch <remote>) 
- Works also when using environment variables 
GIT_SSH_COMMAND or GIT_SSH (see docs) 
 
- or use git config 
core.sshCommand to hard-code it for a repository (e.g. git config --local core.sshCommand "SSHGITUSER='<id>' ssh")
- Does not work for remotes that need different identity files
 
- Does not work when using environment variables 
GIT_SSH_COMMAND or GIT_SSH (see docs) as these override git config core.sshCommand of the repository 
 
 
Setting up OpenSSH client config ssh_config:
Whenever we connect via ssh to a host, then we only want to connect with the identity files we explicitly specify. This can be achieved by setting IdentitiesOnly to yes and IdentityFile to none in a matching Host block, then no other identity files are offered to the target server, even when cached inside ssh-agent, nor the default key definitions will be tried.
If a default Host block exists for all servers, then extend its pattern to exclude the special host there.
Select the wanted identity file by checking an environment variable (e.g. SSHGITUSER). Define an id (number, letter or name) for each user and create a Match block for each id. The Match block should check the Host first to avoid using the identity file for other hosts and to avoid useless calls to the shell for testing the environment variable.
Specifing the user git for github.com and gist.github.com allows to remove git@ from the URL. This setting is overriden when a user is defined in the URL.
Example ~/.ssh/config for GitHub:
...
### >>> GitHub
## use: SSHGITUSER='<id>' git ...
## optional: git config --local core.sshCommand "SSHGITUSER='<id>' ssh"
Host github.com,gist.github.com
    IdentitiesOnly yes
    IdentityFile none
    User git
Match Host github.com,gist.github.com Exec "test ${SSHGITUSER:-_} = '1'"
    IdentityFile ~/.ssh/github-user1.key
Match Host github.com,gist.github.com Exec "test ${SSHGITUSER:-_} = 'gh2'"
    IdentityFile ~/.ssh/github-user2.key
Match Host github.com,gist.github.com Exec "test ${SSHGITUSER:-_} = 'dummy'"
    IdentityFile ~/.ssh/github-dummy-fake.key
<<< GitHub
...
Host !github.com,!gist.github.com,*
    IdentityFile ~/.ssh/personal.key
...
Notes:
- If only a single identity file is used for a host, then in the related 
Host block change IdentityFile from none directly to the identity file and no Match blocks are needed. 
- Remote 
User can also be set in a Match block. Remember a user in the URL overrides this setting. 
Testing ssh config:
Pass the environment variable for the SSH call by defining it directly in front of the command.
Use a wrong user in the URL to avoid actual logins as we just want to see the identity files offered to the server.
SSHGITUSER='1' ssh -vT ssh-test-dummy@github.com
Setting up git config of a repository for a hard-coded user id:
To hard-code the user id to a repository use git config core.sshCommand on the repository itself (via --local) to pass the environment variable to the ssh command.
The ssh command for git is either defined by the environment variable GIT_SSH_COMMAND (since git 2.3) or git config core.sshCommand (since git 2.10). If both are empty, then it normally defaults to just ssh (see Code funtions get_ssh_command() and fill_ssh_args() in connect.c).
Special case is when cloning a repository, then there is no config for the not yet cloned repository, and the environment variable has to be set directly in front of the git call (e.g. SSHGITUSER='<id>' git clone ...).
Example:
SSHGITUSER='1' git clone git@github.com:my-git-user-1/test-repo.git ~/work/test-repo
cd ~/work/test-repo
git config --local core.sshCommand "SSHGITUSER='1' ssh"
# Test: git fetch
Notes:
When using environment variables GIT_SSH_COMMAND or GIT_SSH (see docs) these will override git config core.sshCommand of the repository.
Check first via set | grep -e '^GIT_SSH' and if any is set, then adapt from using environment variables to git config core.sshCommand of the user (via --global) and remove the GIT_SSH[_COMMAND] variable.
(e.g. git config --global core.sshCommand "<content of used GIT_SSH[_COMMAND] variable>", plus git config --local core.sshCommand "SSHGITUSER='<id>' <content of used GIT_SSH[_COMMAND] variable>")
Other ideas for #2:
- Use environment variable for 
IdentityFile ~/.ssh/github-${SSHGITUSER}.key or User ${SSHGITUSER}. Has the tendency to longer user ids. 
Setting up other tools for #2:
On the command line just pass the environment variable by defining it directly in front of the command.
For hard-coding the user id the task is to find out how to pass the environment variable to the tool, e.g. configuration, wrapper script, alias, etc.
Solution #99 - Host renaming
Prerequisites:
Concept:
As also mentioned in this thread you can rename the host as described in the git FAQ for the ssh config to recognize it, choose the identity depending on it and set the correct host name.
I normally do not prefer to mess up URLs instead of using configurations/variables.
Still I would then add the user id as a subdomain, e.g. <user id>.github.com.
After some talk adding the user id behind the host has the advantage that normally DNS resolution will fail as the TLD got messed up and therefore the connection will immediately fail also.
Extended the example for this, e.g. github.com-<user id>.
This also works for Plink and Pageant from Putty.
Putty checks for a saved session named like the "host", e.g. session github.com-<user id>. This can be used for this solution.
Then Putty checks for a session which references the host, e.g. session testing with host github.com. Just to let you know.
Example ~/.ssh/config for GitHub:
...
### >>> GitHub
Host github.com,gist.github.com,*.github.com,*.gist.github.com,github.com-*,gist.github.com-*
        IdentitiesOnly yes
        IdentityFile none
        User git
Host 1.github.com,github.com-1
        IdentityFile ~/.ssh/github-user1.key
        Hostname github.com
Host 1.gist.github.com,gist.github.com-1
        IdentityFile ~/.ssh/github-user1.key
        Hostname gist.github.com
Host gh2.github.com,github.com-gh2
        IdentityFile ~/.ssh/github-user2.key
        Hostname github.com
Host gh2.gist.github.com,gist.github.com-gh2
        IdentityFile ~/.ssh/github-user2.key
        Hostname gist.github.com
<<< GitHub
Host !github.com,!gist.github.com,*
   IdentityFile ~/.ssh/personal.key
...