Skip to content

Repo.clone_from(env=...) doesn't have the desired effect #400

Description

@Neil511

I was wondering if there was an option or configuration in GitPython that allows you to specify what ssh key you would like to use for certain clones?

Example: I have a submodule that I would like to clone but it requires special access that I would like my script to employ. I need to allow access to anyone running the script and would like to avoid forcing users to setup an ssh config to do this.

Is there perhaps another way of tackling this problem that I'm unaware of?

Activity

  1. Byron commented on Mar 28, 2016

    @Byron
    Member

    Hi @Neil511,

    indeed git itself supports this via GIT_SSH and SSH_COMMAND, and I have linked numerous resources that should help to use it.

    The problem mentioned here is also detailed, to some extend, in the gitpython tutorial, just look for id_rsa in there.

    As I believe this question is answered, I am closing the issue - please feel free to comment on it in case you need it reopened.

  2. theherk commented on Apr 20, 2016

    @theherk

    @Byron: As far as I can tell, this cannot be done. I have worked around it in the meantime with:

    os.environ['GIT_SSH_COMMAND'] = ssh_cmd
    

    However, I cannot use custom_environment or update_environment before instantiating the repo.

    I have tried this:

    ssh_cmd = 'ssh -i /home/user/.ssh/other_rsa'
    repo = Repo()
    repo.git.update_environment(GIT_SSH_COMMAND=ssh_cmd)
    repo = Repo.clone_from(repo_url, repo_dir)
    

    NOGO - looks for wrong keys

    Also:

    ssh_cmd = 'ssh -i /home/user/.ssh/other_rsa'
    repo = Repo()
    with repo.git.custom_environment(GIT_SSH_COMMAND=ssh_cmd)
        repo = Repo.clone_from(repo_url, repo_dir)
    

    NOGO - looks for wrong keys

    Also:

    ssh_cmd = 'ssh -i /home/user/.ssh/other_rsa'
    repo = Repo.clone_from(repo_url, repo_dir, env={'GIT_SSH_COMMAND': ssh_cmd})
    

    NOGO - looks for wrong keys

    In the preceding scenarios, I have verified that repo.git.environment() is set correctly, and it still doesn't work.

    The only thing that works is:

    os.environ['GIT_SSH_COMMAND'] = ssh_cmd
    repo = Repo.clone_from(repo_url, repo_dir)
    
  3. Byron commented on Apr 22, 2016

    @Byron
    Member

    This seems to be a usability issue, as Repo.clone_from(repo_url, repo_dir, env={'GIT_SSH_COMMAND': ssh_cmd}) is the one that should work. The others cannot work as Repo.clone_from is a class method, not an instance method.

    I do wonder whether you are using the latest version, as judging from the code, the env=... version seems to be implemented correctly.

  4. theherk commented on Apr 22, 2016

    @theherk

    Well I am using 1.0.2. I see there is a tag for 2.0.0, but when I

    pip install gitpython
    

    I get 1.0.2. That is odd since I see 2.0.0 is on PyPI, but even doing

    pip install GitPython==2.0.0
    

    I get No matching distribution found for GitPython==2.0.0.

    When I get a chance I'll install from the repo tag and see if it changes.

  5. Byron commented on Apr 22, 2016

    @Byron
    Member

    Thanks for letting me know, it seems we have got a bug at our hands. There is no test for this feature, so it might very well be it's broken. The workaround described here works as the git command will use the current environment as its basis when spawning git commands - good to know that this works at least.

    Regarding the installation issue: It should work now. Turns out I managed to not upload the actual file when creating the new release.

  6. changed the title [-]Cloning with Specific Private SSH Key[/-] [+]Repo.clone_from(env=...) doesn't have the desired effect[/+] on Apr 22, 2016
  7. christianbundy commented on May 10, 2016

    @christianbundy

    I'm having [what I believe to be] the same issue on GitPython 2.0.2, but the workaround isn't working for me either.

    key_path = '/over/the/rainbow'
    repo_path = 'git@github.com:foo/bar.git'
    repo = Repo.init(repo_path)
    origin = repo.create_remote('origin', url)
    ssh_cmd = 'ssh -i ' + keypath
    with repo.git.custom_environment(GIT_SSH_COMMAND=ssh_cmd):
        os.environ['GIT_SSH_COMMAND'] = ssh_cmd
        print("GIT_SSH_COMMAND='" + ssh_cmd + '' git clone ' + url)
        repo.remotes.origin.fetch()

    This returns:

    GIT_SSH_COMMAND='ssh -i /over/the/rainbow' git clone git@github.com:foo/bar.git
    Traceback (most recent call last):
      File "/opt/champagne/lib/main.py", line 35, in <module>
        repo.remotes.origin.fetch()
      File "/usr/local/lib/python3.4/dist-packages/git/remote.py", line 657, in fetch
        res = self._get_fetch_info_from_stderr(proc, progress or RemoteProgress())
      File "/usr/local/lib/python3.4/dist-packages/git/remote.py", line 556, in _get_fetch_info_from_stderr
        raise GitCommandError(("Error when fetching: %s" % line,), 2)
    git.exc.GitCommandError: 'Error when fetching: fatal: Could not read from remote repository.

    Strangely enough, running GIT_SSH_COMMAND='ssh -i /over/the/rainbow' git clone git@github.com:foo/bar.git by itself works perfectly though. Weird, right?

  8. theherk commented on May 10, 2016

    @theherk

    Try using only the os.environ setting. Doing so inside of the custom environment may be superseding your environment variable by passing it to the command.

    key_path = '/over/the/rainbow'
    repo_path = 'git@github.com:foo/bar.git'
    repo = Repo.init(repo_path)
    origin = repo.create_remote('origin', url)
    ssh_cmd = 'ssh -i ' + keypath
    os.environ['GIT_SSH_COMMAND'] = ssh_cmd
    print("GIT_SSH_COMMAND='" + ssh_cmd + '' git clone ' + url)
    repo.remotes.origin.fetch()
  9. christianbundy commented on May 11, 2016

    @christianbundy

    That did the trick, cheers @theherk!

  10. Byron commented on May 19, 2016

    @Byron
    Member

    This is an odd one - I checked the code-path it is taking and could only see that it looks alright: The git process is always started with a customized environment, based on os.environ, with all custom environment variables added to it.

    As you shouldn't have to change os.environ directly to influence command execution, something you might try to learn more about the issue is to add a line line this right after this line:

    import pprint
    pprint.pprint(env)

    This should make clear which environment is actually passed to help understanding what is going on here.

  11. woshihaoren commented on Aug 22, 2016

    @woshihaoren

    @Byron I use python2.7 and gitpython2.0.8

    from git import Repo
    import os
    import logging
    logging.basicConfig(level=logging.INFO)
    os.environ['GIT_PYTHON_TRACE']='1'
    os.environ['GIT_SSH_COMMAND']='ssh -i /tmp/id_rsa'
    repo = Repo.clone_from('git@gitlab.xxx.com:config/config.git', 'aabb',env={'GIT_SSH_COMMAND':'ssh -i /tmp/id_rsa'})
    

    this code doesn't work and doesn't hava debug log

  12. Byron commented on Aug 23, 2016

    @Byron
    Member

    @woshihaoren I think what could work here is if you would import git after setting the environment variables, or by setting the environment variables from the shell invoking the python interpreter. Reason for that is that the environment variable is only read once at the time of import, and then cached in a similarly named class variable in the Git type.

  13. woshihaoren commented on Aug 23, 2016

    @woshihaoren

    @Byron
    Thank you , It's OK, and git version need >=2.3 GIT_SSH_COMMAND can work

    import os
    import logging
    logging.basicConfig(level=logging.INFO)
    os.environ['GIT_PYTHON_TRACE']='1'
    from git import Repo
    Repo.clone_from('git@gitlab.xxx.com:config/config.git', 'aabb',env={'GIT_SSH_COMMAND':'ssh -i /tmp/id_rsa'})
    
  14. added theissue type on Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions