GitPython and SSH Keys?
Asked Answered
B

8

29

How can I use GitPython along with specific SSH Keys?

The documentation isn't very thorough on that subject. The only thing I've tried so far is Repo(path).

Bahner answered 3/2, 2015 at 5:24 Comment(0)
P
13

Please note that all of the following will only work in GitPython v0.3.6 or newer.

You can use the GIT_SSH environment variable to provide an executable to git which will call ssh in its place. That way, you can use any kind of ssh key whenever git tries to connect.

This works either per call using a context manager ...

ssh_executable = os.path.join(rw_dir, 'my_ssh_executable.sh')
with repo.git.custom_environment(GIT_SSH=ssh_executable):
    repo.remotes.origin.fetch()

... or more persistently using the set_environment(...) method of the Git object of your repository:

old_env = repo.git.update_environment(GIT_SSH=ssh_executable)
# If needed, restore the old environment later
repo.git.update_environment(**old_env)

As you can set any amount of environment variables, you can use some to pass information along to your ssh-script to help it pick the desired ssh key for you.

More information about the becoming of this feature (new in GitPython v0.3.6) you will find in the respective issue.

Periclean answered 3/2, 2015 at 6:12 Comment(7)
Have to admit that I'm struggling with this as well. I'd really rather not write a custom SSH script. Is there any way to just identify the key to use? I'm new-ish to Python and the tutorial/API just aren't quite getting me where I need to be to get this working. Thanks.Stowers
Turns out, starting with git 2.3, this is pretty much built-in. Using the new GIT_SSH_COMMAND, you can specify the ssh -i ... command now directly, rather than relying on an external script.Periclean
Thanks. The following isn't working for me. What am I missing (formatting sucks in comments, but hopefully you get the idea)? with git_project.git.custom_environment(GIT_SSH_COMMAND='ssh -i ~/.ssh/id_rsa [email protected]'): git_project.remotes.origin.push(git_project.heads.master). If I add the -T option and execute from the command line, I logged in as expected. Formatting issue in my Python code?Stowers
Note that I added the [email protected] after an attempt without it also failed. Desperation trial & error, I guess. :-)Stowers
Unfortunately I lack personal experience with these environment variables. Maybe it's worth adding a new question that is specific to your particular problem.Periclean
You also shouldn't have to supply the hostname, so try omitting the [email protected].Lentissimo
I don't understand what to do here... where do I put the path to my ssh key?Helmet
G
18

Following worked for me on gitpython==2.1.1

import os
from git import Repo
from git import Git

git_ssh_identity_file = os.path.expanduser('~/.ssh/id_rsa')
git_ssh_cmd = 'ssh -i %s' % git_ssh_identity_file

with Git().custom_environment(GIT_SSH_COMMAND=git_ssh_cmd):
     Repo.clone_from('git@....', '/path', branch='my-branch')
Gouty answered 20/12, 2016 at 22:57 Comment(9)
What is the variable 'git' in this example?Ordinarily
You mean git@? That is the repo url, for example [email protected]:django/django.gitGouty
The line with git.custom_environment(GIT_SSH_COMMAND=git_ssh_cmd): ... what is git ? There is no variable or import that defines git in your code snippet.Ordinarily
This doesn't seem to work for me. I don't know but I think its having issue with adding the private key in the "os.path.expanduser(...)" step. Is there anyway i can verify the add is successful?Bashibazouk
This doesn't work in the case of clone_from. Check my answer below for a working version.Prentiss
Source in GitPython docs. Handling Remotes. At least as at GitPython==3.0.2Slipstream
github.com/gitpython-developers/GitPython/issues/339. This the GIT_SSH_COMMAND configt won't work for the clone_from() function.Ama
@Bashibazouk os.path.expanduser(...) returns a filename, a string. add - no, GitPython just passed it as argument to git executable.Player
clone_from now has the keyword env to pass the environment: Repo.clone_from(url, dst_path, branch=branch, env=dict(GIT_SSH_COMMAND=ssh_cmd))Eastman
A
16

I'm on GitPython==3.0.5 and the below worked for me.

from git import Repo
from git import Git    
git_ssh_identity_file = os.path.join(os.getcwd(),'ssh_key.key')
git_ssh_cmd = 'ssh -i %s' % git_ssh_identity_file
Repo.clone_from(repo_url, os.path.join(os.getcwd(), repo_name),env=dict(GIT_SSH_COMMAND=git_ssh_cmd))

Using repo.git.custom_environment to set the GIT_SSH_COMMAND won't work for the clone_from function. Reference: https://github.com/gitpython-developers/GitPython/issues/339

Ama answered 26/11, 2019 at 9:8 Comment(0)
P
13

Please note that all of the following will only work in GitPython v0.3.6 or newer.

You can use the GIT_SSH environment variable to provide an executable to git which will call ssh in its place. That way, you can use any kind of ssh key whenever git tries to connect.

This works either per call using a context manager ...

ssh_executable = os.path.join(rw_dir, 'my_ssh_executable.sh')
with repo.git.custom_environment(GIT_SSH=ssh_executable):
    repo.remotes.origin.fetch()

... or more persistently using the set_environment(...) method of the Git object of your repository:

old_env = repo.git.update_environment(GIT_SSH=ssh_executable)
# If needed, restore the old environment later
repo.git.update_environment(**old_env)

As you can set any amount of environment variables, you can use some to pass information along to your ssh-script to help it pick the desired ssh key for you.

More information about the becoming of this feature (new in GitPython v0.3.6) you will find in the respective issue.

Periclean answered 3/2, 2015 at 6:12 Comment(7)
Have to admit that I'm struggling with this as well. I'd really rather not write a custom SSH script. Is there any way to just identify the key to use? I'm new-ish to Python and the tutorial/API just aren't quite getting me where I need to be to get this working. Thanks.Stowers
Turns out, starting with git 2.3, this is pretty much built-in. Using the new GIT_SSH_COMMAND, you can specify the ssh -i ... command now directly, rather than relying on an external script.Periclean
Thanks. The following isn't working for me. What am I missing (formatting sucks in comments, but hopefully you get the idea)? with git_project.git.custom_environment(GIT_SSH_COMMAND='ssh -i ~/.ssh/id_rsa [email protected]'): git_project.remotes.origin.push(git_project.heads.master). If I add the -T option and execute from the command line, I logged in as expected. Formatting issue in my Python code?Stowers
Note that I added the [email protected] after an attempt without it also failed. Desperation trial & error, I guess. :-)Stowers
Unfortunately I lack personal experience with these environment variables. Maybe it's worth adding a new question that is specific to your particular problem.Periclean
You also shouldn't have to supply the hostname, so try omitting the [email protected].Lentissimo
I don't understand what to do here... where do I put the path to my ssh key?Helmet
P
10

In case of a clone_from in GitPython, the answer by Vijay doesn't work. It sets the git ssh command in a new Git() instance but then instantiates a separate Repo call. What does work is using the env argument of clone_from, as I learned from here:

Repo.clone_from(url, repo_dir, env={"GIT_SSH_COMMAND": 'ssh -i /PATH/TO/KEY'})
Prentiss answered 9/8, 2019 at 13:54 Comment(2)
This approach doesn't work for me. Any updates on this?Kentiggerma
What did you try?Prentiss
H
4

I've found this to make things a bit more like the way git works in the shell by itself.

import os
from git import Git, Repo

global_git = Git()
global_git.update_environment(
    **{ k: os.environ[k] for k in os.environ if k.startswith('SSH') }
)

It basically is copying the SSH environment variables to GitPython's "shadow" environment. It then uses the common SSH-AGENT authentication mechanisms so you don't have to worry about specifying exactly which key it is.

For a quicker alternative which carries probably a lot of cruft with it, but it works too:

import os
from git import Git

global_git = Git()
global_git.update_environment(**os.environ)

That mirrors your entire environment, more like the way a subshell works in bash.

Either way, any future call to create a repo or clone picks up the 'adjusted' environment and does the standard git authentication.

No shim scripts necessary.

Hookah answered 28/3, 2019 at 15:51 Comment(0)
E
1

With Windows be careful where you place the quotes. Say you have

git.Repo.clone_from(bb_url, working_dir, env={"GIT_SSH_COMMAND": git_ssh_cmd})

then this works:

git_ssh_cmd = f'ssh -p 6022 -i "C:\Users\mwb\.ssh\id_rsa_mock"'

but this does not:

git_ssh_cmd = f'ssh -p 6022 -i C:\Users\mwb\.ssh\id_rsa_mock'

Reason:

https://github.com/git-lfs/git-lfs/issues/3131

https://github.com/git-lfs/git-lfs/issues/1895

Eastman answered 6/4, 2021 at 11:53 Comment(0)
T
0

Here are the steps to clone gitlab repository using GitPython

  1. Create SSH key in Gitlab

  2. Run the following script after adding necessary details

    from git import Repo
    Repo.clone_from("gitlab_ssh_url", 
                    "path_where_you_want_to_clone_repo", 
                    env={"GIT_SSH_COMMAND": 'ssh -i path_to_ssh_private_key'})
    
    """
    Example
    Repo.clone_from("[email protected]:some_group/some_repo.git", 
                    "empty_dir/some_repo", 
                    env={"GIT_SSH_COMMAND": 'ssh -i /home/some_user/.ssh/id_rsa'})
    """
    
Testaceous answered 8/6, 2022 at 23:42 Comment(0)
I
0

This is what the latest documentation says:

ssh_cmd = 'ssh -i id_deployment_key'
with repo.git.custom_environment(GIT_SSH_COMMAND=ssh_cmd):
    repo.remotes.origin.fetch()

From: https://gitpython.readthedocs.io/en/stable/tutorial.html#handling-remotes

Install answered 5/10, 2022 at 17:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.