web-dev-qa-db-ja.com

Python Gitモジュールエクスペリエンス?

PythonのGitモジュールのいずれかでの人々の経験は何ですか? (私はGitPython、PyGit、およびDulwichを知っています-それらを知っていれば、他の人に言及してください。)

私はGitリポジトリと対話(追加、削除、コミット)する必要があるプログラムを書いていますが、Gitの経験がないため、探しているものの1つはGitに関する使いやすさ/理解です。

私が主に興味を持っている他のことは、ライブラリの成熟度と完全性、バグの合理的な不足、継続的な開発、ドキュメントと開発者の有用性です。

私が知りたい/必要とするかもしれない何かについて考えているなら、気軽にそれを言及してください。

165
PTBNL

私は答えで提案されたものとは異なる道を進んでいるので、自分の質問に答えると思いました。それにもかかわらず、答えた人に感謝します。

まず、GitPython、PyGit、およびDulwichでの私の経験の簡単な概要:

  • GitPython :ダウンロード後、これをインポートし、適切なオブジェクトを初期化しました。ただし、チュートリアルで提案されていることを実行しようとすると、エラーが発生しました。ドキュメントが不足しているため、別の場所に目を向けました。
  • PyGit :これはインポートすらされず、ドキュメントも見つかりませんでした。
  • Dulwich :最も有望なようです(少なくとも私が望んで見たものは)。 EggにはPythonソースが付属しているため、GitPythonよりも少し進歩しました。しかし、しばらくして、私がやったことを試してみる方が簡単だと判断しました。

また、 StGit は面白そうですが、機能を別のモジュールに抽出する必要があり、それがすぐに起こるのを待ちたくありません。

上記の3つのモジュールを機能させるために費やした時間よりも(はるかに)短い時間で、サブプロセスモジュールを介してgitコマンドを機能させることができました。

def gitAdd(fileName, repoDir):
    cmd = ['git', 'add', fileName]
    p = subprocess.Popen(cmd, cwd=repoDir)
    p.wait()

gitAdd('exampleFile.txt', '/usr/local/example_git_repo_dir')

これはまだ私のプログラムに完全には組み込まれていませんが、速度を除いて問題を予想していません(何百または何千ものファイルを処理することがあるため)。

たぶん、DulwichやGitPythonで物事を進める忍耐力がなかったのかもしれません。そうは言っても、モジュールがより多くの開発を得て、すぐにもっと便利になることを願っています。

72
PTBNL

この質問は少し前に尋ねられたものであり、その時点でのライブラリの状態はわかりませんが、GitPythonはコマンドラインツールを抽象化するのに適しているため、使用する必要はありません。サブプロセス。使用できるいくつかの便利な組み込みの抽象化がありますが、他のすべてについては次のようなことができます。

import git
repo = git.Repo( '/home/me/repodir' )
print repo.git.status()
# checkout and track a remote branch
print repo.git.checkout( 'Origin/somebranch', b='somebranch' )
# add a file
print repo.git.add( 'somefile' )
# commit
print repo.git.commit( m='my commit message' )
# now we are one commit ahead
print repo.git.status()

GitPythonの他のすべての機能により、ナビゲートが簡単になります。私はこのライブラリにかなり満足しており、基礎となるgitツールのラッパーであることを高く評価しています。

UPDATE:gitだけでなく、Pythonで必要なほとんどのコマンドラインユーティリティでshモジュールを使用するように切り替えました。上記を複製するには、代わりにこれを行います:

import sh
git = sh.git.bake(_cwd='/home/me/repodir')
print git.status()
# checkout and track a remote branch
print git.checkout('-b', 'somebranch')
# add a file
print git.add('somefile')
# commit
print git.commit(m='my commit message')
# now we are one commit ahead
print git.status()
111
underrun

pygit2 -優れた libgit2 バインディングを使用することをお勧めします

30
tamale

これはかなり古い質問です。Gitライブラリを探しているときに、今年(2013年)に作成された Gittle と呼ばれるものを見つけました。

それは私にとってはうまくいきました(私が試した他のものは不安定でした)。また、一般的なアクションのほとんどをカバーしているようです。

READMEのいくつかの例:

from gittle import Gittle

# Clone a repository
repo_path = '/tmp/gittle_bare'
repo_url = 'git://github.com/FriendCode/gittle.git'
repo = Gittle.clone(repo_url, repo_path)

# Stage multiple files
repo.stage(['other1.txt', 'other2.txt'])

# Do the commit
repo.commit(name="Samy Pesse", email="[email protected]", message="This is a commit")

# Authentication with RSA private key
key_file = open('/Users/Me/keys/rsa/private_rsa')
repo.auth(pkey=key_file)

# Do Push
repo.Push()
19
gak

たぶんそれは役立つかもしれませんが、BazaarとMercurialはどちらもGitの相互運用性のためにdulwichを使用しています。

Dulwichは、Pythonでのgitの再実装であるという意味で、おそらく他のものとは異なります。もう1つはGitのコマンドのラッパーである可能性があり(したがって、高レベルの観点から使用する方が簡単かもしれません:コミット/追加/削除)、おそらくAPIがgitのコマンドラインに非常に近いため、必要になりますGitの経験を積むため。

17
tonfa

変更された時間を反映した更新された回答:

現在、GitPythonが最も使いやすいです。多くのgit plumbコマンドのラッピングをサポートし、プラグ可能なオブジェクトデータベース(それらの1つであるダッチ)があり、コマンドが実装されていない場合、コマンドラインにシェルアウトするための簡単なAPIを提供します。例えば:

repo = Repo('.')
repo.checkout(b='new_branch')

これは以下を呼び出します:

bash$ git checkout -b new_branch

Dulwichも良いですが、はるかに低いレベルです。配管レベルでgitオブジェクトを操作する必要があり、通常はしたい素敵な磁器がないため、使用するのはやや苦痛です。ただし、gitの一部を変更する場合、またはgit-receive-packとgit-upload-packを使用する場合は、dulwichを使用する必要があります。

7
Jon Chu

完全を期すために、 http://github.com/alex/pyvcs/ はすべてのdvcの抽象化レイヤーです。ダルウィッチを使用しますが、他のdvcとの相互運用性を提供します。

6
Justin Abrahms

PTBNLの回答は私にとって非常に完璧です。 Windowsユーザー向けにもう少し作成します。

import time
import subprocess
def gitAdd(fileName, repoDir):
    cmd = 'git add ' + fileName
    pipe = subprocess.Popen(cmd, Shell=True, cwd=repoDir,stdout = subprocess.PIPE,stderr = subprocess.PIPE )
    (out, error) = pipe.communicate()
    print out,error
    pipe.wait()
    return 

def gitCommit(commitMessage, repoDir):
    cmd = 'git commit -am "%s"'%commitMessage
    pipe = subprocess.Popen(cmd, Shell=True, cwd=repoDir,stdout = subprocess.PIPE,stderr = subprocess.PIPE )
    (out, error) = pipe.communicate()
    print out,error
    pipe.wait()
    return 
def gitPush(repoDir):
    cmd = 'git Push '
    pipe = subprocess.Popen(cmd, Shell=True, cwd=repoDir,stdout = subprocess.PIPE,stderr = subprocess.PIPE )
    (out, error) = pipe.communicate()
    pipe.wait()
    return 

temp=time.localtime(time.time())
uploaddate= str(temp[0])+'_'+str(temp[1])+'_'+str(temp[2])+'_'+str(temp[3])+'_'+str(temp[4])

repoDir='d:\\c_Billy\\vfat\\Programming\\Projector\\billyccm' # your git repository , windows your need to use double backslash for right directory.
gitAdd('.',repoDir )
gitCommit(uploaddate, repoDir)
gitPush(repoDir)
2
Billy Jin

「git status」の非常に簡単な実装を次に示します。

import os
import string
from subprocess import *

repoDir = '/Users/foo/project'

def command(x):
    return str(Popen(x.split(' '), stdout=PIPE).communicate()[0])

def rm_empty(L): return [l for l in L if (l and l!="")]

def getUntracked():
    os.chdir(repoDir)
    status = command("git status")
    if "# Untracked files:" in status:
        untf = status.split("# Untracked files:")[1][1:].split("\n")
        return rm_empty([x[2:] for x in untf if string.strip(x) != "#" and x.startswith("#\t")])
    else:
        return []

def getNew():
    os.chdir(repoDir)
    status = command("git status").split("\n")
    return [x[14:] for x in status if x.startswith("#\tnew file:   ")]

def getModified():
    os.chdir(repoDir)
    status = command("git status").split("\n")
    return [x[14:] for x in status if x.startswith("#\tmodified:   ")]

print("Untracked:")
print( getUntracked() )
print("New:")
print( getNew() )
print("Modified:")
print( getModified() )
1
Shane Geiger

StGitのgitインタラクションライブラリ部分は、実際には非常に優れています。ただし、個別のパッケージとして分割されるわけではありませんが、十分な関心があれば、修正できると確信しています。

コミット、ツリーなどを表すため、および新しいコミットとツリーを作成するための非常に素晴らしい抽象化があります。

0
dkagedal