开始使用Git Python

3
我的目标是从Python访问现有的Git仓库。我想获取仓库历史记录和按需差异。
为了实现这一目标,我开始使用dulwich。所以我尝试了以下操作:
from dulwich.repo import Repo
Repo.init('/home/umpirsky/Projects/my-exising-git-repo')

出现了错误:OSError: [Errno 17] File exists: '/home/umpirsky/Projects/my-exising-git-repo/.git

doc中提到:您可以打开现有存储库,也可以创建新存储库。

有什么想法吗?我能否使用dulwich获取历史记录和差异?您能推荐其他用于Git访问的库吗?我正在开发Ubuntu应用程序,因此最好有Ubuntu软件包以便于部署。

我还会定期检查以检测存储库中的新更改,因此我宁愿使用远程,以便我可以检测尚未拉入本地的更改。我不确定这应该如何工作,因此任何帮助都将不胜感激。

提前致谢。


1
我不了解dulwich,但是有一个提示。在GIT中,“init”是创建存储库的命令。因此,您需要在文档中进一步查找。 - Niclas Nilsson
是的,我也这么认为,但文档太差了 :) 如您所见http://www.samba.org/~jelmer/dulwich/apidocs/dulwich.repo.BaseRepo.html init没有记录。我尝试了Repo.init("myrepo", mkdir=False) http://www.samba.org/~jelmer/dulwich/docs/tutorial/object-store.html 但我得到了相同的错误。 - umpirsky
是的!大约一年前我曾试图让git-python工作。但是我放弃了。后来我了解了不同的GIT模块对Python的支持,最终只是通过subprocess来调用Python。 - Niclas Nilsson
2个回答

6

我认为init方法用于创建新存储库,要打开现有存储库,只需以此方式传递路径:

from dulwich.repo import Repo
repo = Repo(<path>)

如果您想了解备选库的摘要,请查看此答案。基本上,它建议使用subprocess模块更容易,因为这是使用您已知接口的最佳方式。


谢谢,这解决了我的问题。现在我可以使用 repo.revision_history(repo.head()) 获取修订历史记录了。我不确定如何获取特定提交中更改的文件列表,但我会继续尝试。我不使用 subprocess 的原因是我想避免解析输出。问题仍然是如何检查本地未拉取的新修订版本。我猜 repo.revision_history(repo.head()) 只查看本地检出。 - umpirsky
可以从URI创建Repo而不是路径吗?我看到有一个函数get_transport_and_path-从URI或路径获取git客户端http://www.samba.org/~jelmer/dulwich/apidocs/dulwich.client.html#get_transport_and_path。这将返回GitClient,但我无法做太多事情。另一方面,Repo在注释中说“由本地磁盘支持的git存储库”。 - umpirsky
根据 dulwich.repo.Repo 的文档字符串,您可以打开一个“由本地磁盘支持的git存储库”。看起来 dulwich.web.get_repo 可能有用来完成您需要的操作,但还没有弄清楚使用哪个正确的后端。 - jcollado
哎呀,我不知道,使用了pysvn之后,我以为Git就会像小菜一样简单,但事实证明我错了。在同dulwich搞了几个小时之后,我开始转向GitPython的学习 http://packages.python.org/GitPython/0.3.1/tutorial.html - umpirsky
1
Git协议使得真正打开远程存储库变得不可能——你所能做的就是获取pack文件或tarballs并上传pack文件。dulwich.web包含一个HTTP Git服务器实现,但你不能像打开本地存储库一样打开HTTP存储库。 - jelmer

4

大多数Dulwich文档都假设读者已经有了Git文件格式/协议的一定了解。

您应该可以使用Repo打开现有存储库:

from dulwich.repo import Repo
x = Repo("/path/to/git/repo")

或者创建一个新的:
x = Repo.init("/path/to/new/repo")

为了获取某个提交的差异(与其第一个父提交的差异),您可以执行以下操作:
from dulwich.patch import write_tree_diff
commit = x[commit_id]
parent_commit = x[commit.parents[0]]
write_tree_diff(sys.stdout, x.object_store, parent_commit.tree, commit.tree)

Git协议只允许获取/发送包,不允许直接访问数据库中的特定对象。这意味着要检查远程存储库,您首先必须从远程存储库获取相关提交,然后才能查看它们。
from dulwich.client import get_transport_and_path
client, path = get_transport_and_path(remote_url)
remote_refs = client.fetch(path, x)
print x[remote_refs["refs/heads/master"]]

谢谢,非常好的回答。请允许我问一些子问题,因为我在这方面是新手。您最后一段代码中的remote_refs,它们是哪些提交?例如,我获取了您的dulwich git repo http://gist.github.com/1562112,但我得到了一些奇怪的提交,这些提交未列在https://github.com/jelmer/dulwich/commits/master上,并且看起来它们没有按提交时间排序。我的目标是获取所有按提交时间排序的提交(限制为最近的x个提交)。再次感谢。 - umpirsky
如果您想访问远程主分支中的最后X个提交,您可能需要像这样做:commit_ids = repo.get_walker(include=[remote_refs["refs/heads/master"]], max_entries=10)。 - jelmer
get_walker() 是相对较新的函数 - 如果你正在运行一个旧版本的 Dulwich,你需要使用 .revision_history(remote_refs["refs/heads/master"])[:10]。 - jelmer
你可以使用 repo.object_store.tree_changes() 来迭代每个文件的更改,例如修改/删除/添加。 - jelmer
这个问题在0.7.1和0.8.1版本中都存在,https://gist.github.com/1566513出现了相同的错误。这是一个bug吗?你能重现它吗? - umpirsky
显示剩余8条评论

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