Experiencias del módulo Python Git? [cerrado]

172

¿Cuáles son las experiencias de las personas con cualquiera de los módulos Git para Python? (Sé de GitPython, PyGit y Dulwich, siéntete libre de mencionar a otros si los conoces).

Estoy escribiendo un programa que tendrá que interactuar (agregar, eliminar, confirmar) con un repositorio de Git, pero no tengo experiencia con Git, por lo que una de las cosas que estoy buscando es la facilidad de uso / comprensión con respecto a Git.

Las otras cosas que me interesan principalmente son la madurez y la integridad de la biblioteca, la falta razonable de errores, el desarrollo continuo y la utilidad de la documentación y los desarrolladores.

Si piensa en otra cosa que tal vez quiera / necesite saber, no dude en mencionarlo.

PTBNL
fuente
25
¿Podemos convertir esta pregunta en una wiki comunitaria? Siento que la mejor respuesta cambiará con el tiempo.
relet
44
@relet: No se puede hacer wiki mientras esté cerrado.
PTBNL

Respuestas:

119

Si bien esta pregunta se hizo hace un tiempo y no conozco el estado de las bibliotecas en ese momento, vale la pena mencionar para los buscadores que GitPython hace un buen trabajo al abstraer las herramientas de línea de comandos para que no necesite usar subproceso Hay algunas abstracciones útiles incorporadas que puedes usar, pero para todo lo demás puedes hacer cosas como:

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

Todo lo demás en GitPython solo facilita la navegación. Estoy bastante satisfecho con esta biblioteca y aprecio que sea un contenedor de las herramientas git subyacentes.

ACTUALIZACIÓN : He cambiado a usar el módulo sh no solo para git sino para la mayoría de las utilidades de línea de comandos que necesito en python. Para replicar lo anterior, haría esto en su lugar:

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
fuente
2
La excelente herramienta Legit utiliza GitPython: github.com/kennethreitz/legit/blob/develop/legit/scm.py
forivall
9
Basado en esta respuesta, acabo de probar suerte con git-python. Me resulta extraño tratar con la API. La mayoría de las veces tiene que recurrir a la interfaz general repo.git. *, E incluso eso no funciona correctamente a veces (por ejemplo, repo.git.branch(b=somebranch)funciona, pero repo.git.branch(D=somebranch)no lo hace, ya que falta un espacio). Creo que yo mismo implementaré una función general basada en subprocesos. Estoy triste, tenía muchas esperanzas. : - /
Christoph
66
He cambiado a usar el módulo sh ahora con git = sh.git.bake(_cwd=repopath). Funciona increíblemente.
Underrun
10
enlace a sh: amoffat.github.io/sh realmente debería ser parte de python stdlib.
g33kz0r
44
La última versión de python sh no funciona en Windows. Completa falla total.
void.pointer
81

Pensé que respondería a mi propia pregunta, ya que estoy tomando un camino diferente al sugerido en las respuestas. Sin embargo, gracias a quienes respondieron.

Primero, una breve sinopsis de mis experiencias con GitPython, PyGit y Dulwich:

  • GitPython : Después de descargar, importé esto y se inicializó el objeto apropiado. Sin embargo, tratar de hacer lo que se sugirió en el tutorial condujo a errores. Al carecer de más documentación, recurrí a otro lado.
  • PyGit : Esto ni siquiera importaría, y no pude encontrar documentación.
  • Dulwich : Parece ser el más prometedor (al menos para lo que quería y vi). Hice algunos progresos con él, más que con GitPython, ya que su huevo viene con la fuente Python. Sin embargo, después de un tiempo, decidí que podría ser más fácil probar lo que hice.

Además, StGit parece interesante, pero necesitaría la funcionalidad extraída en un módulo separado y no quiero esperar a que eso suceda en este momento.

En (mucho) menos tiempo del que pasé tratando de hacer que los tres módulos anteriores funcionen, logré que los comandos git funcionen a través del módulo de subproceso, por ejemplo

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

Esto aún no está completamente incorporado a mi programa, pero no estoy anticipando un problema, excepto tal vez la velocidad (ya que a veces estaré procesando cientos o incluso miles de archivos).

Tal vez simplemente no tuve la paciencia para poner las cosas en marcha con Dulwich o GitPython. Dicho esto, espero que los módulos tengan más desarrollo y sean más útiles pronto.

PTBNL
fuente
25
Esta respuesta se está haciendo vieja.
Alex Chamberlain el
3
Sí, me interesaría una actualización.
JosefAssad
GitPython funciona muy bien y está ampliamente documentado.
Arthur
1
@Arthur No estoy de acuerdo, ya que tengo al menos 3 horas en la documentación de StackOverflow y GitPython solo para comprender los conceptos básicos de git pull, add, commit y push en un repositorio remoto usándolo. La documentación tiene algunos casos de uso avanzados, pero carece de los muy básicos. Básicamente, me estoy rindiendo y también estoy usando el subproceso.
Daniel Lavedonio de Lima
31

Recomiendo pygit2 : utiliza los excelentes enlaces libgit2

tamal
fuente
1
Da el mejor acceso a la fontanería git también.
pielgrzym
pygit2es una biblioteca realmente útil, ¡y espero que se expanda en el futuro!
Alex Chamberlain el
2
Tal como está ahora, uno debe descargar manualmente y compilar / configurar versiones semi-estables de ambos libgity pygit2, tomando la fuente de GitHub. El problema es que las ramas principales tienen pruebas rotas y la última instalación "estable" falla ... No es una solución adecuada si la confiabilidad es importante y necesita implementar en una variedad de entornos ... :(
mac
1
manténgase alejado de esta combinación si alguna vez planea clientes que usan cygwin. pygit2 es un contenedor para libgit2 y libgit2 ha eliminado todo el soporte de cygwin. El comentario que recibí de uno de los desarrolladores, "Puedes intentarlo, pero sería un milagro si se construye" API hermosa, sí, pero la mitad de mis clientes son cygwin, por lo tanto, no puedo usarlo. Probablemente vaya a GitPython.
scphantm
2
Tenga en cuenta que no son compatibles con cygwin porque en su lugar se centran en el soporte nativo de Windows . Entonces, aunque es correcto que libgit2 no sea compatible con cygwin, no significa que los usuarios de Windows se queden fuera.
Xiong Chiamiov
19

Esta es una pregunta bastante antigua, y mientras buscaba bibliotecas de Git, encontré una que se hizo este año (2013) llamada Gittle .

Funcionó muy bien para mí (donde los otros que probé eran escamosos), y parece cubrir la mayoría de las acciones comunes.

Algunos ejemplos de 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
fuente
2
no me gusta que "organice" los archivos en lugar de "agregarlos" al índice. cambiar los nombres de operaciones comunes / importantes parece ser confuso.
Underrun
3
@underrun agregar es agregar archivos al escenario. ¿No es lo mismo con los archivos de ensayo?
Jimmy Kane
agregar archivos está preparando archivos para confirmar (los agrega al índice). la operación es la misma pero en la línea de comando escribiría git add other1.txt other2.txtpara que no siga lo que se esperaría.
underrun
1
De acuerdo en la superioridad de este paquete. Incluso he podido usarlo dentro de la aplicación Pythonista después de instalar StaSh, con el que estaba empaquetado. Además, vale la pena señalar que su respuesta es la más actualizada de las respuestas a esta pregunta.
Chris Redford
1
En realidad, parece que solo funciona para mí en Pythonista. Conseguir que autentique con contraseña un clon de un repositorio privado de bitbucket en mi Mac fue una pesadilla que finalmente abandoné.
Chris Redford
17

Quizás ayude, pero Bazaar y Mercurial están usando dulwich para su interoperabilidad Git.

Dulwich es probablemente diferente al otro en el sentido de que es una reimplementación de git en python. El otro podría ser un envoltorio alrededor de los comandos de Git (por lo que podría ser más simple de usar desde un punto de vista de alto nivel: commit / add / delete), probablemente significa que su API está muy cerca de la línea de comandos de git, por lo que necesitará para ganar experiencia con Git.

tonfa
fuente
Respuesta muy útil, no sabía que Mercurial usa Dulwich, ¡gracias!
kissgyorgy
7

En aras de la integridad, http://github.com/alex/pyvcs/ es una capa de abstracción para todos los dvcs. Utiliza dulwich, pero proporciona interoperabilidad con los otros dvcs.

Justin Abrahms
fuente
7

Una respuesta actualizada que refleja los tiempos cambiados:

GitPython actualmente es el más fácil de usar. Admite la envoltura de muchos comandos de fontanería git y tiene una base de datos de objetos conectables (dulwich es uno de ellos), y si no se implementa un comando, proporciona una API fácil para desviarse a la línea de comando. Por ejemplo:

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

Esto llama:

bash$ git checkout -b new_branch

Dulwich también es bueno pero de nivel mucho más bajo. Es un poco difícil de usar porque requiere operar con objetos de git a nivel de plomería y no tiene una buena porcelana que normalmente querría hacer. Sin embargo, si planea modificar alguna parte de git, o usa git-recibir-paquete y git-upload-pack, debe usar dulwich.

Jon Chu
fuente
2

Aquí hay una implementación realmente rápida del "estado de 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() )
Shane Geiger
fuente
55
No recomendaría el análisisgit status
Ehtesh Choudhury
1
El análisis git status --shortsería más fácil y creo --shortque es menos probable que cambie la salida.
Ben Page
2
Úselo git status --porcelainpara esto--porcelain: Give the output in a stable, easy-to-parse format for scripts...
estani
O incluso mejor, use en --zlugar de --porcelain. A diferencia --porcelain, --zno escapa a los nombres de archivo.
Vojislav Stojkovic
2

La respuesta de PTBNL es bastante perfecta para mí. Hago un poco más para el usuario de 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
fuente
44
Veo mucha repetición de código ...: p
Ciasto piekarz
0

La parte de la biblioteca de interacción git de StGit es bastante buena. Sin embargo, no se desglosa como un paquete separado, pero si hay suficiente interés, estoy seguro de que se puede solucionar.

Tiene muy buenas abstracciones para representar commits, árboles, etc., y para crear nuevos commits y árboles.

dkagedal
fuente
-3

Para el registro, ninguna de las bibliotecas de Git Python mencionadas parece contener un equivalente de "estado de git", que es realmente lo único que desearía, ya que tratar con el resto de los comandos de git a través de un subproceso es tan fácil.

xdissent
fuente
3
con GitPython: git.Repo (repoDir) .git.status ()
empotramiento