Python Git Module Erfahrungen? [geschlossen]

172

Welche Erfahrungen haben die Leute mit einem der Git-Module für Python gemacht? (Ich kenne GitPython, PyGit und Dulwich - zögern Sie nicht, andere zu erwähnen, wenn Sie davon wissen.)

Ich schreibe ein Programm, das mit einem Git-Repository interagieren (hinzufügen, löschen, festschreiben) muss, aber keine Erfahrung mit Git habe. Eines der Dinge, die ich suche, ist die Benutzerfreundlichkeit / das Verständnis in Bezug auf Git.

Die anderen Dinge, die mich hauptsächlich interessieren, sind die Reife und Vollständigkeit der Bibliothek, ein angemessener Mangel an Fehlern, die Weiterentwicklung und die Hilfsbereitschaft der Dokumentation und der Entwickler.

Wenn Sie an etwas anderes denken, das ich wissen möchte / muss, können Sie es gerne erwähnen.

PTBNL
quelle
25
Können wir diese Frage in ein Community-Wiki verwandeln? Ich denke, die beste Antwort wird sich im Laufe der Zeit ändern.
Relet
4
@relet: Es kann kein Wiki erstellt werden, solange es geschlossen ist.
PTBNL

Antworten:

119

Obwohl diese Frage vor einiger Zeit gestellt wurde und ich den Status der Bibliotheken zu diesem Zeitpunkt noch nicht kenne, ist es für Suchende erwähnenswert, dass GitPython die Befehlszeilentools gut abstrahiert, sodass Sie sie nicht verwenden müssen Unterprozess. Es gibt einige nützliche eingebaute Abstraktionen, die Sie verwenden können, aber für alles andere können Sie Dinge tun wie:

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

Alles andere in GitPython erleichtert die Navigation. Ich bin ziemlich zufrieden mit dieser Bibliothek und weiß zu schätzen, dass sie ein Wrapper für die zugrunde liegenden Git-Tools ist.

UPDATE : Ich habe das sh-Modul nicht nur für Git, sondern für die meisten Befehlszeilenprogramme verwendet, die ich in Python benötige. Um das oben Gesagte zu replizieren, würde ich stattdessen Folgendes tun:

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()
unterlaufen
quelle
2
Das ausgezeichnete Legit-Tool verwendet GitPython: github.com/kennethreitz/legit/blob/develop/legit/scm.py
für den
9
Aufgrund dieser Antwort habe ich gerade mein Glück mit Git-Python versucht. Ich finde es seltsam, mit der API umzugehen. Meistens müssen Sie auf die allgemeine Schnittstelle repo.git. * Zurückgreifen, und selbst das funktioniert manchmal nicht richtig (z. B. repo.git.branch(b=somebranch)funktioniert, repo.git.branch(D=somebranch)aber nicht, da ein Leerzeichen fehlt). Ich denke, ich werde selbst eine subprozessbasierte allgemeine Funktion implementieren. Ich bin traurig, ich hatte große Hoffnungen. : - /
Christoph
6
Ich habe jetzt auf die Verwendung des sh-Moduls mit umgestellt git = sh.git.bake(_cwd=repopath). es funktioniert super.
Unterlauf
10
Link zu sh: amoffat.github.io/sh sollte wirklich Teil von Python stdlib sein.
g33kz0r
4
Die neueste Python Sh-Version funktioniert nicht unter Windows. Kompletter völliger Fehlschlag.
void.pointer
81

Ich dachte, ich würde meine eigene Frage beantworten, da ich einen anderen Weg gehe als in den Antworten vorgeschlagen. Trotzdem danke an diejenigen, die geantwortet haben.

Zunächst eine kurze Zusammenfassung meiner Erfahrungen mit GitPython, PyGit und Dulwich:

  • GitPython : Nach dem Herunterladen habe ich dies importiert und das entsprechende Objekt initialisiert. Der Versuch, das zu tun, was im Tutorial vorgeschlagen wurde, führte jedoch zu Fehlern. Da ich keine Dokumentation mehr hatte, wandte ich mich woanders hin.
  • PyGit : Dies würde nicht einmal importiert, und ich konnte keine Dokumentation finden.
  • Dulwich : Scheint am vielversprechendsten zu sein (zumindest für das, was ich wollte und sah). Ich habe damit einige Fortschritte gemacht, mehr als mit GitPython, da sein Ei mit Python-Quelle geliefert wird. Nach einer Weile entschied ich jedoch, dass es möglicherweise einfacher ist, zu versuchen, was ich getan habe.

Auch StGit sieht interessant aus, aber ich würde die Funktionalität in ein separates Modul extrahieren müssen und möchte nicht warten, bis dies jetzt geschieht.

In (viel) weniger Zeit, als ich damit verbracht habe, die drei oben genannten Module zum Laufen zu bringen, gelang es mir, Git-Befehle über das Unterprozessmodul zum Laufen zu bringen, z

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

Dies ist noch nicht vollständig in mein Programm integriert, aber ich erwarte kein Problem, außer vielleicht Geschwindigkeit (da ich manchmal Hunderte oder sogar Tausende von Dateien verarbeiten werde).

Vielleicht hatte ich einfach nicht die Geduld, mit Dulwich oder GitPython etwas in Gang zu bringen. Trotzdem bin ich zuversichtlich, dass die Module bald weiterentwickelt und nützlicher werden.

PTBNL
quelle
25
Diese Antwort wird alt.
Alex Chamberlain
3
Ja, ich würde mich für ein Update interessieren.
JosefAssad
GitPython funktioniert sehr gut und ist ausführlich dokumentiert.
Arthur
1
@Arthur Ich bin anderer Meinung, da ich mindestens 3 Stunden in der StackOverflow- und GitPython-Dokumentation bin, um die Grundlagen von Git Pull, Add, Commit und Push in ein Remote-Repo zu verstehen. Die Dokumentation enthält einige fortgeschrittene Anwendungsfälle, es fehlen jedoch die grundlegenden. Ich gebe im Grunde auf und benutze auch Subprozess.
Daniel Lavedonio de Lima
31

Ich würde pygit2 empfehlen - es verwendet die hervorragenden libgit2- Bindungen

Tamale
quelle
1
Es bietet auch den besten Zugang zu Git-Sanitär.
Pielgrzym
pygit2ist eine wirklich nützliche Bibliothek und ich freue mich darauf, sie in Zukunft zu erweitern!
Alex Chamberlain
2
So wie es jetzt ist, muss man halbstabile Versionen von beiden manuell herunterladen und kompilieren / einrichten libgitund pygit2die Quelle von GitHub entnehmen. Das Problem ist, dass die Hauptzweige fehlerhafte Tests haben und die neueste "stabile" Installation fehlschlägt ... Keine geeignete Lösung, wenn Zuverlässigkeit wichtig ist und Sie in einer Vielzahl von Umgebungen bereitstellen müssen ... :(
mac
1
Halten Sie sich von dieser Kombination fern, wenn Sie jemals planen, dass Kunden Cygwin verwenden. pygit2 ist ein Wrapper für libgit2 und libgit2 hat die gesamte Cygwin-Unterstützung eingestellt. Der Kommentar, den ich von einem der Entwickler erhalten habe: "Sie können es versuchen, aber es ist ein Wunder, wenn es eine schöne API erstellt", ja, aber die Hälfte meiner Kunden sind Cygwin, daher kann ich sie nicht verwenden. Wahrscheinlich gehe ich zu GitPython.
Scphantm
2
Beachten Sie, dass sie Cygwin nicht unterstützen, da ihr Fokus stattdessen auf der nativen Windows-Unterstützung liegt . Obwohl es richtig ist, dass libgit2 auf cygwin nicht unterstützt wird, bedeutet dies nicht , dass Windows-Benutzer im Dunkeln gelassen werden.
Xiong Chiamiov
19

Dies ist eine ziemlich alte Frage, und als ich nach Git-Bibliotheken suchte, fand ich eine, die dieses Jahr (2013) mit dem Namen Gittle erstellt wurde .

Es hat großartig für mich funktioniert (wo die anderen, die ich ausprobiert habe, schuppig waren) und scheint die meisten gängigen Aktionen abzudecken.

Einige Beispiele aus der 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
quelle
2
Ich mag es nicht, dass Sie Dateien "inszenieren", anstatt sie dem Index "hinzuzufügen". Das Ändern der Namen allgemeiner / wichtiger Operationen scheint nur verwirrend zu sein.
Unterlauf
3
@underrun Hinzufügen fügt der Bühne Dateien hinzu. Ist das nicht dasselbe mit Staging-Dateien?
Jimmy Kane
Durch das Hinzufügen von Dateien werden Dateien festgeschrieben, die festgeschrieben werden sollen (sie werden dem Index hinzugefügt). Die Operation ist dieselbe, aber in der Befehlszeile würden Sie eingeben, git add other1.txt other2.txtdamit sie nicht den Erwartungen entspricht.
Unterlauf
1
Einig über die Überlegenheit dieses Pakets. Ich konnte es sogar in der Pythonista-App verwenden, nachdem ich StaSh installiert hatte, mit dem es verpackt war. Es ist auch erwähnenswert, dass Ihre Antwort die zuletzt aktualisierte Antwort auf diese Frage ist.
Chris Redford
1
Eigentlich scheint es nur für mich auf Pythonista zu funktionieren. Es war ein Albtraum, einen Klon eines privaten Bitbucket-Repos auf meinem Mac mit einem Passwort authentifizieren zu lassen, den ich schließlich aufgegeben hatte.
Chris Redford
17

Vielleicht hilft es, aber Bazaar und Mercurial verwenden beide Dulwich für ihre Git-Interoperabilität.

Dulwich ist wahrscheinlich anders als das andere in dem Sinne, dass es eine Neuimplementierung von Git in Python ist. Der andere ist möglicherweise nur ein Wrapper um die Befehle von Git (daher könnte die Verwendung unter einem höheren Gesichtspunkt einfacher sein: Festschreiben / Hinzufügen / Löschen). Dies bedeutet wahrscheinlich, dass sich die API sehr nahe an der Befehlszeile von Git befindet, sodass Sie diese benötigen Erfahrungen mit Git sammeln.

Tonfa
quelle
Sehr nützliche Antwort, ich wusste nicht, dass Mercurial Dulwich verwendet, danke!
Kissgyorgy
7

Der Vollständigkeit halber ist http://github.com/alex/pyvcs/ eine Abstraktionsschicht für alle DVDs. Es verwendet Dulwich, bietet aber Interop mit den anderen DVCs.

Justin Abrahms
quelle
7

Eine aktualisierte Antwort, die geänderte Zeiten widerspiegelt:

GitPython ist derzeit am einfachsten zu bedienen. Es unterstützt das Umschließen vieler Git-Plumbing-Befehle und verfügt über eine steckbare Objektdatenbank (Dulwich ist eine davon). Wenn ein Befehl nicht implementiert ist, bietet es eine einfache API zum Ausgeben an die Befehlszeile. Beispielsweise:

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

Dies ruft auf:

bash$ git checkout -b new_branch

Dulwich ist auch gut, aber viel niedriger. Die Verwendung ist etwas mühsam, da es erforderlich ist, Git-Objekte auf Sanitär-Ebene zu bearbeiten, und kein schönes Porzellan hat, das Sie normalerweise tun möchten. Wenn Sie jedoch Teile von Git ändern oder Git-Receive-Pack und Git-Upload-Pack verwenden möchten, müssen Sie Dulwich verwenden.

Jon Chu
quelle
2

Hier ist eine wirklich schnelle Implementierung von "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
quelle
5
Ich würde das Parsen nicht empfehlengit status
Ehtesh Choudhury
1
Das Parsen git status --shortwäre einfacher, und ich denke, dass sich die --shortAusgabe weniger wahrscheinlich ändert.
Ben Seite
2
Verwenden Sie git status --porcelainfür diese--porcelain: Give the output in a stable, easy-to-parse format for scripts...
estani
Oder noch besser, verwenden Sie --zstatt --porcelain. Im Gegensatz zu --porcelain, --znicht entkommt Dateinamen.
Vojislav Stojkovic
2

Die Antwort von PTBNL ist perfekt für mich. Ich mache ein bisschen mehr für Windows-Benutzer.

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
quelle
4
Ich sehe viele Code-Wiederholungen ...: p
Ciasto piekarz
0

Der Git-Interaktionsbibliotheksteil von StGit ist eigentlich ziemlich gut. Es wird jedoch nicht als separates Paket aufgeteilt, aber wenn genügend Interesse besteht, kann dies sicher behoben werden.

Es hat sehr schöne Abstraktionen zum Darstellen von Commits, Bäumen usw. und zum Erstellen neuer Commits und Bäume.

dkagedal
quelle
-3

Für den Datensatz scheint keine der oben genannten Git Python-Bibliotheken ein "Git-Status" -Äquivalent zu enthalten, was wirklich das einzige ist, was ich möchte, da der Umgang mit den restlichen Git-Befehlen über einen Unterprozess so einfach ist.

xdissent
quelle
3
mit GitPython: git.Repo (repoDir) .git.status ()
unterlaufen