Creating a Partial Clone of a Git Repo

A trick I use for writing on this site without being distracted by its code

in Software 820 words — 3 min read 1 comment

TL;DR
Terminal window
git clone -n --depth=1 --no-checkout --filter=tree:0 <your-repo-git-url>
cd your-new-repo-folder
git sparse-checkout set --no-cone path/to/desired/folder
git checkout

I upgraded my computer a few months ago, and, after some thought, decided to turn my old one into a writing-only device. The goal was to use higher-order agency thinking—decisions that shape one’s decisions1—to enable myself to focus more deeply on my journaling, this blog, Innerhelm, and my other writing. I removed everything not related to writing from this device: accounts and bookmarks in my browser, the messaging apps I use, the handful of games I had installed, and even the VS Code extensions I use that don’t relate to Markdown. (I use VS Code for my writing for a few reasons, most notably (a) because I have yet to find a text editor I like that supports the inline footnotes syntax I use, and (b) because I have a large amount of muscle memory built up for getting around it, which reduces the friction of writing.)

I was left with a much-less-interesting VS Code for my blog writing, Notesnook for my journaling, and Obsidian for storing quotes from books and articles that I might use in my writing.

But one big distractor remained: my personal site’s code. I’ve spent so many hours tweaking this site’s design and implementation like one would rub a worry-stone—not out of genuine need but as an escape from the “should” of writing. Because my posts are stored as Markdown files in an Astro content collection, the code that renders those posts is right there, singing its siren song to me, luring me into the rocks of comfort-coding when my intended goal was to write.

Being the git geek that I am, I wondered if there was a way to use git to “tie myself to the mast” by only cloning the folder that contains my posts. Turns out, there is! (Kudos to Ciro Santilli for providing the solution in this answer on Stack Overflow.)

There are two commands you’ll need to run. Let’s break down each of them.

Step 1: Clone the repository

Terminal window
git clone -n --depth=1 --no-checkout --filter=tree:0 <your-repo-git-url>

This isn’t your standard-issue git clone command. Here we use --filter to specify the objects (think versions of files) we want to download. Specifying tree:0 as the filter value means we don’t want anything—at least, not until we say which files we do want. --depth=1 means we don’t want any commits other than the most recent one. (Commits we or others make on the main branch will be pulled when we git pull, but nothing older than the most recent commit at the time of the clone will be downloaded, even on those subsequent pulls.)

Replace <your-repo-url> with the URL you normally use for git clone. For example, in my case, I used git@github.com:tylermercer/personal-website.git.

Step 2: Checkout the directory you want

cd into the newly-created directory for your repo. Then run the following command:

Terminal window
git sparse-checkout set --no-cone path/to/desired/folder && git checkout

This one uses the new-ish sparse-checkout command. You can specify multiple folders if you would like, by listing them after the set command, separated by spaces.

This will initialize a file in your-repo/.git/info/sparse-checkout with these paths listed, which git will then use for updating your working-tree when you checkout or pull. In my case, the path to the folder was /src/content, which is where my Markdown files live.2

Step 3: Enjoy your peace of mind

I suppose this depends on what you are using it for. But in my case, carving out an interruption-free digital space for my writing has been so nice.

Imperfections

I should note here that the resulting folder structure still preserves the parent directories, which may be a downside for some use cases, such as mine. It would be great if I could just have a personal-website folder containing the contents of my content folder, right alongside the .git directory. Maybe git will someday add that ability. But until then, this works well enough for me.


Changelog

  • 2024-08-07: Added --no-cone and --no-checkout flags, and final git checkout command. These proved necessary when doing this process for a new repo today, probably due to changes in git since this article was written.

Footnotes

  1. I wrote about this topic briefly in the Feb 8 Innerhelm newsletter, and am planning on writing a longer Innerhelm blog post about it at some point.

  2. The path was actually different when I first did the partial clone, because I did it prior to my migration to Astro.

Comments

1 comment
  • 1 reply
    • Bryan Hogan

      Thank you for your comment! Generally I can recommend using the submodule approach, for me it works great. But I'm not sure if one repository can be private while the other is public, haven't looked into that. Looking forward to an update if you do!


      2 replies
      • Tyler Mercer

        I figured it out! Thanks for your writeup about your setup; it was very helpful.

        I'll write a follow up post to this one at some point, but if you'd like to know how I did it, you can check out the PR.


      • Tyler Mercer

        I use GitHub Actions for my deploy pipelines, and for my private repos (such as the one for Innerhelm.com) I've had to add a GitHub Personal Access Token to get the checkout action to work—I wonder if doing the same here (and finding a way to pass in the --recursive flag) would work. I'll try it and report back.