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 a git.Repo
object
Initialize a new git Repo¶
# $ git init <path/to/dir> from git import Repo repo = 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 from https://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) for entry in tree] 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¶
def print_files_from_git(root, level=0): for entry in root: print(f'{"-" * 4 * level}| {entry.path}, {entry.type}') if entry.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 git update_file = "dir1/file2.txt" # we'll use local_dir/dir1/file2.txt with open(f"{local_dir}/{update_file}", "a") as f: f.write("\nUpdate version 2")Now lets add the updated file to git
# $ git add <file> add_file = [update_file] # relative path from git root repo.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 root repo.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. with open(f"{local_dir}/Downloads/file3.txt", "w") as f: 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) for d in diffs: print(d.a_path) # Output # Downloads/file3.txt
Diffs¶
Compare staging area to head commit
diffs = repo.index.diff(repo.head.commit) for d in diffs: print(d.a_path) # Output# Let's add untracked.txt. repo.index.add(["untracked.txt"]) diffs = repo.index.diff(repo.head.commit) for d in diffs: 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) for d in diffs: 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 full GitPython tutorial and the API Reference. Happy coding!