Quelles sont les expériences des personnes avec l’un des modules Git pour Python? (Je connais GitPython, PyGit et Dulwich - n'hésitez pas à en mentionner d'autres si vous les connaissez.)
J'écris un programme qui devra interagir (ajouter, supprimer, commettre) avec un référentiel Git, mais n'ayant aucune expérience de Git, une des choses que je recherche est la facilité d'utilisation/compréhension de Git.
Les autres choses qui m'intéressent principalement sont la maturité et l'exhaustivité de la bibliothèque, un manque raisonnable de bogues, le développement continu et l'utilité de la documentation et des développeurs.
Si vous pensez à autre chose que je pourrais vouloir/avoir besoin de savoir, n'hésitez pas à le mentionner.
Je pensais pouvoir répondre à ma propre question, car je suis sur un chemin différent de celui suggéré dans les réponses. Néanmoins, merci à ceux qui ont répondu.
Tout d'abord, un bref résumé de mes expériences avec GitPython, PyGit et Dulwich:
En outre, StGit semble intéressant, mais il me faudrait extraire la fonctionnalité dans un module séparé et je ne veux pas attendre que cela se produise maintenant.
Dans (beaucoup) moins de temps que j'ai passé à essayer de faire fonctionner les trois modules ci-dessus, j'ai réussi à faire fonctionner les commandes git via le module de sous-processus, par exemple.
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')
Cela n’est pas encore totalement intégré à mon programme, mais je n’anticipe aucun problème, à part peut-être la rapidité (étant donné que je traiterai parfois des centaines voire des milliers de fichiers).
Peut-être que je n'avais tout simplement pas la patience de faire avancer les choses avec Dulwich ou GitPython. Cela dit, j'espère que les modules recevront plus de développement et seront plus utiles bientôt.
Bien que cette question ait été posée il y a quelque temps et que je ne connaisse pas l'état des bibliothèques à ce stade, il convient de mentionner que GitPython résume bien les outils de ligne de commande afin que vous n'ayez pas besoin d'utiliser sous-processus. Vous pouvez utiliser certaines abstractions intégrées utiles, mais pour tout le reste, vous pouvez faire des choses comme:
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()
Tout le reste dans GitPython facilite simplement la navigation. Je suis assez bien satisfait de cette bibliothèque et je sais que c’est une enveloppe pour les outils git sous-jacents.
UPDATE : Je suis passé à utiliser le module sh pour non seulement git, mais la plupart des utilitaires en ligne de commande dont j'ai besoin en python. Pour reproduire ce qui précède, je le ferais à la place:
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()
C'est une assez vieille question, et en cherchant des bibliothèques Git, j'en ai trouvé une qui a été faite cette année (2013) et qui s'appelle Gittle .
Cela a très bien fonctionné pour moi (là où les autres que j'ai essayés était feuilleté) et semble couvrir la plupart des actions courantes.
Quelques exemples tirés du fichier 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()
Peut-être que ça aide, mais Bazaar et Mercurial utilisent tous deux dulwich pour leur interopérabilité Git.
Dulwich est probablement différent de l'autre en ce sens qu'il s'agit d'une réimplémentation de git en python. L'autre pourrait simplement être un wrapper autour des commandes de Git (donc, il pourrait être plus simple d'utiliser d'un point de vue de haut niveau: commit/add/delete), cela signifie probablement que leur API est très proche de la ligne de commande de git, vous aurez donc besoin acquérir de l'expérience avec Git.
Une réponse mise à jour reflétant les temps modifiés:
GitPython est actuellement le plus facile à utiliser. Il prend en charge le wrapping de nombreuses commandes de git plumbing et possède une base de données d'objet enfichable (dulwich en est une) et, si aucune commande n'est implémentée, fournit une interface facile à utiliser pour décaler en ligne de commande. Par exemple:
repo = Repo('.')
repo.checkout(b='new_branch')
Cela appelle:
bash$ git checkout -b new_branch
Dulwich est également bon mais beaucoup plus bas. Son utilisation est un peu pénible car elle nécessite de manipuler des objets git au niveau de la plomberie et ne contient pas de porcelaine de Nice comme vous le souhaiteriez normalement. Cependant, si vous envisagez de modifier des parties de git ou si vous utilisez git-receive-pack et git-upload-pack, vous devez utiliser dulwich.
Par souci d'exhaustivité, http://github.com/alex/pyvcs/ est une couche d'abstraction pour tous les dvcs. Il utilise dulwich, mais assure l'interopérabilité avec les autres DVD.
La réponse de PTBNL est tout à fait parfaite pour moi. Je fais un peu plus pour l'utilisateur 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)
Voici une implémentation très rapide du "statut git":
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() )
La bibliothèque d'interaction git de StGit est en fait plutôt bonne. Cependant, il ne s'agit pas d'un package séparé, mais si l'intérêt est suffisant, je suis sûr que cela peut être corrigé.
Il a de très jolies abstractions pour représenter les commits, les arbres, etc., et pour créer de nouveaux commits et arbres.