Опыт работы с Python Git Module? [закрыто]

172

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

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

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

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

PTBNL
источник
25
Можем ли мы превратить этот вопрос в вики сообщества? Я чувствую, что лучший ответ изменится со временем.
Рет
4
@relet: это нельзя сделать вики, пока оно закрыто.
PTBNL

Ответы:

119

Хотя этот вопрос был задан некоторое время назад, и я не знаю состояния библиотек на тот момент, стоит отметить, что поисковики 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()
опустошения
источник
2
Отличный инструмент Legit использует GitPython: github.com/kennethreitz/legit/blob/develop/legit/scm.py
forivall
9
Основываясь на этом ответе, я просто попытал счастья с git-python. Я нахожу API странным, чтобы иметь дело с. Большую часть времени вам приходится прибегать к общему интерфейсу repo.git. *, И даже он иногда не работает должным образом (например, repo.git.branch(b=somebranch)работает, но repo.git.branch(D=somebranch)не работает , поскольку пробел отсутствует). Я предполагаю, что сам реализую основную функцию на основе подпроцесса. Мне грустно, у меня были большие надежды. : - /
Кристоф
6
я перешел на использование модуля sh сейчас с git = sh.git.bake(_cwd=repopath). это работает потрясающе.
опустошил
10
ссылка на sh: amoffat.github.io/sh действительно должна быть частью python stdlib.
g33kz0r
4
Последняя версия Python Sh не работает на Windows. Полный полный провал.
void.pointer
81

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

Во-первых, краткий обзор моего опыта работы с 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. Тем не менее, я надеюсь, что модули получат больше развития и будут более полезными в ближайшее время.

PTBNL
источник
25
Этот ответ стареет.
Алекс Чемберлен
3
Да, я был бы заинтересован в обновлении.
JosefAssad
GitPython работает очень хорошо и подробно документирован.
Артур
1
@ Артур Я не согласен, так как я, по крайней мере, 3 часа изучаю документацию StackOverflow и GitPython, просто чтобы понять основы git pull, add, commit и push в удаленном репо, используя его. Документация имеет несколько продвинутых вариантов использования, но не содержит самых основных. Я в основном сдаюсь и использую подпроцесс.
Даниэль Лаведонио де Лима
31

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

Тамале
источник
1
Это также дает лучший доступ к git-сантехнике.
pielgrzym
pygit2действительно полезная библиотека, и я с нетерпением жду ее расширения в будущем!
Алекс Чемберлен
2
Как теперь, нужно вручную загрузить и компиляции / установки полуустойчивых версии обоих libgitи pygit2, принимая источник из GitHub. Проблема в том, что в головных ветках были сломаны тесты, а последняя «стабильная» неудачная установка ... Не подходит, если важна надежность и вам нужно развертывать в различных средах ... :(
mac
1
держитесь подальше от этой комбинации, если вы когда-либо планируете использовать клиентов cygwin. pygit2 - это оболочка для libgit2, а libgit2 прекратила поддержку cygwin. Замечание, которое я получил от одного из разработчиков: «Вы можете попробовать, но это будет чудом, если он создаст» прекрасный API, да, но половина моих клиентов - Cygwin, поэтому я не могу его использовать. Вероятно, собирается GitPython.
scphantm
2
Обратите внимание, что они не поддерживают Cygwin, потому что вместо этого они сосредоточены на собственной поддержке Windows . Поэтому, хотя правильно, что libgit2 не поддерживается Cygwin, это не означает, что пользователи Windows остаются в дураках.
Xiong Chiamiov
19

Это довольно старый вопрос, и, когда я искал библиотеки 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()
гак
источник
2
мне не нравится, что вы «ставите» файлы вместо того, чтобы «добавлять» их в индекс. изменение имен общих / важных операций просто кажется странным.
опустошение
3
@underrun добавление - это добавление файлов на сцену. Разве это не то же самое с промежуточными файлами?
Джимми Кейн
добавление файлов - это подготовка файлов для фиксации (это добавление их в индекс). операция та же, но в командной строке вы набираете текст, git add other1.txt other2.txtчтобы он не соответствовал ожидаемому.
опустился
1
Договорились о превосходстве этого пакета. Я даже смог использовать его в приложении Pythonista после установки StaSh, с которым он был упакован. Кроме того, стоит отметить, что ваш ответ является последним обновленным из ответов на этот вопрос.
Крис Редфорд
1
На самом деле, кажется, это работает только для меня на Pythonista. Получение пароля для аутентификации клона частного репозитория на моем Mac было кошмаром, от которого я наконец отказался.
Крис Редфорд
17

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

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

тонфа
источник
Очень полезный ответ, я не знал, что Mercurial использует Далвич, спасибо!
kissgyorgy
7

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

Джастин Абрамс
источник
7

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

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.

Джон Чу
источник
2

Вот очень быстрая реализация «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() )
Шейн Гейгер
источник
5
Я бы не советовал git status
разбирать
1
Синтаксический анализ git status --shortбыл бы легче, и я думаю, что --shortрезультат будет меньше изменяться.
Бен Пейдж
2
Используйте git status --porcelainдля этого--porcelain: Give the output in a stable, easy-to-parse format for scripts...
Эстани
Или даже лучше, используйте --zвместо --porcelain. В отличие от --porcelain, --zне избегает имен файлов.
Воислав Стойкович
2

Ответ 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)
Билли Джин
источник
4
Я вижу много повторений кода ...: p
Ciasto piekarz
0

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

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

dkagedal
источник
-3

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

xdissent
источник
3
с GitPython: git.Repo (repoDir) .git.status ()
опустошение