Опыт работы с Python Git Module?

Каков опыт людей с любым из модулей Git для Python? (Я знаю о GitPython, PyGit и Dulwich - не стесняйтесь упоминать других, если вы знаете о них.)

Я пишу программу, которая должна взаимодействовать (добавлять, удалять, фиксировать) с Git-репозиторием, но не иметь опыта работы с Git, поэтому одна из вещей, которые я ищу, - это простота использования / понимания в отношении Git.

Другие вещи, которые меня в первую очередь интересуют, - это зрелость и полнота библиотеки, разумное отсутствие ошибок, постоянное развитие и полезность документации и разработчиков.

Если вы думаете о чем-то еще, что я хотел бы / нужно знать, пожалуйста, не стесняйтесь упоминать об этом.

11 ответов

Решение

Я думал, что отвечу на свой вопрос, так как я иду по другому пути, чем предложено в ответах. Тем не менее, спасибо тем, кто ответил.

Во-первых, краткий обзор моего опыта с GitPython, PyGit и Dulwich:

  • GitPython: После загрузки я импортировал это и инициализировал соответствующий объект. Однако попытка сделать то, что было предложено в руководстве, привела к ошибкам. Не имея больше документации, я обратился в другое место.
  • PyGit: это даже не импортировать, и я не смог найти документацию.
  • Дульвич: Кажется, это самое перспективное (по крайней мере, то, что я хотел и увидел). Я добился некоторого прогресса в этом, больше, чем в GitPython, так как его яйцо поставляется с исходным кодом Python. Однако через некоторое время я решил, что может быть проще попробовать то, что я сделал.

Кроме того, StGit выглядит интересно, но мне нужно, чтобы функциональность была выделена в отдельный модуль, и я не хочу ждать, пока это произойдет прямо сейчас.

За (намного) меньше времени, чем я потратил, пытаясь заставить работать три вышеупомянутых модуля, мне удалось заставить команды git работать через модуль подпроцесса, например

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

Это еще не полностью включено в мою программу, но я не ожидаю проблемы, кроме, возможно, скорости (так как я буду обрабатывать сотни или даже тысячи файлов за раз).

Возможно, у меня просто не хватило терпения наладить отношения с Далвичем или GitPython. Тем не менее, я надеюсь, что модули получат больше развития и будут более полезными в ближайшее время.

Хотя этот вопрос был задан некоторое время назад, и я не знаю состояния библиотек на тот момент, стоит отметить, что поисковики GitPython отлично справляются с абстракцией инструментов командной строки, так что вам не нужно использовать подпроцесс. Есть несколько полезных встроенных абстракций, которые вы можете использовать, но для всего остального вы можете делать такие вещи, как:

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

Все остальное в GitPython просто облегчает навигацию. Я довольно доволен этой библиотекой и понимаю, что она является оберткой для базовых инструментов git.

ОБНОВЛЕНИЕ: я перешел на использование модуля sh не только для git, но и для большинства утилит командной строки, которые мне нужны в python. Чтобы повторить вышеизложенное, я бы сделал это вместо этого:

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

Я бы порекомендовал pygit2 - он использует отличные привязки libgit2

Возможно, это помогает, но Bazaar и Mercurial используют dulwich для своей совместимости с Git.

Далвич, вероятно, отличается от других в том смысле, что это повторная реализация git в python. Другой может быть просто оберткой вокруг команд Git (так что это может быть проще использовать с точки зрения высокого уровня: commit/add/delete), это, вероятно, означает, что их API очень близок к командной строке git, поэтому вам понадобится получить опыт работы с Git.

Это довольно старый вопрос, и, ища библиотеки Git, я нашел один, который был сделан в этом году (2013) и называется Gittle.

Это прекрасно сработало для меня (где другие, которые я пробовал, были нестабильны) и, кажется, покрывают большинство общих действий.

Некоторые примеры из 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="samy@friendco.de", 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()

Обновленный ответ, отражающий изменившиеся времена:

GitPython в настоящее время является самым простым в использовании. Он поддерживает перенос многих команд git plumbing и имеет подключаемую базу данных объектов (dulwich является одной из них), и, если команда не реализована, предоставляет легкий API-интерфейс для обработки командной строки. Например:

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

Это вызывает:

bash$ git checkout -b new_branch

Дульвич тоже хороший, но гораздо более низкий уровень. Это немного болезненно, потому что требует работы с объектами git на уровне сантехники и не имеет хорошего фарфора, который вы обычно хотели бы делать. Однако, если вы планируете модифицировать какие-либо части git или использовать git-receive-pack и git-upload-pack, вам нужно использовать dulwich.

Для полноты http://github.com/alex/pyvcs/ это уровень абстракции для всех dvcs. Он использует Далвич, но обеспечивает взаимодействие с другими DVC.

Ответ PTBNL совершенно идеален для меня. Я делаю немного больше для пользователя 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)

Вот очень быстрая реализация "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() )

Часть библиотеки Git Interaction в StGit на самом деле довольно хороша. Тем не менее, он не разбит на отдельные пакеты, но если есть достаточный интерес, я уверен, что это можно исправить.

Он имеет очень хорошие абстракции для представления коммитов, деревьев и т. Д., А также для создания новых коммитов и деревьев.

Напомним, что ни одна из вышеупомянутых библиотек Git Python, похоже, не содержит эквивалента "git status", что на самом деле является единственной вещью, которую я хотел бы получить, поскольку иметь дело с остальными командами git с помощью подпроцесса.

Другие вопросы по тегам