如何使用GitPython拉?
我正在使用GitPython从Gitlab服务器克隆存储库如何使用GitPython拉?,python,git,gitpython,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): pr
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:
我已经阅读了两次文档,但我不知道问题出在哪里。特别是,如果我尝试使用SourceTree这样的专用工具来拉取此回购,它将在没有错误或警告的情况下工作。
我不明白为什么我签出了一个带标签的版本,即使有一个分离的头部,也阻止我拉
编辑:根据建议,我试图查看exception.stdout和exception.sterr,但这里没有任何有用的内容(分别是b''和None)。这就是为什么我很难理解哪里出了问题。我认为最好先了解更多的情况(问题2:发生了什么?),这将引导你回答问题1(如何解决这个问题?) 要了解更多错误,您可以从异常打印出
stdout
和stderr
。Git通常将错误详细信息打印到控制台,因此应该在stdout
或stderr
中
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:
如下所示:git fetch origin master:master
。这将获取远程并将本地主分支与跟踪分支合并,而无需签出,因此您可以始终保持分离的头部状态,而不会出现任何问题。有关非常规使用fetch命令的更多详细信息,请参阅此SO答案:
使用GitPython,代码可以如下所示:
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(info.ref, info.old_commit, info.flags))
master 11249124f123a394132523513 64
它会打印如下内容:
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(info.ref, info.old_commit, info.flags))
master 11249124f123a394132523513 64
。。。所以标志等于64
。这是什么意思?当您执行print(git.FetchInfo.FAST\u FORWARD)
时,结果是64
,这意味着提取是快进类型的,因此您的本地分支已成功与远程跟踪分支合并,即您已执行git pull origin master
,而未签出master
重要提示:只有当您的分支可以使用快进合并与远程分支合并时,这种提取才有效。答案是,即使某些智能客户端能够很好地处理这种情况,尝试使用分离头也不是一个好主意。
因此,在这种情况下,我的解决方案是签出分支(master)上的最后一个版本,然后再次签出所需的标记版本。
然而,我们对GitPython给出的错误消息感到遗憾。遗憾的是,stderr或stdout中都没有任何内容(分别是b''和None)。我唯一得到的是异常注释:“git pull-v origin”返回,退出代码为1。这就是我在这里有点迷路的原因。我并没有做太多的工作,只是创建一个新的git.Repo(path)并尝试拉取。我用另一个可能有用的解决方法更新了我的答案。我承认之前我完全错过了对分离的头部的拉动。我同意,这不是一个好主意。无论如何,如果答案()能为您的问题提供最佳解决方案,请不要忘记接受它:)