Python Gitモジュールの経験?[閉まっている]


172

Python用のGitモジュールのいずれかを使用して、どのような経験をしましたか?(私はGitPython、PyGit、およびDulwichを知っています。ご存知の場合は、他の人に言及しても構いません。)

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

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

他に知りたい、または知りたいことがあれば、遠慮なくお知らせください。


25
この質問をコミュニティーWikiに変えることはできますか?最良の答えは時間とともに変化すると思います。
2013

4
@relet:閉じている限り、wikiにすることはできません。
PTBNL 2015年

回答:


119

この質問は少し前に尋ねられたもので、その時点でのライブラリの状態はわかりませんが、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ツールのラッパーであることを感謝しています。

更新: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()

2
優れたLegitツールはGitPythonを使用します:github.com/kennethreitz/legit/blob/develop/legit/scm.py
forivall

9
この答えに基づいて、私はgit-pythonで運を試しました。APIの扱いがおかしいと思います。ほとんどの場合、repo.git。*汎用インターフェースにフォールバックする必要があり、それでも時々適切に機能しません(例えば、repo.git.branch(b=somebranch)機能しますがrepo.git.branch(D=somebranch)、スペースがないため機能しません)。私はサブプロセスベースの一般的な機能を自分で実装すると思います。悲しいです、私は高い希望を持っていました。:-/
クリストフ

6
shモジュールの使用に切り替えましたgit = sh.git.bake(_cwd=repopath)。それは素晴らしく機能します。
2013年

10
shへのリンク:amoffat.github.io/sh は、Python stdlibの一部である必要があります。
g33kz0r 2013年

4
最新のpython shバージョンはWindowsでは動作しません。完全に失敗する。
void.pointer 2014

81

私は自分の質問に答えるつもりだと思っていました。答えで提案されているのとは異なる方法を取っているからです。それにもかかわらず、答えた人々に感謝します。

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

  • GitPython:ダウンロード後、これをインポートして適切なオブジェクトを初期化しました。ただし、チュートリアルで提案されたことを実行しようとすると、エラーが発生しました。ドキュメントが足りなかったので、私は別の場所を探しました。
  • PyGit:これはインポートすらできず、ドキュメントも見つかりませんでした。
  • Dulwich:(少なくとも私が望んで見たものに対して)最も有望であるようです。その卵には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で物事を進めるための忍耐力がなかったのかもしれません。そうは言っても、モジュールがもっと開発されてすぐにもっと役立つことを期待しています。


25
この答えは古くなっています。
Alex Chamberlain

3
はい、更新に興味があります。
JosefAssad

GitPythonは非常にうまく機能し、詳細に文書化されています。
Arthur

1
@Arthur私は同意しません。Gitのプル、追加、コミット、およびそれを使用するリモートリポジトリへのプッシュの基本を理解するために、StackOverflowとGitPythonのドキュメントに少なくとも3時間入っているからです。ドキュメントにはいくつかの高度な使用例がありますが、非常に基本的なものはありません。私は基本的にあきらめてサブプロセスも使用しています。
Daniel Lavedonio de Lima

31

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


1
git plumbへのアクセスも最適です。
pielgrzym 2012年

pygit2は本当に便利なライブラリであり、今後さらに拡張されることを楽しみにしています!
アレックスチェンバレン

2
現在のように、GitHubからソースを取得して、libgitとの両方の準安定バージョンを手動でダウンロードしてコンパイル/セットアップする必要がありpygit2ます。問題は、ヘッドブランチのテストが壊れており、最新の「安定した」インストールが失敗する...信頼性が重要であり、さまざまな環境に展開する必要がある場合、適切なソリューションではない... :(
mac

1
cygwinを使用するクライアントを計画している場合は、この組み合わせに近づかないでください。pygit2はlibgit2のラッパーであり、libgit2はすべてのcygwinサポートを削除しました。私が開発者の1人から受け取ったコメント、「試すことはできますが、ビルドできれば奇跡です」という美しいAPIですが、クライアントの半分はcygwinなので、使用できません。おそらくGitPythonに行きます。
scphantm 2013

2
代わりにWindowsのネイティブサポートに重点を置いているため cygwinはサポートされていません。したがって、libgit2がcygwinでサポートされていないのは正しいことですが、Windowsユーザーが風邪に負けているわけではありません
Xiong Chiamiov 2016

19

これはかなり古い質問です。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="samy@friendco.de", 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()

2
インデックスに「追加」するのではなく、「ステージング」することは好きではありません。一般的な/重要な操作の名前を変更すると、混乱を招くように見えます。
2014

3
@underrun追加は、ファイルをステージに追加することです。ステージングファイルと同じではありませんか?
ジミー・ケイン

ファイルの追加とは、コミットするファイルのステージングです(インデックスにファイルを追加しています)。操作は同じですが、コマンドラインで入力するgit add other1.txt other2.txtので、期待どおりに動作しません。
2014

1
このパッケージの優位性に同意しました。パッケージされているStaShをインストールした後、Pythonistaアプリ内でも使用できました。また、あなたの回答は、この質問への回答の中で最も最近更新されたものであることに注意してください。
Chris Redford

1
実際、Pythonistaでしか機能しないようです。Macでプライベートbitbucketリポジトリのクローンをパスワード認証してパスワードを取得するのは、ようやく諦めた悪夢でした。
Chris Redford

17

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

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


MercurialがDulwichを使用していることを知りませんでした。ありがとうございます。
kissgyorgy


7

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

現在、GitPythonが最も簡単に使用できます。多くのgit plumbingコマンドのラッピングをサポートし、プラグイン可能なオブジェクトデータベース(dulwichはその1つです)を備えています。コマンドが実装されていない場合は、コマンドラインに簡単にAPIを提供できます。例えば:

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

これは:

bash$ git checkout -b new_branch

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


2

ここに「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() )

5
私は解析をお勧めしませんgit status
Ehtesh Choudhury

1
構文解析のgit status --short方が簡単で、--short出力が変更される可能性は低いと思います。
Ben Page

2
使用git status --porcelainこのために--porcelain: Give the output in a stable, easy-to-parse format for scripts...
estani

またはさらに良いことに、の--z代わりに使用してください--porcelain。とは異なり--porcelain--zファイル名をエスケープしません。
Vojislav Stojkovic

2

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)

4
コードの繰り返しがたくさんあります...:p
Ciasto piekarz '15年

0

StGitのgit対話ライブラリー部分は、実際には非常に優れています。ただし、別パッケージとしては別れていませんが、十分ご興味がありましたら、修正できると確信しております。

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


-3

ちなみに、前述のGit Pythonライブラリには、同等の「git status」が含まれているようには見えません。これは、サブプロセスを介して残りのgitコマンドを処理することが非常に簡単であるため、実際に必要なのはこれだけです。


3
GitPythonの場合:git.Repo(repoDir).git.status()
アンダーラン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.