Expériences du module Python Git? [fermé]

172

Quelles sont les expériences des gens avec l'un des modules Git pour Python? (Je connais GitPython, PyGit et Dulwich - n'hésitez pas à en mentionner d'autres si vous en connaissez.)

J'écris un programme qui devra interagir (ajouter, supprimer, valider) avec un référentiel Git, mais je n'ai aucune expérience avec Git, donc l'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 à quelque chose d'autre que je pourrais souhaiter / avoir besoin de savoir, n'hésitez pas à le mentionner.

PTBNL
la source
25
Pouvons-nous transformer cette question en un wiki communautaire? Je pense que la meilleure réponse changera avec le temps.
sortie le
4
@relet: Il ne peut pas être fait wiki tant qu'il est fermé.
PTBNL

Réponses:

119

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 aux chercheurs que GitPython fait un bon travail d'abstraction des outils de ligne de commande afin que vous n'ayez pas besoin d'utiliser sous-processus. Il existe des abstractions intégrées utiles que vous pouvez utiliser, 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 satisfait de cette bibliothèque et j'apprécie qu'il s'agit d'un wrapper sur les outils git sous-jacents.

MISE À JOUR : Je suis passé à l'utilisation du module sh non seulement pour git, mais aussi pour la plupart des utilitaires de 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()
underrun
la source
2
L'excellent outil Legit utilise GitPython: github.com/kennethreitz/legit/blob/develop/legit/scm.py
forivall
9
Sur la base de cette réponse, je viens de tenter ma chance avec git-python. Je trouve l'API étrange à gérer. La plupart du temps, vous devez revenir à l'interface générale repo.git. *, Et même cela ne fonctionne pas correctement à certains moments (par exemple repo.git.branch(b=somebranch)fonctionne mais repo.git.branch(D=somebranch)ne fonctionne pas car il manque un espace). Je suppose que je vais implémenter moi-même une fonction générale basée sur un sous-processus. Je suis triste, j'avais de grands espoirs. : - /
Christoph
6
Je suis maintenant passé à l'utilisation du module sh avec git = sh.git.bake(_cwd=repopath). cela fonctionne à merveille.
underrun
10
lien vers sh: amoffat.github.io/sh devrait vraiment faire partie de python stdlib.
g33kz0r
4
La dernière version de python sh ne fonctionne pas sous Windows. Échec total complet.
void.pointer
81

J'ai pensé que je répondrais à ma propre question, car je prends 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:

  • GitPython : Après le téléchargement, je l'ai importé et l'objet approprié initialisé. Cependant, essayer de faire ce qui a été suggéré dans le didacticiel a conduit à des erreurs. Faute de plus de documentation, je me suis tourné ailleurs.
  • PyGit : Cela ne serait même pas importé, et je n'ai trouvé aucune documentation.
  • Dulwich : Semble être le plus prometteur (au moins pour ce que je voulais et vu). J'ai fait quelques progrès avec lui, plus qu'avec GitPython, puisque son œuf est livré avec la source Python. Cependant, après un certain temps, j'ai décidé qu'il serait peut-être plus facile d'essayer ce que j'avais fait.

De plus, StGit semble intéressant, mais j'aurais besoin de la fonctionnalité extraite dans un module séparé et je ne veux pas attendre que cela se produise maintenant.

En (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')

Ce n'est pas encore totalement intégré à mon programme, mais je n'anticipe pas de problème, sauf peut-être la vitesse (puisque 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 bénéficieront de plus de développement et seront bientôt plus utiles.

PTBNL
la source
25
Cette réponse vieillit.
Alex Chamberlain
3
Oui, je serais intéressé par une mise à jour.
JosefAssad
GitPython fonctionne très bien et est largement documenté.
Arthur
1
@Arthur Je ne suis pas d'accord, car je suis au moins 3 heures dans la documentation StackOverflow et GitPython juste pour comprendre les bases de git pull, ajouter, valider et pousser dans un dépôt distant en l'utilisant. La documentation contient des cas d'utilisation avancés, mais manque les éléments très basiques. J'abandonne fondamentalement et j'utilise également un sous-processus.
Daniel Lavedonio de Lima
31

Je recommanderais pygit2 - il utilise les excellentes liaisons libgit2

tamale
la source
1
Il donne également le meilleur accès à la plomberie git.
pielgrzym
pygit2est une bibliothèque vraiment utile, et j'ai hâte qu'elle s'agrandisse à l'avenir!
Alex Chamberlain
2
Dans l'état actuel des choses, il faut télécharger et compiler / configurer manuellement des versions semi-stables des deux libgitet pygit2, en prenant la source de GitHub. Le problème est que les branches principales ont des tests cassés et la dernière installation échoue «stable» ... Pas une solution appropriée si la fiabilité est importante et que vous devez déployer dans une variété d'environnements ... :(
mac
1
éloignez-vous de cette combinaison si jamais vous prévoyez des clients utilisant cygwin. pygit2 est un wrapper pour libgit2 et libgit2 a abandonné tout support cygwin. Le commentaire que j'ai reçu de l'un des développeurs, "Vous pouvez essayer, mais ce serait un miracle s'il construit" une belle API, oui, mais la moitié de mes clients sont cygwin donc je ne peux pas l'utiliser. Aller probablement à GitPython.
scphantm
2
Notez qu'ils ne prennent pas en charge cygwin car ils se concentrent plutôt sur la prise en charge native de Windows . Donc, s'il est correct que libgit2 n'est pas pris en charge sur cygwin, cela ne signifie pas que les utilisateurs de Windows sont laissés pour compte.
Xiong Chiamiov
19

C'est une question assez ancienne, et en cherchant des bibliothèques Git, j'en ai trouvé une qui a été faite cette année (2013) appelée Gittle .

Cela a très bien fonctionné pour moi (là où les autres que j'ai essayés étaient floconneux) et semble couvrir la plupart des actions courantes.

Quelques exemples du 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()
gak
la source
2
Je n'aime pas que vous "prépariez" des fichiers au lieu de les "ajouter" à l'index. changer les noms d'opérations courantes / importantes semble simplement déroutant.
underrun
3
@underrun l'ajout ajoute des fichiers à la scène. N'est-ce pas la même chose avec les fichiers intermédiaires?
Jimmy Kane
l'ajout de fichiers consiste à préparer les fichiers à valider (c'est à les ajouter à l'index). l'opération est la même mais sur la ligne de commande, vous devez taper git add other1.txt other2.txtpour qu'elle ne suive pas ce à quoi on s'attend.
underrun
1
Convenu de la supériorité de ce package. J'ai même pu l'utiliser dans l'application Pythonista après avoir installé StaSh, avec lequel il était fourni. En outre, il convient de noter que votre réponse est la plus récemment mise à jour parmi les réponses à cette question.
Chris Redford le
1
En fait, cela semble ne fonctionner que pour moi sur Pythonista. Obtenir l'authentification par mot de passe d'un clone d'un dépôt bitbucket privé sur mon Mac était un cauchemar auquel j'ai finalement abandonné.
Chris Redford le
17

Peut-être que cela aide, mais Bazaar et Mercurial utilisent tous les 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 (il pourrait donc être plus simple à 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 pour acquérir de l'expérience avec Git.

tonfa
la source
Réponse très utile, je ne savais pas que Mercurial utilisait Dulwich, merci!
kissgyorgy
7

Par souci d'exhaustivité, http://github.com/alex/pyvcs/ est une couche d'abstraction pour tous les dvcs. Il utilise dulwich, mais fournit une interopérabilité avec les autres dvcs.

Justin Abrahms
la source
7

Une réponse mise à jour reflétant les temps modifiés:

GitPython est actuellement le plus simple à utiliser. Il prend en charge l'encapsulation de nombreuses commandes de plomberie git et possède une base de données d'objets enfichables (dulwich étant l'un d'entre eux), et si une commande n'est pas implémentée, fournit une API facile pour la transmission à la ligne de commande. Par exemple:

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

Cela appelle:

bash$ git checkout -b new_branch

Dulwich est également bon niveau mais bien inférieur. C'est un peu pénible à utiliser car cela nécessite d'opérer sur des objets git au niveau de la plomberie et n'a pas de belle porcelaine que vous voudriez normalement faire. Cependant, si vous prévoyez de modifier une partie de git ou d'utiliser git-receive-pack et git-upload-pack, vous devez utiliser dulwich.

Jon Chu
la source
2

Voici une implémentation très rapide de "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() )
Shane Geiger
la source
5
Je ne recommanderais pas l'analysegit status
Ehtesh Choudhury
1
L'analyse git status --shortserait plus facile, et je pense que la --shortsortie est moins susceptible de changer.
Ben Page
2
Utilisez git status --porcelainpour cela--porcelain: Give the output in a stable, easy-to-parse format for scripts...
estani
Ou mieux encore, utilisez à la --zplace de --porcelain. Contrairement à --porcelain, --zn'échappe pas aux noms de fichiers.
Vojislav Stojkovic
2

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)
Billy Jin
la source
4
Je vois beaucoup de répétition de code ...: p
Ciasto piekarz
0

La partie bibliothèque d'interaction git de StGit est en fait assez bonne. Cependant, ce n'est pas un package séparé, mais s'il y a suffisamment d'intérêt, je suis sûr que cela peut être corrigé.

Il a de très belles abstractions pour représenter les commits, les arbres, etc., et pour créer de nouveaux commits et arbres.

dkagedal
la source
-3

Pour mémoire, aucune des bibliothèques Git Python susmentionnées ne semble contenir d'équivalent "git status", ce qui est vraiment la seule chose que je voudrais car traiter le reste des commandes git via un sous-processus est si facile.

xdissent
la source
3
avec GitPython: git.Repo (repoDir) .git.status ()
underrun