<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Codex on Chris — freshteapot</title><link>https://freshteapot.net/tags/codex/</link><description>Chris makes things, ships them, and writes down what happened.</description><generator>Hugo 0.163.3</generator><language>en</language><atom:link href="https://freshteapot.net/tags/codex/" rel="self" type="application/rss+xml"/><item><title>Checking Git disk usage after working with Codex</title><link>https://freshteapot.net/writing/codex-git-disk-usage/</link><pubDate>Wed, 11 Nov 2026 00:00:00 +0000</pubDate><guid>https://freshteapot.net/writing/codex-git-disk-usage/</guid><description>How I reduced Git storage from about 7 GiB to 611 MiB by checking Codex snapshots, cleaning temporary packs, and pruning unreachable objects.</description><content:encoded><![CDATA[<p>To check how much space Git is using, run these two commands inside your repository:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">du -sh <span class="s2">&#34;</span><span class="k">$(</span>git rev-parse --git-common-dir<span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">git count-objects -vH
</span></span></code></pre></div><p>My repository&rsquo;s <code>.git</code> directory was about <strong>7 GiB</strong>. Removing 58 abandoned temporary pack files reclaimed <strong>3.44 GiB</strong>, leaving about <strong>3.4 GiB</strong>. Removing unreachable objects then brought it down to <strong>611 MiB</strong>.</p>
<h2 id="read-the-storage-breakdown">Read the storage breakdown</h2>
<p>In the output from <code>git count-objects</code>, look for:</p>
<ul>
<li><code>size-pack</code>: space used by packed Git objects.</li>
<li><code>size</code>: space used by loose objects.</li>
<li><code>garbage</code>: the number of files Git does not recognise as valid object storage.</li>
<li><code>size-garbage</code>: the space those files occupy.</li>
</ul>
<p>My warnings named files such as <code>.git/objects/pack/tmp_pack_…</code>. These were temporary pack files. Their presence was consistent with interrupted packing operations; I did not establish what interrupted them.</p>
<h2 id="codex-snapshots-can-include-untracked-files">Codex snapshots can include untracked files</h2>
<p><strong>Codex can store snapshots of files you have never added or committed to Git.</strong> That means local files can occupy space inside <code>.git</code> even when they are absent from your branch history.</p>
<p>In my repository, Codex had stored snapshots under these references:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">refs/codex/turn-diffs/captures/...
</span></span><span class="line"><span class="cl">refs/codex/turn-diffs/checkpoints/...
</span></span></code></pre></div><p>You can check for them with:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git <span class="k">for</span>-each-ref --format<span class="o">=</span><span class="s1">&#39;%(objecttype) %(refname)&#39;</span> refs/codex
</span></span></code></pre></div><p>These references pointed to Git trees: stored directory snapshots. Their names indicate that they support tracking changes between turns. A Git <strong>worktree</strong> is a checkout directory; the snapshots we found were objects inside Git&rsquo;s storage.</p>
<p>Git reuses identical file objects, while changed content can create new versions. In my case, snapshots included several versions of an untracked local database, each over 1 GiB before compression.</p>
<p>This makes <code>.gitignore</code> useful even for files you never intend to commit. After ignoring that database, I confirmed that newer Codex captures excluded it. Older snapshots still retained their copies.</p>
<h2 id="remove-abandoned-temporary-packs">Remove abandoned temporary packs</h2>
<p>Before cleaning up, stop Codex sessions and other Git activity for the repository, including linked worktrees. Keep them stopped during cleanup. These commands work on macOS with <code>lsof</code> installed:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="nv">git_dir</span><span class="o">=</span><span class="s2">&#34;</span><span class="k">$(</span>git rev-parse --git-common-dir<span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">lsof +D <span class="s2">&#34;</span><span class="nv">$git_dir</span><span class="s2">/objects/pack&#34;</span>
</span></span></code></pre></div><p>If <code>lsof</code> lists processes, wait for them to finish. No output normally means no open files were found; if it reports an error, resolve that first. This is a point-in-time check, so it cannot protect against another process starting afterwards.</p>
<p>List temporary pack files older than an hour:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">find <span class="s2">&#34;</span><span class="nv">$git_dir</span><span class="s2">/objects/pack&#34;</span> -type f -name <span class="s1">&#39;tmp_pack_*&#39;</span> -mmin +60 -print
</span></span></code></pre></div><p>Once you have reviewed that list and confirmed they are abandoned, the following command <strong>permanently deletes those matching temporary files</strong>. Age alone does not establish that a file is abandoned. Keep regular <code>pack-*.pack</code> files intact.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">find <span class="s2">&#34;</span><span class="nv">$git_dir</span><span class="s2">/objects/pack&#34;</span> -type f -name <span class="s1">&#39;tmp_pack_*&#39;</span> -mmin +60 -print -delete
</span></span></code></pre></div><p>Then run normal garbage collection and check the result:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git gc
</span></span><span class="line"><span class="cl">git fsck --connectivity-only --no-dangling
</span></span><span class="line"><span class="cl">du -sh <span class="s2">&#34;</span><span class="nv">$git_dir</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">git count-objects -vH
</span></span></code></pre></div><p>In my case, <code>garbage</code> and <code>size-garbage</code> became zero, and the connectivity check passed. The temporary-file removal produced the 3.44 GiB saving; <code>git gc</code> alone was not the whole cleanup.</p>
<h2 id="why-unreachable-objects-remain">Why unreachable objects remain</h2>
<p>After that cleanup, <code>.git</code> was still 3.4 GiB.</p>
<p>About <strong>2.84 GiB was unreachable data</strong>: stored objects no longer retained through references or reflogs. Git keeps recent unreachable objects for a grace period. This can help recover discarded work and protects objects another Git process may have written before attaching a reference to them.</p>
<p>Normal <code>git gc</code> uses a two-week expiry cutoff by default. In this repository it collected that data into a <strong>cruft pack</strong>, a pack for retained unreachable objects. A later collection can remove objects once they qualify for expiry. There is no background countdown that deletes them automatically.</p>
<p>Another roughly <strong>0.59 GiB remained referenced</strong>, including Codex checkpoints. Ordinary branch, tag, and remote-tracking history accounted for only about <strong>79 MiB</strong> of stored objects. Garbage collection preserves referenced data, even when it is an old database snapshot.</p>
<h2 id="remove-unreachable-objects-now">Remove unreachable objects now</h2>
<p>To remove unreachable objects immediately, you can skip the age grace period. <strong>This permanently removes otherwise recoverable data.</strong> Stop Codex sessions and all other Git activity in the repository and its linked worktrees first; concurrent writes can risk corruption. Keep them stopped until collection finishes.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">git gc --prune<span class="o">=</span>now
</span></span></code></pre></div><p>This preserves objects retained by references and reflogs, including branches, tags, stashes, and Codex checkpoints. It does not remove those checkpoints.</p>
<p>Check the resulting size and connectivity:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">du -sh <span class="s2">&#34;</span><span class="k">$(</span>git rev-parse --git-common-dir<span class="k">)</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">git count-objects -vH
</span></span><span class="line"><span class="cl">git fsck --connectivity-only --no-dangling
</span></span></code></pre></div><h2 id="the-result">The result</h2>
<p>For this second cleanup, my <code>du</code> output went from:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">3.4G    .git
</span></span></code></pre></div><p>to:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">611M    .git
</span></span></code></pre></div><p>That reclaimed roughly another <strong>2.8 GiB</strong>, on top of the <strong>3.44 GiB</strong> from temporary files. The remaining storage includes referenced Codex snapshots as well as the repository&rsquo;s ordinary history.</p>
]]></content:encoded></item></channel></rss>