Pengalaman Modul Python Git? [Tutup]

172

Apa pengalaman orang dengan modul Git untuk Python? (Saya tahu tentang GitPython, PyGit, dan Dulwich - jangan ragu untuk menyebutkan yang lain jika Anda mengenal mereka.)

Saya menulis sebuah program yang harus berinteraksi (menambah, menghapus, mengkomit) dengan repositori Git, tetapi tidak memiliki pengalaman dengan Git, jadi salah satu hal yang saya cari adalah kemudahan penggunaan / pemahaman sehubungan dengan Git.

Hal lain yang paling saya minati adalah kedewasaan dan kelengkapan perpustakaan, kurangnya bug yang masuk akal, pengembangan berkelanjutan, dan bantuan dokumentasi dan pengembang.

Jika Anda memikirkan hal lain yang saya ingin / perlu ketahui, jangan ragu untuk menyebutkannya.

PTBNL
sumber
25
Bisakah kita mengubah pertanyaan ini menjadi wiki komunitas? Saya merasa jawaban terbaik akan berubah seiring waktu.
Relet
4
@relet: Tidak dapat dibuat wiki selama ditutup.
PTBNL

Jawaban:

119

Sementara pertanyaan ini ditanyakan beberapa waktu lalu dan saya tidak tahu keadaan perpustakaan pada saat itu, perlu disebutkan bagi para pencari bahwa GitPython melakukan pekerjaan yang baik untuk mengabstraksi alat-alat baris perintah sehingga Anda tidak perlu menggunakan subproses. Ada beberapa abstraksi bawaan yang berguna yang dapat Anda gunakan, tetapi untuk semua yang lain, Anda dapat melakukan hal-hal seperti:

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

Segala sesuatu yang lain di GitPython hanya mempermudah navigasi. Saya cukup puas dengan perpustakaan ini dan menghargai bahwa itu adalah pembungkus alat git yang mendasarinya.

UPDATE : Saya telah beralih menggunakan modul sh untuk tidak hanya git tetapi sebagian besar utilitas commandline yang saya butuhkan dalam python. Untuk meniru di atas saya akan melakukan ini sebagai gantinya:

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
sumber
2
Alat Legit yang sangat baik menggunakan GitPython: github.com/kennethreitz/legit/blob/develop/legit/scm.py
forivall
9
Berdasarkan jawaban ini, saya baru saja mencoba keberuntungan saya dengan git-python. Saya menemukan API aneh untuk dihadapi. Sebagian besar waktu Anda harus kembali ke antarmuka umum repo.git. *, Dan bahkan itu kadang-kadang tidak berfungsi dengan baik (mis. repo.git.branch(b=somebranch)Berfungsi tetapi repo.git.branch(D=somebranch)tidak karena ada ruang yang hilang). Saya kira saya akan mengimplementasikan fungsi umum berbasis subproses sendiri. Aku sedih, aku punya harapan besar. : - /
Christoph
6
Saya sudah beralih menggunakan modul sh sekarang dengan git = sh.git.bake(_cwd=repopath). itu bekerja dengan sangat baik.
underrun
10
tautan ke sh: amoffat.github.io/sh benar-benar harus menjadi bagian dari python stdlib.
g33kz0r
4
Versi python sh terbaru tidak berfungsi di Windows. Benar-benar gagal total.
void.pointer
81

Saya pikir saya akan menjawab pertanyaan saya sendiri, karena saya mengambil jalan yang berbeda dari yang disarankan dalam jawaban. Meskipun demikian, terima kasih kepada mereka yang menjawab.

Pertama, sinopsis singkat pengalaman saya dengan GitPython, PyGit, dan Dulwich:

  • GitPython : Setelah mengunduh, saya mendapatkan ini diimpor dan objek yang sesuai diinisialisasi. Namun, mencoba melakukan apa yang disarankan dalam tutorial menyebabkan kesalahan. Karena tidak memiliki lebih banyak dokumentasi, saya berbalik ke tempat lain.
  • PyGit : Ini bahkan tidak akan diimpor, dan saya tidak dapat menemukan dokumentasi.
  • Dulwich : Tampaknya menjadi yang paling menjanjikan (setidaknya untuk apa yang saya inginkan dan lihat). Saya membuat beberapa kemajuan dengannya, lebih dari dengan GitPython, karena telurnya berasal dari sumber Python. Namun, setelah beberapa saat, saya memutuskan mungkin lebih mudah untuk mencoba apa yang saya lakukan.

Juga, StGit terlihat menarik, tetapi saya akan membutuhkan fungsionalitas diekstraksi menjadi modul terpisah dan tidak ingin menunggu itu terjadi sekarang.

Dalam waktu (jauh) lebih sedikit daripada yang saya habiskan untuk mendapatkan tiga modul di atas bekerja, saya berhasil mendapatkan perintah git bekerja melalui modul subproses, misalnya

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

Ini belum sepenuhnya dimasukkan ke dalam program saya, tapi saya tidak mengantisipasi masalah, kecuali mungkin kecepatan (karena saya akan memproses ratusan atau bahkan ribuan file di kali).

Mungkin saya tidak punya kesabaran untuk menyelesaikan masalah dengan Dulwich atau GitPython. Yang mengatakan, saya berharap modul akan mendapatkan lebih banyak pengembangan dan lebih bermanfaat segera.

PTBNL
sumber
25
Jawaban ini semakin tua.
Alex Chamberlain
3
Ya, saya akan tertarik dengan pembaruan.
JosefAssad
GitPython bekerja dengan sangat baik & didokumentasikan secara luas.
Arthur
1
@Arthur saya tidak setuju, karena saya setidaknya 3 jam ke StackOverflow dan dokumentasi GitPython hanya untuk memahami dasar-dasar git pull, menambah, komit, dan mendorong repo jarak jauh menggunakannya. Dokumentasi memang memiliki beberapa kasus penggunaan lanjutan, tetapi tidak memiliki yang sangat mendasar. Saya pada dasarnya menyerah dan menggunakan subproses juga.
Daniel Lavedonio de Lima
31

Saya akan merekomendasikan pygit2 - ia menggunakan binding libgit2 yang sangat baik

tamale
sumber
1
Ini memberikan akses terbaik ke pipa git juga.
pielgrzym
pygit2adalah perpustakaan yang sangat berguna, dan saya menantikannya berkembang di masa depan!
Alex Chamberlain
2
Seperti sekarang, kita harus mengunduh dan mengkompilasi / mengatur versi semi-stabil keduanya libgitdan pygit2mengambil sumber dari GitHub secara manual . Masalahnya adalah, kepala cabang telah melanggar tes, dan instalasi gagal "stabil" terbaru ... Bukan solusi yang cocok jika keandalan penting dan Anda perlu menggunakan di berbagai lingkungan ... :(
mac
1
menjauhlah dari kombinasi ini jika Anda berencana untuk klien menggunakan cygwin. pygit2 adalah pembungkus untuk libgit2 dan libgit2 telah menjatuhkan semua dukungan cygwin. Komentar yang saya dapatkan dari salah satu dev, "Anda dapat mencoba, tetapi itu adalah keajaiban jika membangun" API yang indah, ya, tetapi setengah klien saya adalah cygwin, oleh karena itu saya tidak dapat menggunakannya. Mungkin pergi ke GitPython.
scphantm
2
Perhatikan bahwa mereka tidak mendukung cygwin karena fokus mereka adalah pada dukungan Windows asli . Jadi sementara benar bahwa libgit2 tidak didukung di cygwin, itu tidak berarti bahwa pengguna Windows ditinggalkan dalam dingin.
Xiong Chiamiov
19

Ini adalah pertanyaan yang cukup lama, dan saat mencari perpustakaan Git, saya menemukan satu yang dibuat tahun ini (2013) bernama Gittle .

Ini bekerja sangat baik untuk saya (di mana yang lain saya coba terkelupas), dan tampaknya mencakup sebagian besar tindakan umum.

Beberapa contoh dari 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
sumber
2
saya tidak suka bahwa Anda "panggung" file, bukan "menambahkan" mereka ke indeks. mengubah nama operasi umum / penting sepertinya akan membingungkan.
underrun
3
Menambahkan @underrun menambahkan file ke panggung. Bukankah itu sama dengan pementasan file?
Jimmy Kane
menambahkan file adalah pementasan file yang akan dikomit (itu menambahkannya ke indeks). operasinya sama tetapi pada baris perintah Anda mengetik git add other1.txt other2.txtsehingga tidak mengikuti apa yang diharapkan.
underrun
1
Menyetujui keunggulan paket ini. Saya bahkan bisa menggunakannya di dalam aplikasi Pythonista setelah menginstal StaSh, yang dikemas dengan itu. Juga, perlu dicatat bahwa jawaban Anda adalah yang terakhir diperbarui dari jawaban untuk pertanyaan ini.
Chris Redford
1
Sebenarnya, sepertinya hanya bekerja untuk saya di Pythonista. Mendapatkannya dengan kata sandi mengotentikasi klon dari repo bitbucket pribadi di Mac saya adalah mimpi buruk yang akhirnya saya menyerah.
Chris Redford
17

Mungkin itu membantu, tetapi Bazaar dan Mercurial sama-sama menggunakan dulwich untuk interoperabilitas Git mereka.

Dulwich mungkin berbeda dari yang lain dalam arti itu adalah implementasi ulang git di python. Yang lain mungkin hanya menjadi pembungkus di sekitar perintah Git (jadi bisa lebih mudah untuk digunakan dari sudut pandang tingkat tinggi: komit / tambahkan / hapus), itu mungkin berarti API mereka sangat dekat dengan baris perintah git sehingga Anda akan perlu untuk mendapatkan pengalaman dengan Git.

tonfa
sumber
Jawaban yang sangat berguna, saya tidak tahu bahwa Mercurial menggunakan Dulwich, terima kasih!
kissgyorgy
7

Demi kelengkapan, http://github.com/alex/pyvcs/ adalah lapisan abstraksi untuk semua dvcs. Ini menggunakan dulwich, tetapi menyediakan interop dengan dvcs lain.

Justin Abrahms
sumber
7

Jawaban yang diperbarui mencerminkan waktu yang berubah:

GitPython saat ini adalah yang paling mudah digunakan. Ini mendukung pembungkus banyak perintah git plumbing dan memiliki database objek pluggable (dulwich salah satunya), dan jika sebuah perintah tidak diimplementasikan, memberikan api yang mudah untuk keluar ke baris perintah. Sebagai contoh:

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

Ini panggilan:

bash$ git checkout -b new_branch

Dulwich juga bagus tapi levelnya jauh lebih rendah. Agak menyakitkan untuk digunakan karena membutuhkan operasi pada objek git di tingkat pipa ledeng dan tidak memiliki porselen bagus yang biasanya ingin Anda lakukan. Namun, jika Anda berencana memodifikasi bagian git, atau menggunakan paket git-accept-pack dan git-upload-pack, Anda perlu menggunakan dulwich.

Jon Chu
sumber
2

Berikut ini adalah implementasi "git status" yang sangat cepat:

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
sumber
5
Saya tidak akan merekomendasikan parsinggit status
Ehtesh Choudhury
1
Parsing git status --shortakan lebih mudah, dan saya pikir --shortoutput cenderung berubah.
Ben Page
2
Gunakan git status --porcelainuntuk ini--porcelain: Give the output in a stable, easy-to-parse format for scripts...
estani
Atau bahkan lebih baik, gunakan --zsaja --porcelain. Tidak seperti itu --porcelain, --ztidak luput dari nama file.
Vojislav Stojkovic
2

Jawaban PTBNL cukup sempurna untuk saya. Saya membuat sedikit lebih banyak untuk pengguna 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
sumber
4
Saya melihat banyak pengulangan kode ...: p
Ciasto piekarz
0

Bagian pustaka interaksi git dari StGit sebenarnya cukup bagus. Namun, itu tidak pecah sebagai paket terpisah tetapi jika ada minat yang cukup, saya yakin itu bisa diperbaiki.

Ini memiliki abstraksi yang sangat bagus untuk mewakili komit, pohon dll, dan untuk membuat komit dan pohon baru.

dkagedal
sumber
-3

Sebagai catatan, tidak ada pustaka Git Python yang disebutkan di atas yang tampaknya mengandung "git status" yang setara, yang merupakan satu-satunya hal yang saya inginkan karena berurusan dengan sisa perintah git melalui subproses sangat mudah.

Xdissent
sumber
3
dengan GitPython: git.Repo (repoDir) .git.status ()
underrun