Python 克隆 Git 仓库的方法

146

有没有一种不使用子进程的Python方式来克隆git存储库?我可以使用您推荐的任何模块。


3
Gitpy,我猜它会被称为这个名字。 - SilentGhost
@SilentGhost:你是指这个gitpy吗?http://github.com/vmalloc/gitpy 来自http://www.ryaari.com/blog/?p=9 - VonC
看起来有GitPython(http://pypi.python.org/pypi/GitPython,http://gitorious.org/git-python),我不认为它有克隆方法,但我敢打赌你可以添加一个...内部它将不得不调用`git clone`。 - Cascabel
1
Dulwich是Git的纯Python实现,完全不进行分叉。请注意,它仍在开发中,可能存在错误。 - Mark Lodato
12个回答

215
使用GitPython将为您提供一个良好的Python接口来使用Git。
要克隆一个新的存储库,您可以使用clone_from函数:
from git import Repo  # pip install gitpython

Repo.clone_from(git_url, repo_dir)

查看GitPython教程以获取使用Repo对象的示例。
注意:GitPython需要在系统上安装git,并通过系统的PATH访问。

4
如果必须以自动化方式运行,如何处理身份验证? - SunilS
3
根据您克隆仓库的来源,您可以在git_url中提供验证信息,可能需要在其中输入用户名和密码/令牌。请参阅此处的Github - LemurPwned
2
我们能否得到git_urlrepo_dir的示例? - Sam
有没有办法检查是否已经克隆? - undefined

87
有一个叫做GitPython的东西。之前没听说过,它内部依赖于某个地方有git可执行文件;此外,它可能有很多bug。但是试一试也许是值得的。
如何克隆
import git  # pip install gitpython
git.Git("/your/directory/to/clone").clone("git://gitorious.org/git-python/mainline.git")

(这样做不太好,我也不知道这是否是官方支持的方式,但它起作用了。)

是的,但有点复杂。 - Debilski
1
哦,我的错,我忽略了那种可能性。迈克,记住,内部其实只是在调用 git 可执行文件;它只是为你做了一些管理上的工作。 - Cascabel
我看了一下Gitorious,只是忽略了克隆选项,因为它根本没有记录在案..但我期望无论我使用什么都能执行某种进程命令..这个方法很有效,谢谢! - Mike
这个模块真的很有帮助,谢谢。你能帮我用这个模块拉取已经克隆过的仓库的主分支吗? - The Gr8 Adakron
3
如果需要自动化运行,如何处理身份验证? - SunilS
是的,我使用了GitPython。缺点是它不是纯API,它依赖于存在git二进制文件(必须)。对于身份验证,我使用了个人访问令牌。 - SunilS

30

我的解决方案非常简单和直接。它甚至不需要手动输入密码。

这是我的完整代码:

import sys
import os

path  = "/path/to/store/your/cloned/project" 
clone = "git clone gitolite@<server_ip>:/your/project/name.git" 

os.system("sshpass -p your_password ssh user_name@your_localhost")
os.chdir(path) # Specifying the path where the cloned project needs to be copied
os.system(clone) # Cloning

2
工作得很好,但是如果您在项目中使用其他相对路径,则可能需要记住真实的工作目录“os.getcwd()”,然后再使用“os.chdir(...)”更改它,并在之后将其重置回来。 - Maximosaic
1
@Maximosaic,可以通过使用git clone <repo_url> <target_path>来避免这种情况。不需要使用chdir - Lahiru Chandima
仅适用于Linux和Mac操作系统,不支持Windows。 - matan h
除了已经提到的其他潜在注意事项之外,如果您想运行一个shell命令(在这种情况下是git cli),最好选择subprocess而不是os,因为os.system将被弃用。祝好! - theraulpareja
这对于跨平台,即Linux和Windows都不起作用。 - undefined

19

针对 Python 3:

首先安装模块:

pip3 install gitpython

然后,编写代码 :)

from git.repo.base import Repo
Repo.clone_from("https://github.com/*****", "folderToSave")

我希望这能对你有所帮助


有没有办法检查是否已经克隆? - undefined

14
这是一种在克隆使用GitPython的仓库时打印进度的方法。
import time
import git  # pip install gitpython
from git import RemoteProgress

class CloneProgress(RemoteProgress):
    def update(self, op_code, cur_count, max_count=None, message=''):
        if message:
            print(message)

print('Cloning into %s' % git_root)
git.Repo.clone_from('https://github.com/your-repo', '/your/repo/dir', 
        branch='master', progress=CloneProgress())

1
以下是如何撰写一个好的回答?的一些指南。这个提供的答案可能是正确的,但它可以从解释中受益。仅有代码的答案不被认为是“好”的答案。来自审查 - Trenton McKinney
有没有办法检索是否已经克隆? - undefined

13
Github的libgit2绑定库pygit2提供了一个一行代码即可克隆远程目录的功能:

Github的libgit2绑定,pygit2提供了一行代码来克隆远程目录:

clone_repository(url, path, 
    bare=False, repository=None, remote=None, checkout_branch=None, callbacks=None)

这需要单独安装 libgit2,还是它与 pygit2 捆绑在一起? - norok2

5
你可以使用dload
import dload
dload.git_clone("https://github.com/some_repo.git")

pip install dload

4
使用Dulwich,您应该能够做到以下事情:
from dulwich.repo import Repo
Repo("/path/to/source").clone("/path/to/target")

这还很基础——它会复制对象和引用,但如果您创建一个非裸库,则不会创建工作树的内容。


4

一个相当简单的方法就是直接在 URL 中传递凭据,但这可能会引起怀疑 - 使用时请谨慎。

import os

def getRepo(repo_url, login_object):
  '''
  Clones the passed repo to my staging dir
  '''

  path_append = r"stage\repo" # Can set this as an arg 
  os.chdir(path_append)

  repo_moddedURL = 'https://' + login_object['username'] + ':' + login_object['password'] + '@github.com/UserName/RepoName.git'
  os.system('git clone '+ repo_moddedURL)

  print('Cloned!')


if __name__ == '__main__':
    getRepo('https://github.com/UserName/RepoYouWant.git', {'username': 'userName', 'password': 'passWord'})

1
这是使用gitpython模块进行gitpull和gitpush的示例代码。
import os.path
from git import *
import git, os, shutil
# create local Repo/Folder
UPLOAD_FOLDER = "LocalPath/Folder"
if not os.path.exists(UPLOAD_FOLDER):
  os.makedirs(UPLOAD_FOLDER)
  print(UPLOAD_FOLDER)
new_path = os.path.join(UPLOADFOLDER)
DIR_NAME = new_path
REMOTE_URL = "GitURL"  # if you already connected with server you dont need to give 
any credential
# REMOTE_URL looks "git@github.com:path of Repo"
# code for clone
class git_operation_clone():
  try:
    def __init__(self):
        self.DIR_NAME = DIR_NAME
        self.REMOTE_URL = REMOTE_URL

    def git_clone(self):

        if os.path.isdir(DIR_NAME):
            shutil.rmtree(DIR_NAME)
        os.mkdir(DIR_NAME)
        repo = git.Repo.init(DIR_NAME)
        origin = repo.create_remote('origin', REMOTE_URL)
        origin.fetch()
        origin.pull(origin.refs[0].remote_head)
  except Exception as e:
      print(str(e))
# code for push
class git_operation_push():
  def git_push_file(self):
    try:
        repo = Repo(DIR_NAME)
        commit_message = 'work in progress'
        # repo.index.add(u=True)
        repo.git.add('--all')
        repo.index.commit(commit_message)
        origin = repo.remote('origin')
        origin.push('master')
        repo.git.add(update=True)
        print("repo push succesfully")
    except Exception as e:
        print(str(e))
if __name__ == '__main__':
   a = git_operation_push()
   git_operation_push.git_push_file('')
   git_operation_clone()
   git_operation_clone.git_clone('')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接