前面已经阐述了Git基本的运做机制和使用方式,介绍了不少Git提供的工具来帮助你简单且有效地使用它。本部分将演示怎样借助Git的一些重要的配置方法和钩子机制,来知足本身定义的需求。javascript
(1)配置Git
可以用git config 配置Git。java
$ git config --global user.name "ligang"
$ git config --global user.email "ligang@example.com"
高速回顾下:Git使用一系列配置文件来保存你本身定义的行为。node
以上三个层次中每层的配置(系统、全局、本地)都会覆盖掉上一层次的配置:本地 > 全局 > 系统。
(2)Git中的着色
Git会本身主动着色大部分输出内容。但假设你不喜欢花花绿绿,也可以关掉。git
# 这个设置的默认值是auto
$ git config --global color.ui false
# 详细设置某项,diff的输出信息以蓝色前景、黑色背景和粗体显示
$ git config --global color.diff.meta "blue black bold"
(3)格式化与多余的空白字符
如你正在 Windows 上敲代码,而你的同伴用的是其它系统(或相反),你可能会遇到CRLF问题。这是因为Windows使用回车(CR)和换行(LF)两个字符来结束一行,而 Mac 和 Linux 仅仅使用换行(LF)一个字符。 尽管这是小问题。但它会极大地扰乱跨平台协做。
假设是在Windows系统上,把它设置成 true。这样在检出代码时,换行会被转换成回车和换行:github
$ git config --global core.autocrlf true
假设使用以换行做为行结束符的 Linux 或 Mac,设置成input来告诉Git在提交时把回车和换行转换成换行。检出时不转换:sql
$ git config --global core.autocrlf input
假设,所有人使用一样的系统开发,则可以取消该功能:数据库
$ git config --global core.autocrlf false
Git 预先设置了一些选项来探測和修正多余空白字符问题。ruby
它提供了六种处理多余空白字符的主要选项。bash
选项 | 说明 | 是否默认开启 |
---|---|---|
blank-at-eol | 查找行尾的空格 | 默认开启 |
blank-at-eof | 盯住文件底部的空行 | 默认开启 |
space-before-tab | 警戒行头tab前面的空格 | 默认开启 |
indent-with-non-tab | 揪出以空格而非tab开头的行 | 默认关闭 |
tab-in-indent | 监视在行头表示缩进的 tab | 默认关闭 |
cr-at-eol | 告诉 Git 忽略行尾的回车 | 默认关闭 |
多个选项以逗号切割,经过逗号切割的链中去掉选项或在选项前加-来关闭。markdown
# 开启indent-with-non-tab,cr-at-eol模式
$ git config --global core.whitespace "indent-with-non-tab,cr-at-eol"
# 在打上补丁前本身主动修正此问题
$ git apply --whitespace=fix <patch>
你也可以针对特定的路径配置某些设置项,这样Git就仅仅对特定的子文件夹或子文件集运用它们。
这些基于路径的设置项被称为Git属性,可以在你的文件夹下的 .gitattributes 文件内进行设置(通常是你的项目的根文件夹)。假设不想让这些属性文件与其它文件一同提交,你也可以在 .git/info/attributes 文件里进行设置。
经过使用属性。你可以对项目中的文件或文件夹单独定义不一样的合并策略,让Git知道怎样比較非文本文件。或者让Git在提交或检出前过滤内容。
(1)导出版本号库
当归档的时候。可以设置Git不导出某些文件和文件夹。
假设你不想在归档中包括某个子文件夹或文件,但想把它们归入项目的版本号管理中。你可以在export-ignore属性中指定它们。
# 在项目导出的压缩包中,不包括test/文件夹下文件
test/ export-ignore
(2)合并策略
经过Git属性,你还能对项目中的特定文件指定不一样的合并策略。
一个很实用的选项就是,告诉Git当特定文件发生冲突时不要尝试合并它们,而是直接使用你这边的内容。
# 合并分支时,确保database.xml选择咱们的,不被覆盖
database.xml merge=ours # 定义一个虚拟的合并策略,叫作ours $ git config --global merge.ours.driver true $ git merge topic Auto-merging database.xml Merge made by recursive.
Git 能在特定的重要动做发生时触发本身定义脚本。 有两组这种钩子:client的和server端的。
client钩子由诸如提交和合并这种操做所调用,而server端钩子做用于诸如接收被推送的提交这种联网操做。
钩子都被存储在.git/hooks文件夹下,默认以.sample结尾。
假设你想启用它们,得先移除这个后缀。
client钩子可分为:提交工做流钩子、电子邮件工做钩子和其它钩子。
(1)提交工做流钩子
它用于检查即将提交的快照。好比。检查是否有所遗漏。确保測试执行,以及核查代码。
假设该钩子以非零值退出,Git将放弃这次提交,只是你可以用 git commit --no-verify
来绕过这个环节。
(2)电子邮件工做流钩子
都是由 git am 命令调用的。
applypatch-msg --> pre-applypatch --> post-applypatch
(3) 其它client钩子
服务端钩子在推送到server以前和以后执行。
假设你的代码眼下不在Git上。但是想迁移到Git。可以參考如下两个地址:
【Git与其它系统 - 做为client的Git】
【Git与其它系统 - 迁移到Git】
了解Git内部原理对于理解Git的用途和强大相当重要。
Git是一个内容寻址(content-addressable)文件系统。并在此之上提供了一个版本号控制系统的用户界面。
以前章节讲述的友好的命令,基本都是“高层”命令。
底层命令得以让你窥探Git内部的工做机制,也有助于说明Git是怎样完毕工做的,以及它为什么如此运做。多数底层命令并不面向终于用户:它们更适合做为新命令和本身定义脚本的组成部分。
当在一个新文件夹或已有文件夹执行git init
时,Git会建立一个.git文件夹。
这个文件夹包括了差点儿所有Git存储和操做的对象。如若想备份或复制一个版本号库,仅仅需把这个文件夹拷贝至还有一处就能够。
$ cd .git
$ ls -F1
HEAD # 指示眼下被检出的分支
index # 保存暂存区信息
config* # 包括项目特有的配置选项
description # 仅供GitWeb程序使用。咱们无需关心
hooks/ # 包括client或服务端的钩子脚本
info/ # 包括一个全局性排除文件
objects/ # 存储所有数据内容
refs/ # 存储指向数据(分支)的提交对象的指针
Git是一个内容寻址文件系统。
Git的核心部分是一个简单的键值对数据库(key-value data store)。你可以向该数据库插入随意类型的内容。它会返回一个键值,经过该键值可以在随意时刻再次检索(retrieve)该内容。
(1)向Git中存入内容
# 因此数据内容都存在objects中
$ find .git/objects
.git/objects
.git/objects/info
.git/objects/pack
# 往Git数据库存入一些文本
$ echo 'test content' | git hash-object -w --stdin
d670460b4b4aece5915caf5c68d12f560a9fe3e4
显示40个字符的校验和:前两个字符用于命名子文件夹,余下的38个字符则用做文件名称。
# 查看objects中的文件
$ find .git/objects -type f
.git/objects//d6/70460b4b4aece5915caf5c68d12f560a9fe3e4
# 查看文件内容
$ git cat-file -p d670460b4b4aece5915caf5c68d12f560a9fe3e4
test content
(2)从Git中取出内容
# 建立一个新文件并将其内容存入数据库
$ echo 'version 1' > test.txt
$ git hash-object -w test.txt
83baae61804e65cc73a7201a7252750c76066a30
# 接着。向文件里写入新内容,并再次将其存入数据库
$ echo 'version 2' > test.txt
$ git hash-object -w test.txt
1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
$ find .git/objects -type f
.git/objects/83/baae61804e65cc73a7201a7252750c76066a30
.git/objects/1f/7a7a472abf3dd9643fd615f6da379c4acb3e3a
# 把内容恢复到第一个版本号或第二个版本号
$ git cat-file -p 83baae61804e65cc73a7201a7252750c76066a30 > test.txt
$ cat test.txt
version 1
$ git cat-file -p 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a > test.txt
$ cat test.txt
version 2
(3)查看文件存储对象的类型
$ git cat-file -t 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a
blob # 数据对象
使用“数据对象”存储,其记住文件的每一个版本号所相应的SHA-1值并不现实,且文件名称并无被保存,仅保了文件的内容。
“树对象”能解决文件名称保存的问题,也赞成咱们将多个文件组织到一块儿。
所有内容均以树对象和数据对象的形式存储:树对象相应文件夹项,数据对象则大体上相应inodes或文件内容。
$ git cat-file -p master^{tree}
100644 blob a906cb2a4a904a152e80877d4088654daad0c859 README
100644 blob 8f94139338f9404f26296befa88755fc2598c289 Rakefile
040000 tree 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0 lib
master^{tree} 语法表示 master 分支上最新的提交所指向的树对象。
lib子文件夹并不是一个数据对象。而是一个指针,其指向的是还有一个树对象。
$ git cat-file -p 99f1a6d12cb4b6f19c8655fca46c3ecf317074e0
100644 blob 47c6340d6459e05787f644c2447d2595f5d3a54b simplegit.rb
(1)建立本身的树对象
$ echo 'new file' > new.txt
$ git update-index test.txt
$ git update-index --add new.txt
$ git write-tree
0155eb4229851634a0f03eb265b69f5a2d56f341
$ git cat-file -p 0155eb4229851634a0f03eb265b69f5a2d56f341
100644 blob fa49b077972391ad58037050f2a75f74e3671e92 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
咱们可以借助类似于 git log 1a410e
这种命令来浏览完整的提交历史,但为了能遍历那段历史从而找到所有相关对象,你仍须记住1a410e是最后一个提交。
咱们需要一个文件来保存SHA-1值。即“引用(references,或缩写为 refs)”
$ find .git/refs
.git/refs
.git/refs/heads
.git/refs/heads/master
.git/refs/remotes
.git/refs/remotes/origin
.git/refs/remotes/origin/master
.git/refs/tags
# 仅仅查看文件
$ find .git/refs type -f
.git/refs/heads/master
.git/refs/remotes/origin/master
$ git log --oneline master
21b61e0 Second commit
1b63b62 First commit
$ more .git/refs/heads/master
21b61e04b11b0bb6e8aedd8d21132974a23630be
(1)更新某个引用
# 方式一
$ echo "1b63b62c89014812fb7d00c6c47b80abcec286e0" > .git/refs/heads/master
# 方式二
$ git update-ref refs/heads/master 1b63b62c89014812fb7d00c6c47b80abcec286e0
注意:不提倡直接编辑引用文件。!!
(2)依据某提交创建分支(好!!
!)
# 在第一次提交上建立一个分支“test”
$ git update-ref refs/heads/test 1b63b62c89014812fb7d00c6c47b80abcec286e0 $ git log --oneline master 21b61e0 Second commit 1b63b62 First commit $ git log --oneline test 1b63b62 First commit
注意:master分支并未收到不论什么影响!!。
HEAD 文件是一个符号引用(symbolic reference),指向眼下所在的分支。所谓符号引用,意味着它并不像普通引用那样包括一个SHA-1值,它是一个指向其它引用的指针。
$ cat .git/HEAD
ref: refs/heads/master
# 切换到test分支
$ git checkout test
$ cat .git/HEAD
ref: refs/heads/test
当咱们执行git commit
时,该命令会建立一个提交对象,并用HEAD文件里那个引用所指向的 SHA-1值设置其父提交字段。
# 查看HEAD引用相应的值
$ git symbolic-ref HEAD
refs/heads/master
# 设置HEAD引用的值
$ git symbolic-ref HEAD refs/heads/test
$ cat .git/HEAD
refs/heads/test
# 查看当前分支
$ git branch -a
master
* test
remotes/origin/master
经过上述方式,也达到了切换分支的目的。。
标签对象(tag object)很类似于一个提交对象——它包括一个标签建立者信息、一个日期、一段凝视信息。以及一个指针。基本的差异在于,标签对象一般指向一个提交对象。而不是一个树对象。
它像是一个永不移动的分支引用——永远指向同一个提交对象,仅仅只是给这个提交对象加上一个更友好的名字罢了。
(1)建立一个轻量标签
$ git update-ref refs/tags/v1.0.0 21b61e04b11b0bb6e8aedd8d21132974a23630be
(2)查看建立标签对象的SHA-1值
$ cat .git/refs/tags/v1.0.0
21b61e04b11b0bb6e8aedd8d21132974a23630be
加入了一个远程版本号库并对其执行过推送操做。Git 会记录下近期一次推送操做时每一个分支所相应的值。并保存在 refs/remotes 文件夹下。
# origin 远程版本号库的 master 分支所相应的 SHA-1 值。就是近期一次与server通讯时本地 master 分支所相应的 SHA-1 值
$ cat .git/refs/remotes/origin/master
1b63b62c89014812fb7d00c6c47b80abcec286e0
远程引用和分支(位于 refs/heads 文件夹下的引用)之间最基本的差异在于,远程引用是仅仅读的。尽管可以git checkout
到某个远程引用,但是Git并不会将HEAD引用指向该远程引用。所以,你永远不能经过commit命令来更新远程引用。Git将这些远程引用做为记录远程server上各分支最后已知位置状态的书签来管理。
# 查看生成的树对象
$ git cat-file -p master^{tree}
100644 blob eea6e07591843cfb79d894c44b978519af8f07df .gitignore
040000 tree 61621bd52b3ac5ddf5277f06755c13ed6fe76c50 .idea
100644 blob 83c831f0b085c70509b1fbb0a0131a9a32e691ac README.md
100644 blob f73f3093ff865c514c6c51f867e35f693487d0d3 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
# 查看某个对象大小
$ git cat-file -s f73f3093ff865c514c6c51f867e35f693487d0d3
5
# 改动文件
$ echo 'testing' >> new.txt
$ git commit -am "modified new.txt"
$ git cat-file -p master^{tree}
100644 blob eea6e07591843cfb79d894c44b978519af8f07df .gitignore
040000 tree 61621bd52b3ac5ddf5277f06755c13ed6fe76c50 .idea
100644 blob 83c831f0b085c70509b1fbb0a0131a9a32e691ac README.md
100644 blob 76e35462261c5d088d07de3c936458ecd20f4514 new.txt
100644 blob 1f7a7a472abf3dd9643fd615f6da379c4acb3e3a test.txt
new.txt相应一个与以前全然不一样的数据对象,这意味着,尽管你仅仅是在一个文件后面加入一行新内容,Git也会用一个全新的对象来存储新的文件内容:
$ git cat-file -s 76e35462261c5d088d07de3c936458ecd20f4514
13
你的磁盘上现在有两个差点儿全然一样的对象。假设Git仅仅完整保存当中一个。再保存还有一个对象与以前版本号的差别内容,岂不更好?
其实Git可以那样作。Git最初向磁盘中存储对象时所使用的格式被称为“松散(loose)”对象格式。但是,Git会时不时地将多个这些对象打包成一个称为“包文件(packfile)”的二进制文件。以节省空间和提升效率。
当版本号库中有太多的松散对象。或者你手动执行git gc
命令,或者你向远程server执行推送时,Git都会这样作。
# 对对象进行打包
$ git gc
# 再查看 objects 文件夹,你会发现大部分的对象都不见了,与此同一时候出现了一对新文件
$ find .git/objects -type f
.git/objects/8c/6c1746924fa81ab1e7a7bc79c0c2e9cd34ffd5
.git/objects/info/packs
.git/objects/pack/pack-9032188022086c91c3810adf1900ec5d2014e7d3.idx # 索引
.git/objects/pack/pack-9032188022086c91c3810adf1900ec5d2014e7d3.pack # 包文件
包文件包括了刚才从文件系统中移除的所有对象的内容。
索引文件包括了包文件的偏移信息。咱们经过索引文件就可以高速定位随意一个指定对象。经过打包对象可以下降大约 ⅔ 的磁盘占用空间。
**Git是怎样作到这点的?**Git打包对象时,会查找命名及大小相近的文件。并仅仅保存文件不一样版本号之间的差别内容。你可以查看包文件,观察它是怎样节省空间的。
# 查看已打包的内容
$ git verify-pack -v .git/objects/pack/pack-9032188022086c91c3810adf1900ec5d2014e7d3.idx
(1)引用规格
引用规格的格式由一个可选的 + 号和紧随其后的 <src>:<dst>
组成,当中 <src>
是一个模式(pattern),表明远程版本号库中的引用;<dst>
是那些远程引用在本地所相应的位置。
+ 号告诉 Git 即便在不能快进的状况下也要(强制)更新引用。
默认状况下,引用规格由 git remote add
命令本身主动生成, Git 获取server中 refs/heads/
如下的所有引用。并将它写入到本地的 refs/remotes/origin/
中。
$ git remote add origin https://github.com/381510688/test.git
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://github.com/381510688/test.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
因此,假设server上有一个 master 分支。咱们可以在本地经过如下这种方式来訪问该分支上的提交记录:
$ git log origin/master
$ git log remotes/origin/master
$ git log refs/remotes/origin/master
注意:上面的三个命令做用一样。因为 Git 会把它们都扩展成 refs/remotes/origin/master。
假设想让 Git 每次仅仅拉取远程的 master 分支,而不是所有分支,可以把(引用规格的)获取那一行改动为:
fetch = +refs/heads/master:refs/remotes/origin/master
注意:这仅是针对该远程版本号库的 git fetch 操做的默认引用规格。
也可以在配置文件里指定多个用于获取操做的引用规格。
假设想在每次获取时都包括 master 和 experiment 分支,加入例如如下两行:
[remote "origin"]
url = https://github.com/schacon/simplegit-progit
fetch = +refs/heads/master:refs/remotes/origin/master
fetch = +refs/heads/experiment:refs/remotes/origin/experiment
注意:不能在模式中使用部分通配符,因此像如下这种引用规格是不合法的
fetch = +refs/heads/qa*:refs/remotes/origin/qa* # 不合法
fetch = +refs/heads/*:refs/remotes/origin/* # 合法
(2)引用规格推送
把master分支推送到远程server的 qa/master 分支上
$ git push origin master:refs/heads/qa/master
假设他们但愿 Git 每次执行 git push origin
时都像上面这样推送,可以在他们的配置文件里加入一条 push 值:
[remote "origin"]
url = https://github.com/schacon/simplegit-progit
fetch = +refs/heads/*:refs/remotes/origin/*
push = refs/heads/master:refs/heads/qa/master
(3)删除引用
$ git push origin :topic
因为引用规格(的格式)是 <src>:<dst>
,因此上述命令把 <src>
留空。意味着把远程版本号库的 topic 分支定义为空值。也就是删除它。
(1)维护
Git会不定时地本身主动执行一个叫作“auto gc”的命令。大多数时候,这个命令并不会产生效果。
然而。假设有太多松散对象(不在包文件里的对象)或者太多包文件,Git会执行一个完整的git gc命令。
“gc” 表明垃圾回收。这个命令会作如下事情:收集所有松散对象并将它们放置到包文件里。将多个包文件合并为一个大的包文件,移除与不论什么提交都不相关的陈旧对象。
# 手动执行本身主动垃圾回收
$ git gc --auto
就像上面提到的,这个命令一般并不会产生效果。大约需要7000个以上的松散对象或超过50个的包文件才干让Git启动一次真正的gc命令。
你可以经过改动gc.auto与gc.autopacklimit的设置来改动这些数值。
(2)数据恢复
在你使用Git的时候。你可能会意外丢失一次提交。一般这是因为你强制删除了正在工做的分支。但是最后却发现你还需要这个分支;亦或者硬重置了一个分支,放弃了你想要的提交。
假设这些事情已经发生,该怎样找回你的提交呢?
$ git log --pretty=oneline
f991403ee78279300170ee9d192931668d2645d3 modified new.txt
21b61e04b11b0bb6e8aedd8d21132974a23630be Second commit 1b63b62c89014812fb7d00c6c47b80abcec286e0 First commit # 将master分支硬重置到第二次提交 $ git reset --hard 21b61e04b11b0bb6e8aedd8d21132974a23630be HEAD is now at 21b61e0 Second commit $ git log --pretty=oneline 21b61e04b11b0bb6e8aedd8d21132974a23630be Second commit 1b63b62c89014812fb7d00c6c47b80abcec286e0 First commit
现在顶部的提交已经丢失了-没有分支指向这些提交。你需要找出最后一次提交的SHA-1而后添加一个指向它的分支。窍门就是找到最后一次的提交的SHA-1-但是预计你记不起来了。对吗?最方便。也是最常用的方法。是使用一个名叫git reflog 的工具。
$ git reflog
21b61e0 HEAD@{0}: reset: moving to 21b61e04b11b0bb6e8aedd8d21132974a23630be
f991403 HEAD@{1}: commit: modified new.txt
21b61e0 HEAD@{2}: commit: Second commit
1b63b62 HEAD@{3}: commit: First commit
为了使显示的信息更加实用,咱们可以执行 git log -g
$ git branch recover-branch f991403
$ git checkout recover-branch
$ git log --pretty=oneline
f991403ee78279300170ee9d192931668d2645d3 modified new.txt
21b61e04b11b0bb6e8aedd8d21132974a23630be Second commit 1b63b62c89014812fb7d00c6c47b80abcec286e0 First commit
(3)移除对象
git clone
会下载整个项目的历史,包括每一个文件的每一个版本号。假设所有的东西都是源码那么这很好,因为Git被高度优化来有效地存储这种数据。然而。假设某我的在以前向项目加入了一个大小特别大的文件,即便你将这个文件从项目中移除了,每次克隆仍是都要强制的下载这个大文件。
之因此会产生这个问题。是因为这个文件在历史中是存在的,它会永远在那里。
因此,你必须找到并移除这些大文件。警告:这个操做对提交历史的改动是破坏性的。它会从你必须改动或移除一个大文件引用最先的树对象開始重写每一次提交。假设你在导入仓库后。在不论什么人開始基于这些提交工做前执行这个操做,那么将不会有不论什么问题;不然,你必须通知所有的贡献者他们需要将他们的成果变基到你的新提交上。
# 加入一个大文件到仓库中
curl https://github.com/381510688/javascript_test.git > git.tgz
$ git add git.tgz
$ git commit -m "add big file"
# 移除这个大文件
$ git rm git.tgz
$ git commit -m "oops - remove big file"
# 执行 gc 来查看数据库占用了多少空间
$ git gc
Counting objects: 31, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (20/20), done.
Writing objects: 100% (31/31), done.
Total 31 (delta 5), reused 26 (delta 4)
# 也可以执行 count-objects 命令来高速的查看占用空间大小
$ git count-objects -v
count: 1
size: 4
in-pack: 31
packs: 1
size-pack: 4
prune-packable: 0
garbage: 0
size-garbage: 0
# 找出哪一个文件或哪些文件占用了如此多的空间,而后对输出内容的第三列(即文件大小)进行排序
git verify-pack -v .git/objects/pack/pack-d3e9607420577f00bdd580919f4d70835010c9a9.idx | sort -k 3 -n | tail -3;
7246fb5e4a10799d0f37c296a0de4d89d907aef4 blob 178 121 2435
9b8415079b0023a650395f070be3556d96d1e9d1 commit 227 155 12
7246fb5e4a10799d0f37c296a0de4d89d907aef4 commit 256 171 768
# 找出数据对象的名字
git rev-list --objects --all | grep 7246fb5e4a10799d0f37c296a0de4d89d907aef4
7246fb5e4a10799d0f37c296a0de4d89d907aef4 git.tgz
# 从过去所有的树中移除这个文件
$ git log --oneline --branches -- git.tgz
9b84150 oops - remove big file
5a17b55 add big file
$ git filter-branch --index-filter \
'git rm --ignore-unmatch --cached git.tgz' -- 5a17b55^..
历史中将再也不包括对那个文件的引用。
只是。你的引用日志和你在 .git/refs/original 经过 filter-branch 选项加入的新引用中还存有对这个文件的引用,因此你必须移除它们而后又一次打包数据库。 在又一次打包前需要移除不论什么包括指向那些旧提交的指针的文件:
$ rm -Rf .git/refs/original
$ rm -Rf .git/logs/
$ git gc
这个大文件还在你的松散对象中,并无消失;但是它不会在推送或接下来的克隆中出现。这才是最重要的。 假设真的想要删除它。可以经过有 –expire 选项的 git prune 命令来全然地移除那个对象:
$ git prune --expire now
做为一套内容寻址文件系统,Git 不只仅是一个版本号控制系统。它同一时候是一个很强大且易用的工具。