- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如果我有一个git仓库,其中有一个初始提交,然后是100个小的提交,它们会更改100个文件,而每个小的提交只对一个文件进行一次更改,是否可以通过将这100个提交压缩为一个大的100个文件更改的提交来节省空间?例如:
$ git checkout master
Already on branch 'master'.
$ git reset --soft HEAD~100 && git commit -m 'squash last 100 commits'
master
的尖端,但将其历史记录中的前100个提交保留在历史记录之外。这样可以节省多少空间?
最佳答案
也许(甚至“大概”)会节省一些空间,但不是马上。实际上,起初它会使事情变大一点。
让我们看一下git如何实际存储事物。它变得复杂,但是开始非常简单:git完整地存储了每个文件(使用“ zlib deflate”压缩,否则仅存储原始文件)。
git对象模型
在git存储库中,所有内容都存储为一个对象。每个对象都由其SHA-1命名,SHA-1是其实际内容(对象类型,大小和数据)的加密校验和。这使您可以执行以下两项操作之一:计算SHA-1并按对象名称存储对象(或发现对象已经在其中);或者,给定SHA-1名称,找到对象并访问其内容。
有四种类型的对象。一个在这里没有意思。1另外三个是:
“提交对象”,用于保存提交数据,包括提交消息本身以及“树”对象的SHA-1 ID;
“树”对象,用于存储内容列表:SHA-1,文件名和文件的模式; 2和
“ blob”(文件)对象,用于存储您的实际文件。 (偶然地,单词“ blob”可能源自数据库术语BLOB,它是"backronym" for "Binary Large OBject"。)
通过从提交的SHA-1 ID开始,git可以提取树,该树告诉它要提取的blob以及为其指定的文件名(例如,blob对象1234567...
被称为file1.txt
)。
实际对象存储在.git/objects
的子目录中,例如,对象1234567...
保留在.git/objects/12/34567...
中。 (SHA-1的长度始终为40个字符,但我们通常将其缩写为7加3点,通常就足够了。)
1为了完整起见,最后一个对象类型是“带注释的标记”:它包含一个提交(如提交)(“ tagger”),另一个SHA-1(如提交)和一条消息(如提交),因此基本上就像一个承诺;但是它包含的SHA-1 ID通常是提交对象的ID,而不是树对象的ID,然后有一个轻量级标签指向带注释的标签。除其他外,这使您可以将经过密码签名的标记放入存储库中,其他人可以检查该标记以例如查看您是否已批准该特定提交。
2对于普通文件,该模式实际上只是一个位(执行或不执行),但是git还可以存储符号链接,子树和“子模块”,因此实际上还有一点点。出于我们的目的,我们可以忽略所有文件。
一个例子
假设我们创建了一个存储库,并对其进行了100个文件的初始提交,每个文件都与所有其他文件不同。为了简单起见,我们还将所有100个文件都放在顶层(没有子目录)。这样,存储库的初始状态为:
一个提交对象
一棵树对象
100个斑点
加上通常的git开销(一个分支文件,其中包含master
的最尖端SHA-1 ID,HEAD
文件,依此类推)。我们将这个仓库称为“ hundredfile.git”。这100个文件只是“ file1.txt”到“ file100.txt”。
如果我们在数百文件.git中计算对象,那么根据上面的列表,将有102个对象。
现在,我们将克隆此存储库,以便我们可以进行100次提交或1次提交,并比较结果。首先,让我们进行100次提交。以下内容实际上是伪代码,但足够接近,可以真正起作用(我认为/希望),只要您设置了make_change_即可对文件进行更改。另外,我们希望每次更改都产生一个新的唯一文件(以便所有100个文件始终互不相同),否则以下描述中的某些项目将变为错误。
$ git clone ssh://host.dom.ain/hundredfile.git method1
[clone messages]
$ cd method1
$ for i in $(jot 100); do # note: jot 100 => print list of values 1, 2, ... 100
> make_change_to file$i.txt; git add file$i.txt; git commit -m "change $i"
> done
[100 commit results come out here]
file$i.txt
具有新的SHA-1 ID。
"change $i"
加上作者和提交者的时间戳,再加上树),一个新的“ tree”对象(列出99个相同的Blob ID)加上一个新的,不同的Blob-ID)和一个新的“ blob”对象。
method1
中的此克隆具有402个对象。
hundredfile.git
并进行新的克隆:
$ cd .. # up out of the "method1" repo
$ git clone ssh://host.dom.ain/hundredfile.git method2
[clone messages]
$ cd method2
$ for i in $(jot 100); do
> make_change_to file$i.txt; git add file$i.txt
> done
$ git commit -m 'change all'
[one commit result comes out here]
method1
中的402个对象。
method1
中)压缩为一个时,git所做的就是将一个新提交添加到其存储库中。这一新提交包含您的提交消息(无论它是什么)以及通常的日期和树ID等。它有一棵树,该树与上一次提交的最终树完全相同,因为该树存储每个Blob的名称和SHA-1,也与文件中带有该Blob的文件的前一个Blob完全相同。一样的名字。 (也就是说,新提交中的树的“ file1.txt是1234567 ...”与原始分支提示提交中的树相同,并且对于每个文件都是如此,因此树是相同的,因此其校验和相同,因此其SHA-1 ID也相同。)
method1
中得到的是402个对象变为403个对象:原始的402,再加上一个新的提交,该提交重新使用了先前的树及其所有先前的blob。存储库会稍微大一点(一个文件可能只有一个磁盘块)。
master
中的SHA-1)将保存在两个引用日志中,一个保存为
HEAD
,另一个保存为分支。 (当然,新的南瓜提交的ID照常进入
master
。)
git reflog expire
将删除它们(或者您可以手动删除它们,但这有点棘手)。
git gc
的一部分,并且请注意
git gc
也会为您运行
git reflog expire
)可以删除提交,一旦删除,还可以删除先前的提交,以此类推,返回100提交。这些使除最后一棵树外的树对象未被引用;而那些反过来使blob未被引用,最终的blob除外。 (最后一棵树和最后一滴斑点仍然可以通过您进行的南瓜提交找到。)
method2
中相同的204个对象。 (如果所有提交时间戳都相同,则它们只是完全相同的对象,但是对象的数量将减少到204。)
.git/objects/12/34567...
)之外,git还具有“打包”格式。打包的对象将针对同一打包中的其他对象进行压缩。
file1.txt
中发生了什么变化:例如,git对
file39.txt
压缩了
file75.txt
。这完全取决于文件中的实际内容以及git选择压缩的对象。甚至可以压缩其他种类的物体
git gc
自动完成的,并且git在认为合适时会自动为您调用
gc
(请参见
setting for gc.auto
)。
.git
目录小于任何单个检出的提交并不罕见。
git filter-branch
进行此操作,尽管它相当复杂。或者您可以使用
BFG cleaner
。有关几种方法,请参见
How to remove/delete a large file from commit history in Git repository?。
关于git - 如何通过压缩提交来节省git存储库中的空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26080278/
我想做的是让 JTextPane 在 JPanel 中占用尽可能多的空间。对于我使用的 UpdateInfoPanel: public class UpdateInfoPanel extends JP
我在 JPanel 中有一个 JTextArea,我想将其与 JScrollPane 一起使用。我正在使用 GridBagLayout。当我运行它时,框架似乎为 JScrollPane 腾出了空间,但
我想在 xcode 中实现以下功能。 我有一个 View Controller 。在这个 UIViewController 中,我有一个 UITabBar。它们下面是一个 UIView。将 UITab
有谁知道Firebird 2.5有没有类似于SQL中“STUFF”函数的功能? 我有一个包含父用户记录的表,另一个表包含与父相关的子用户记录。我希望能够提取用户拥有的“ROLES”的逗号分隔字符串,而
我想使用 JSON 作为 mirth channel 的输入和输出,例如详细信息保存在数据库中或创建 HL7 消息。 简而言之,输入为 JSON 解析它并输出为任何格式。 最佳答案 var objec
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个以前可能被问过的问题,但我很难找到正确的描述。我希望有人能帮助我。 在下面的代码中,我设置了varprice,我想添加javascript变量accu_id以通过rails在我的数据库中查找记
我有一个简单的 SVG 文件,在 Firefox 中可以正常查看 - 它的一些包装文本使用 foreignObject 包含一些 HTML - 文本包装在 div 中:
所以我正在为学校编写一个 Ruby 程序,如果某个值是 1 或 3,则将 bool 值更改为 true,如果是 0 或 2,则更改为 false。由于我有 Java 背景,所以我认为这段代码应该有效:
我做了什么: 我在这些账户之间创建了 VPC 对等连接 互联网网关也连接到每个 VPC 还配置了路由表(以允许来自双方的流量) 情况1: 当这两个 VPC 在同一个账户中时,我成功测试了从另一个 La
我有一个名为 contacts 的表: user_id contact_id 10294 10295 10294 10293 10293 10294 102
我正在使用 Magento 中的新模板。为避免重复代码,我想为每个产品预览使用相同的子模板。 特别是我做了这样一个展示: $products = Mage::getModel('catalog/pro
“for”是否总是检查协议(protocol)中定义的每个函数中第一个参数的类型? 编辑(改写): 当协议(protocol)方法只有一个参数时,根据该单个参数的类型(直接或任意)找到实现。当协议(p
我想从我的 PHP 代码中调用 JavaScript 函数。我通过使用以下方法实现了这一点: echo ' drawChart($id); '; 这工作正常,但我想从我的 PHP 代码中获取数据,我使
这个问题已经有答案了: Event binding on dynamically created elements? (23 个回答) 已关闭 5 年前。 我有一个动态表单,我想在其中附加一些其他 h
我正在尝试找到一种解决方案,以在 componentDidMount 中的映射项上使用 setState。 我正在使用 GraphQL连同 Gatsby返回许多 data 项目,但要求在特定的 pat
我在 ScrollView 中有一个 View 。只要用户按住该 View ,我想每 80 毫秒调用一次方法。这是我已经实现的: final Runnable vibrate = new Runnab
我用 jni 开发了一个 android 应用程序。我在 GetStringUTFChars 的 dvmDecodeIndirectRef 中得到了一个 dvmabort。我只中止了一次。 为什么会这
当我到达我的 Activity 时,我调用 FragmentPagerAdapter 来处理我的不同选项卡。在我的一个选项卡中,我想显示一个 RecyclerView,但他从未出现过,有了断点,我看到
当我按下 Activity 中的按钮时,会弹出一个 DialogFragment。在对话框 fragment 中,有一个看起来像普通 ListView 的 RecyclerView。 我想要的行为是当
我是一名优秀的程序员,十分优秀!