GitPython Quick Start Tutorial
Welcome to the GitPython Quickstart Guide! Designed for developers seeking a practical and interactive learning experience, this concise resource offers step-by-step code snippets to swiftly initialize/clone repositories, perform essential Git operations, and explore GitPython’s capabilities. Get ready to dive in, experiment, and unleash the power of GitPython in your projects!
git.Repo
There are a few ways to create agit.Repo
object
Initialize a new git Repo
# $ git init <path/to/dir>fromgitimportReporepo=Repo.init(path_to_dir)
Existing local git Repo
repo=Repo(path_to_dir)
Clone from URL
For the rest of this tutorial we will use a clone fromhttps://github.com/gitpython-developers/QuickStartTutorialFiles.git
# $ git clone <url> <local_dir>repo_url="https://github.com/gitpython-developers/QuickStartTutorialFiles.git"repo=Repo.clone_from(repo_url,local_dir)
Trees & Blobs
Latest Commit Tree
tree=repo.head.commit.tree
Any Commit Tree
prev_commits=list(repo.iter_commits(all=True,max_count=10))# Last 10 commits from all branches.tree=prev_commits[0].tree
Display level 1 Contents
files_and_dirs=[(entry,entry.name,entry.type)forentryintree]files_and_dirs# Output# [(< git.Tree "SHA1-HEX_HASH" >, 'Downloads', 'tree'),# (< git.Tree "SHA1-HEX_HASH" >, 'dir1', 'tree'),# (< git.Blob "SHA1-HEX_HASH" >, 'file4.txt', 'blob')]
Recurse through the Tree
defprint_files_from_git(root,level=0):forentryinroot:print(f'{"-"*4*level}|{entry.path},{entry.type}')ifentry.type=="tree":print_files_from_git(entry,level+1)print_files_from_git(tree)# Output# | Downloads, tree# ----| Downloads / file3.txt, blob# | dir1, tree# ----| dir1 / file1.txt, blob# ----| dir1 / file2.txt, blob# | file4.txt, blob
Usage
Add file to staging area
# We must make a change to a file so that we can add the update to gitupdate_file="dir1/file2.txt"# we'll use local_dir/dir1/file2.txtwithopen(f"{local_dir}/{update_file}","a")asf:f.write("\nUpdate version 2")Now lets add the updated file to git
# $ git add <file>add_file=[update_file]# relative path from git rootrepo.index.add(add_file)# notice the add function requires a list of pathsNotice the add method requires a list as a parameter
Warning: If you experience any trouble with this, try to invoke
git
instead via repo.git.add(path)
Commit
# $ git commit -m <message>repo.index.commit("Update to file2")
List of commits associated with a file
# $ git log <file># Relative path from git rootrepo.iter_commits(all=True,max_count=10,paths=update_file)# Gets the last 10 commits from all branches.# Outputs: <generator object Commit._iter_from_process_or_stream at 0x7fb66c186cf0>Notice this returns a generator object
commits_for_file_generator=repo.iter_commits(all=True,max_count=10,paths=update_file)commits_for_file=list(commits_for_file_generator)commits_for_file# Outputs: [<git.Commit "SHA1-HEX_HASH-2">,# <git.Commit "SHA1-HEX-HASH-1">]returns list of
Commit
objects
Printing text files
Lets print the latest version of<local_dir>/dir1/file2.txt
print_file="dir1/file2.txt"tree[print_file]# The head commit tree.# Output <git.Blob "SHA1-HEX-HASH">blob=tree[print_file]print(blob.data_stream.read().decode())# Output# File 2 version 1# Update version 2Previous version of<local_dir>/dir1/file2.txt
commits_for_file=list(repo.iter_commits(all=True,paths=print_file))tree=commits_for_file[-1].tree# Gets the first commit tree.blob=tree[print_file]print(blob.data_stream.read().decode())# Output# File 2 version 1
Status
Untracked files
Lets create a new file
f=open(f"{local_dir}/untracked.txt","w")# Creates an empty file.f.close()repo.untracked_files# Output: ['untracked.txt']Modified files
# Let's modify one of our tracked files.withopen(f"{local_dir}/Downloads/file3.txt","w")asf:f.write("file3 version 2")# Overwrite file 3.repo.index.diff(None)# Compares staging area to working directory.# Output: [<git.diff.Diff object at 0x7fb66c076e50>,# <git.diff.Diff object at 0x7fb66c076ca0>]returns a list of
Diff
objectsdiffs=repo.index.diff(None)fordindiffs:print(d.a_path)# Output# Downloads/file3.txt
Diffs
Compare staging area to head commit
diffs=repo.index.diff(repo.head.commit)fordindiffs:print(d.a_path)# Output# Let's add untracked.txt.repo.index.add(["untracked.txt"])diffs=repo.index.diff(repo.head.commit)fordindiffs:print(d.a_path)# Output# untracked.txt
Compare commit to commit
first_commit=list(repo.iter_commits(all=True))[-1]diffs=repo.head.commit.diff(first_commit)fordindiffs:print(d.a_path)# Output# dir1/file2.txt
More Resources
Remember, this is just the beginning! There’s a lot more you can achieve with GitPython in your development workflow.To explore further possibilities and discover advanced features, check out the fullGitPython tutorialand theAPI Reference. Happy coding!