<?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>GitonDocs</title><link>https://hiraethecho.github.io/docs/tags/git/</link><description>Recent contentinGitonDocs</description><generator>Hugo --0.152.2</generator><language>en</language><managingEditor>wyz2016zxc@outlook.com(Hiraeth)</managingEditor><webMaster>wyz2016zxc@outlook.com(Hiraeth)</webMaster><lastBuildDate>Mon, 16 Mar 2026 15:39:39 +0800</lastBuildDate><atom:link href="https://hiraethecho.github.io/docs/tags/git/index.xml" rel="self" type="application/rss+xml"/><item><title>git底层设计</title><link>https://hiraethecho.github.io/docs/dev/git-base/</link><pubDate>Wed, 17 Dec 2025 00:00:00 +0000</pubDate><author>wyz2016zxc@outlook.com(Hiraeth)</author><guid>https://hiraethecho.github.io/docs/dev/git-base/</guid><description>了解了一下git的底层实现方式，感觉很厉害，记录一下</description><content:encoded><![CDATA[<h1 id="git底层设计">
  <a class="anchor inpage" href="#git%e5%ba%95%e5%b1%82%e8%ae%be%e8%ae%a1">#</a>git底层设计</h1>
<p>git是Linus的分布式版本控制软件，据说用了一周写出来，太强了。</p>
<h2 id="目标">
  <a class="anchor inpage" href="#%e7%9b%ae%e6%a0%87">##</a>目标</h2>
<p>版本控制的目标是，记录每次更改，或者说记录每个版本。除此之外还有额外要求：</p>
<ul>
<li>低成本创建分支</li>
<li>保证版本内容的可信性，不被篡改</li>
<li>分布式</li>
</ul>
<h2 id="思路">
  <a class="anchor inpage" href="#%e6%80%9d%e8%b7%af">##</a>思路</h2>
<p>我第一个想到的实现方式是，增量存储，记录变更的内容。换句话说，存储的是一堆diff文件。这样的好处是，理论上存储空间会小。但是每一个版本的内容都会是从某一个版本为基础根据diff计算而来。</p>
<p>然而，信息的存储方式其实只是技术细节，关键的问题在于，如何把部分信息提取出来，组成一个版本的文件。
按照我的理解用比喻的方式描述。</p>
<p>假设现在写一本书，但是不是线性写作，而是多个章节同时开始，内容写在一个活页本上。<br>
第一天分别写了一二三节的开头，写在三页纸上，这三页纸有各自的名字，暂且称为a, b, c。再用一张小纸条，记录内容是<em>a, b, c是第一个版本的内容</em>，这个小纸条也有个名字，暂称为A。把它们放进活页本里。<br>
第二天重写了第二节，写在新的一张纸上，这张纸名字是d。同样的，有另一张小纸条，记录内容是<em>a, d, c是第二个版本的内容</em>，这个小纸条的名字记为B。再把它们放进活页本里。<br>
这样，我们就有A, B两个版本了。</p>
<h2 id="目标的实现">
  <a class="anchor inpage" href="#%e7%9b%ae%e6%a0%87%e7%9a%84%e5%ae%9e%e7%8e%b0">##</a>目标的实现</h2>
<p>沿用上面的比喻，接下来是一些额外的结构，来使用上述思路实现目标。</p>
<p>首先是分支。其实分支就只是又一个小纸条，贴在A, B这样的小纸条上。比如我是书的主要作者，我在B上贴一个main。我的合作者在A的基础上重写了第三节，写在e这张纸上，并且有个C记录<em>a, b, e</em>，在C上就可以有一个dev的小纸条，这就是dev分支。<br>
保证版本内容的可信性，有2个细节。第一，名字a, b, c和A, B, C其实是sha1，这样可以确保内容和名称匹配。第二，B, C上除了内容，其实还包括它的上一个版本，也就是说B还记录了A的名字，这就保证了历史的可信性。<br>
除此之外，git还使用了内容寻址的存储方式。这张纸a的文件名就是a，而a是内容的sha1，所以不同内容的纸不会在这里，很容易检验信息的真实性。<br>
至于分布式，由于分支只是一个小标签，这就自动满足了。</p>
<h2 id="ref">
  <a class="anchor inpage" href="#ref">##</a>ref</h2>
<p>
</p>
]]></content:encoded></item></channel></rss>