如何使用GitPython?

时间:2016-04-27 13:36:08

标签: python git gitpython

我正在使用GitPython从Gitlab服务器克隆存储库。

git.Repo.clone_from(gitlab_ssh_URL, local_path)

稍后我有另一个尝试更新此repo的脚本。

try:
    my_repo = git.Repo(local_path)
    my_repo .remotes.origin.pull()

except (git.exc.InvalidGitRepositoryError, git.exc.NoSuchPathError):
    print("Invalid repository: {}".format(local_path)

这项工作很有效,除非我在中间签出这样的标签:

tag_id = choose_tag()    # Return the position of an existing tag in my_repo.tags
my_repo .head.reference = my_repo.tags[tag_id]
my_repo .head.reset(index=True, working_tree=True)

在这种情况下,拉动时会出现GitCommandError:

git.exc.GitCommandError: 'git pull -v origin' returned with exit code 1

我已经两次阅读文档了,我看不出问题在哪里。特别是因为如果我尝试使用像SourceTree这样的专用工具来拉回这个回购,它的工作没有错误或警告。 我不明白,即使使用分离的HEAD,我检查了标记版本的事实也阻止我拉动。

  1. 在这种情况下我应该怎么做?
  2. 这里发生了什么,我错过了什么?
  3. 编辑:作为建议我试图查看exception.stdout和exception.sterr,这里没有任何用处(分别是b'和None)。这就是为什么我很难理解什么是错的。

2 个答案:

答案 0 :(得分:3)

我认为,最好先了解一下正在发生的事情(问题2:发生了什么?),这应该引导您回答问题1(如何解决这个问题?)

要详细了解出现了什么问题,您可以从例外打印stdoutstderr。 Git通常会将错误详细信息打印到控制台,因此应该在stdoutstderr中。

try:
    git.Repo.clone_from(gitlab_ssh_URL, local_path)
except git.GitCommandError as exception:
    print(exception)
    if exception.stdout:
        print('!! stdout was:')
        print(exception.stdout)
    if exception.stderr:
        print('!! stderr was:')
        print(exception.stderr)

作为旁注,在我使用git.Repo对象进行许多操作之前,我自己遇到了一些问题,然后才使用它与后端进行交互(即git本身)。在我看来,GitPython方面似乎有一些数据缓存问题,并且存储库(.git目录)中的数据与git.Repo对象中的数据结构之间缺乏同步。

修改

好吧,问题似乎是拉着分离的头 - 这可能不是你想要做的。

不过,你可以解决你的问题。由于来自分离的头部,你只需git checkout master进行git pull,然后你回到分离的头部,你可以跳过拉动,而是使用git fetch <remote> <source>:<destination>,如下所示:{{1} }。这将获取远程并将您的本地git fetch origin master:master分支与跟踪分支合并而不检查它,因此您可以始终保持独立头状态而不会出现任何问题。有关非常规使用fetch命令的详细信息,请参阅此SO答案:https://stackoverflow.com/a/23941734/4973698

使用GitPython,代码看起来像这样:

master

它会打印出这样的东西:

my_repo = git.Repo(local_path)
tag_id = choose_tag() # Return the position of an existing tag in my_repo.tags
my_repo.head.reference = my_repo.tags[tag_id]
my_repo.head.reset(index=True, working_tree=True)
fetch_info = my_repo.remotes.origin.fetch('master:master')
for info in fetch_info:
    print('{} {} {}'.format(i.ref, i.old_commit, i.flags))

...所以标志等于master 11249124f123a394132523513 64 。这是什么意思?当您执行64时,结果为print(git.FetchInfo.FAST_FORWARD),这意味着提取属于快进类型,因此您的本地分支已成功与远程跟踪分支合并,即您已执行{{1没有检查主人。

重要提示:仅当您的分支可以使用快进合并与远程分支合并时,此类提取才有效。

答案 1 :(得分:0)

答案是即使一些智能客户端很好地处理这种情况,试图拉开分离头并不是一个好主意。 所以我在这种情况下的解决方案是检查我的分支(主)上的最后一个版本,然后拉出然后再次检查所需的标记版本。 但是,我们可以为GitPython提供的错误消息感到遗憾。