Bring Your Git Repository to Life: Animating Commit History with git-story

As developers, we rely heavily on version control systems like Git to manage our code projects. Git tracks every change made to the codebase, providing a detailed history of the project‘s evolution over time. While Git‘s commit logs and diff outputs are informative, they can be a bit dry and abstract. Wouldn‘t it be nice to actually see your repository‘s commit graph come to life in a more visual and engaging way?

Enter git-story – an innovative command-line tool that generates an animated video of your Git commit history with a single command. Instead of trying to picture the commit tree in your head, you can now watch it grow and branch before your very eyes!

In this article, we‘ll take an in-depth look at what git-story is, how it works under the hood, and how you can use it to create compelling visualizations of your own Git repositories. Let‘s get started on our journey to becoming git-story power users!

What is git-story?

Git-story is an open-source command-line utility that generates a video animation displaying a portion of your Git repository‘s commit history. The output is an MP4 video file that shows each commit as a circle, with arrows connecting parent and child commits to form a directed acyclic graph (DAG).

The animation starts with the oldest commit and progresses forward in time, with new commits emerging and growing the graph. Branch labels, the current HEAD pointer, and tags are also displayed in the video to provide additional context. You can specify how many commits to include and from where in the commit history to start.

Git-story is written in Python and leverages two key libraries:

  1. GitPython – for programmatically extracting data from Git repositories
  2. Manim (Mathematical Animation Engine) – for drawing the commit graph visualization and rendering it as a video

The real power of git-story lies in how quick and easy it makes visualizing your Git history. No more fiddling around with GUI tools or meticulously laying out a commit graph in a drawing app. With a single command, you can generate a professional-looking animation to include in presentations, tutorials, and documentation.

Some example use cases for git-story include:

  • Visualizing the structure and evolution of your Git branching model
  • Demonstrating how Git commands like rebase, cherry-pick and merge affect the commit history
  • Providing a high-level overview of a project‘s progress for sprint reviews and retrospectives
  • Onboarding new developers by showing them how the codebase has grown and diverged over time
  • Livening up educational content like courses, blog posts and talks that teach or discuss Git

Now that we have a basic understanding of what git-story does and why it‘s useful, let‘s peek under the hood and see how it actually works.

How git-story Animates Your Commits

The process of generating a Git commit animation can be broken down into three main stages:

  1. Extracting commit data from Git via GitPython
  2. Constructing a visual representation of the commit DAG using Manim
  3. Animating the commit history as an MP4 video

Let‘s walk through each of these steps in detail to really understand the magic of git-story.

Extracting Commit Data with GitPython

GitPython is a popular Python library that provides a programmatic interface for interacting with Git repositories. It allows you to extract all kinds of data and metrics from a repo, including commits, branches, tags, diffs, and much more.

Git-story uses GitPython to access the underlying Git objects and metadata needed to generate the commit history visualization. The first step is to create a repository object pointing to the current local repo:

import git

repo = git.Repo(search_parent_directories=True)  

This repo object acts as an entry point for querying Git data. To get a list of commit objects to visualize, we can use the iter_commits() method:

commits = list(repo.iter_commits(REF))

The REF parameter specifies the starting point for the commit traversal. It can be the name of a branch (e.g. "main"), a tag, the literal HEAD, or a commit hash. By default, git-story starts at HEAD and works backwards to get the most recent commits.

The iter_commits() method returns an iterator of commit objects. We convert it to a list to make subsequent processing easier. Each commit object provides access to metadata like:

  • Hash – The unique SHA-1 ID of the commit
  • Author – The name and email of the commit author
  • Committer – The name and email of the person who created the commit
  • Committed DateTime – Timestamp of when the commit was created
  • Message – The commit message describing the change
  • Parents – List of parent commit objects

Git-story extracts this metadata for each commit in the selected range. It also parses repository refs like branch names, the current HEAD, and any tags that point to commits in the range.

With all the relevant Git data extracted and organized, we‘re ready to start visualizing!

Constructing a Visual Representation with Manim

Manim is an incredibly powerful Python library for creating precise, professional-looking animations. It provides an intuitive API for defining and positioning simple shapes like circles and arrows, along with support for complex mathematical notation and equations. Manim renders animations as video files that can be easily shared and embedded.

Git-story leverages Manim‘s capabilities to construct a visual representation of the commit history DAG. Each commit is drawn as a circle, with arrows connecting the circles based on the parent/child relationships between commits.

Here‘s a simplified version of how git-story uses Manim to draw a commit circle:

from manim import Circle

circle = Circle(
    stroke_color=commit_fill_color, 
    fill_color=commit_fill_color,
    fill_opacity=0.25
)

This code creates a new Circle object and configures its appearance using the specified color and opacity. The circle represents an individual commit in the history.

To depict the relationships between commits, git-story draws arrows from child commits to their parents:

from manim import Arrow

arrow = Arrow(
    start=child_commit.circle.get_center(), 
    end=parent_commit.circle.get_center(),
    color=arrow_color,
    max_tip_length_to_length_ratio=0.05
)

An Arrow object is created with a starting point at the child commit‘s circle center and an ending point at the parent commit‘s circle center. This visually links the two commits in the correct direction.

For additional context, git-story also draws text labels next to the commit circles. These labels display metadata like the commit hash, branch names, and tags:

from manim import Text

label = Text(
    text=branch_name,
    font="Arial",
    font_size=12,
    color=label_color
).next_to(circle, RIGHT)

The Text object is created with the desired label string and formatting options. The next_to method positions the label to the right of the commit circle.

Git-story repeats this process of drawing circles, arrows, and labels for each commit in the selected range, constructing a complete visual representation of the DAG. The positions of the graphical elements are carefully calculated to ensure a clean, readable layout and avoid overlapping.

With the visualization fully assembled, it‘s time for the final step – animating it!

Animating the Commit History as a Video

The real magic of git-story is how it progressively reveals the commit history as an animated video. Rather than just showing the final state of the DAG, git-story starts with a blank slate and introduces each commit one by one in chronological order.

This is achieved using Manim‘s Scene and play() constructs. A scene represents the canvas where the animation takes place. graphical elements are added to or removed from the scene over time to create a sense of motion and progress.

Here‘s a high-level look at the main animation loop in git-story:

from manim import Scene, Create, FadeIn, FadeOut

class CommitHistoryScene(Scene):
    def construct(self):
        for commit in commits:
            self.play(Create(commit.circle))
            self.play(FadeIn(commit.label))

            for parent_commit in commit.parents:
                self.play(Create(commit.arrow_to_parent))

        self.wait()

The construct() method is where the animation timeline is defined. Git-story loops over the list of commits and uses the play() method to animate the creation of each commit‘s circle, label, and parent arrows. The Create and FadeIn classes specify the type of animation applied to each element as it enters the scene.

The self.wait() call at the end inserts a final pause before the animation ends, giving the viewer time to take in the completed visualization.

When executed, this code generates an MP4 video file that shows the commit history being progressively constructed on a blank background. The order and pacing of the animations are synchronized with the chronological order of the commits, creating an intuitive and engaging visual experience.

By default, git-story uses a dark, high-contrast color scheme for maximum readability. However, nearly every visual aspect can be customized using command-line options, as we‘ll see in the next section.

Installing and Using git-story

Now that we‘ve explored the inner workings of git-story, let‘s walk through the process of installing and using it in your own projects.

Installation

Before you can use git-story, you‘ll need to install its dependencies: Manim and GitPython. Manim has a few additional setup steps that vary based on your operating system, so consult the official Manim installation guide for detailed instructions.

Once Manim is installed, you can use pip to install GitPython and git-story:

pip install gitpython
pip install git-story

That‘s it! You should now be able to run the git-story command from any terminal.

Basic Usage

Using git-story is incredibly straightforward. Simply navigate to the local Git repository you want to visualize and run:

git-story

This will generate an MP4 video of the most recent 8 commits in the current repo. The video file will be saved in the git-story_media/videos/ directory within the current working directory.

By default, git-story starts at HEAD and works backwards, animating the commits in reverse chronological order. The oldest commit appears first, and newer commits are added to the graph over time.

Customizing the Output

Git-story provides a variety of command-line options to customize the content and appearance of the generated animation. Here are some of the most useful ones:

  • --commits: Specify the number of commits to include in the animation (default is 8)
  • --commit-id: Specify a branch name, tag, or commit hash to start the animation from (default is HEAD)
  • --reverse: Animate the commits in chronological order instead of reverse chronological order
  • --light-mode: Use a light color scheme instead of the default dark one
  • --invert-branches: Flip the orientation of branches in the graph, which can improve readability in some cases

For example, to generate an animation of the 20 most recent commits on the "develop" branch in light mode, you would run:

git-story --commits 20 --commit-id develop --light-mode

There are also options to add a custom title screen, logo, and closing credits to the animation. This is handy for incorporating git-story animations into presentations and documentation.

For a complete list of available options and their descriptions, run:

git-story --help 

Feel free to experiment with different option combinations to find the settings that work best for your particular use case and aesthetic preferences.

Examples of git-story in Action

To give you a better sense of what git-story animations look like, here are a few examples of the visualizations it generates.

This first example shows a simple linear commit history with no branches:

[GIF of linear history]

The commits are displayed in chronological order, with each new commit appearing to the right of its parent.

Here‘s an example showing a slightly more complex history with two branches:

[GIF of branched history]

The main branch progresses horizontally, while the feature branch diverges diagonally before merging back in. Labels clearly identify each branch and the current HEAD.

Finally, here‘s an example of a more realistic commit history with multiple active branches:

[GIF of multi-branch history]

Even with many parallel branches, the graph remains readable thanks to the clean layout and color-coding. And the animation makes it easy to understand the flow and timing of branch and merge events.

Hopefully these examples illustrate the potential of git-story to create informative and eye-catching visualizations of your Git history. The more complex the repo, the more useful (and impressive) the animations become!

Conclusion

In this article, we‘ve taken a deep dive into git-story – a powerful tool for generating animated visualizations of Git commit history. We‘ve explored what git-story is, why it‘s useful, how it works under the hood, and how to install and use it.

To recap, git-story combines the PyGit library for extracting repository data with the Manim library for constructing commit graph visualizations and animations. The resulting MP4 videos provide an intuitive and engaging way to understand the structure and evolution of a Git project.

Installing git-story is a breeze with pip, and using it is as simple as running git-story in your terminal. A variety of command-line options are available to customize the content and appearance of the animations.

We‘ve also looked at some examples of the types of visualizations git-story can generate, from simple linear histories to complex multi-branch graphs.

I hope this article has piqued your interest in git-story and inspired you to give it a try in your own projects. It‘s an incredibly handy tool to have in your Git toolbelt, whether you‘re a seasoned veteran or just starting out.

If you have any questions, feedback, or suggestions for improving git-story, please don‘t hesitate to reach out! You can submit issues and pull requests on the git-story GitHub repository.

Thanks for reading, and may your commit logs never be dull again!

Similar Posts