Is there implementation of Git in pure Python?
-
1@Ignacio +1 for your good sense of humor :) – Piotr Dobrogost Mar 18 '11 at 10:16
-
Voting to close as tool rec. – Ciro Santilli OurBigBook.com May 17 '16 at 13:02
-
1@CiroSantilli包子露宪六四事件法轮功 didn't agree on closing this, here question is not about tool exactly, but about implementation. – Reishin May 11 '18 at 05:21
-
@Reishin too broad then :-) Anyways, nowadays I only close vote dupes, nothing else. – Ciro Santilli OurBigBook.com May 11 '18 at 07:10
2 Answers
Found Dulwich:
Dulwich is a pure-Python implementation of the Git file formats and protocols.
The project is named after the village in which Mr. and Mrs. Git live in the Monty Python sketch.
Looks like a low-level library, the API did not appear friendly to my eyes, but there's a tutorial on the Github page

- 86,532
- 28
- 194
- 218
-
2There is a rendered version here: http://www.samba.org/~jelmer/dulwich/docs/tutorial/index.html – jelmer Jan 05 '12 at 01:33
-
I think most of the "friendly" (high-level) functionality is in the `porcelain` module in accordance with the way git separates high/low level functionality by name. Also, looks like some args are not sully supported (IE `git log` does not seem to support commit range) – ThisGuyCantEven Mar 08 '22 at 22:05
I know that this question is rather old, but I just thought I would add this for the next guy. The accepted answer mentions Dulwich and mentions that it is rather low-level (which is also my opinion). I found gittle which is a high-level wrapper around Dulwich. It's rather easy to use.
Install
$ pip install gittle
Examples (taken from the project's README.md):
Clone a repository
from gittle import Gittle
repo_path = '/tmp/gittle_bare'
repo_url = 'git://github.com/FriendCode/gittle.git'
repo = Gittle.clone(repo_url, repo_path)
Init repository from a path
repo = Gittle.init(path)
Get repository information
# Get list of objects
repo.commits
# Get list of branches
repo.branches
# Get list of modified files (in current working directory)
repo.modified_files
# Get diff between latest commits
repo.diff('HEAD', 'HEAD~1')
Commit
# Stage single file
repo.stage('file.txt')
# 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")
Pull
repo = Gittle(repo_path, origin_uri=repo_url)
# Authentication with RSA private key
key_file = open('/Users/Me/keys/rsa/private_rsa')
repo.auth(pkey=key_file)
# Do pull
repo.pull()
Push
repo = Gittle(repo_path, origin_uri=repo_url)
# Authentication with RSA private key
key_file = open('/Users/Me/keys/rsa/private_rsa')
repo.auth(pkey=key_file)
# Do push
repo.push()
Branch
# Create branch off master
repo.create_branch('dev', 'master')
# Checkout the branch
repo.switch_branch('dev')
# Create an empty branch (like 'git checkout --orphan')
repo.create_orphan_branch('NewBranchName')
# Print a list of branches
print(repo.branches)
# Remove a branch
repo.remove_branch('dev')
# Print a list of branches
print(repo.branches)
These are just the parts (again pulled from the project's README.md) which I think would be most common use-cases. You should check out the project yourself if you need more than this.

- 3,552
- 23
- 31
-
2Note that dulwich nowadays also has a ``dulwich.porcelain`` module, which provides higher-level operations. – jelmer Nov 02 '15 at 19:44
-
1You know, I was actually planning on updating this answer because I was just starting to use `dulwich.porcelain`, they did a good job with it too. Everything I've had to do so far has been really easy. – iLoveTux Nov 03 '15 at 02:01
-
1Wait, I should say __you__ did a good job. Thanks for the package, it's great! – iLoveTux Nov 03 '15 at 02:05