Python Git Опыт модулей?

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

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

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

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

Ответ 1

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

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

  • GitPython: после загрузки я получил это импортированное и соответствующий объект инициализирован. Однако попытка сделать то, что было предложено в руководстве, привела к ошибкам. Не имея дополнительной документации, я повернулся в другое место.
  • PyGit: это даже не импортировало бы, и я не мог найти документацию.
  • Dulwich: Кажется, это самый многообещающий (по крайней мере, то, что я хотел и видел). Я сделал некоторый прогресс в этом, больше, чем с 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')

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

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

Ответ 2

Хотя этот вопрос был задан некоторое время назад, и я не знаю состояния библиотек в этот момент, стоит упомянуть для поисковиков, что 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.

UPDATE. Я переключился на использование модуля 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()

Ответ 3

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

Ответ 4

Это довольно старый вопрос, и, ища библиотеки 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="[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()

Ответ 5

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

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

Ответ 6

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

Ответ 7

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

В настоящее время GitPython является самым простым в использовании. Он поддерживает обертку многих команд w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w j Например:

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

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

bash$ git checkout -b new_branch

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

Ответ 8

Ответ 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)

Ответ 9

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

Ответ 10

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

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

Ответ 11

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