Git 學(xué)習(xí)筆記
GitHub瀏覽器快捷鍵:
t: 查找
先丟一堆圖评也。。就是這么任性
目錄
Git對(duì)象說(shuō)明
1.Git對(duì)象模型
SHA :所有用來(lái)表示項(xiàng)目歷史信息的文件涧至,都是通過(guò)對(duì)對(duì)象做SHA1哈希得到的40個(gè)字符的對(duì)象名來(lái)進(jìn)行索引
與SVN的區(qū)別
SVN,CVS:增量文件系統(tǒng),存儲(chǔ)每次提交之間的差異
Git:存儲(chǔ)每次提交的文件的全部?jī)?nèi)容
對(duì)象
包括三個(gè)部分:類型(對(duì)象類型),大刑崤臁(內(nèi)容大小)念链,內(nèi)容
四種類型的對(duì)象:blob, tree commit tag
blob: 用來(lái)存儲(chǔ)數(shù)據(jù)文件盼忌,通常是一個(gè)文件
tree: 有點(diǎn)像目錄,管理一些tree或者blob
commit: 一個(gè)commit只指向一個(gè)tree掂墓,用來(lái)標(biāo)記項(xiàng)目某個(gè)特定時(shí)間點(diǎn)的狀態(tài)谦纱,包括一些關(guān)于時(shí)間點(diǎn)的元數(shù)據(jù)(時(shí)間戳,最近一次提交的作者君编,指向上次提交的指針等)
tag: 標(biāo)記某個(gè)提交的方法
幾乎所有的Git功能都是使用這四個(gè)簡(jiǎn)單的對(duì)象模型來(lái)完成跨嘉,就像在本機(jī)的文件系統(tǒng)之上構(gòu)建了一個(gè)小的文件系統(tǒng)
1. Blob
git show XX
![blob][]
一塊二進(jìn)制數(shù)據(jù),不指向任何東西吃嘿,沒(méi)有任何屬性祠乃,因?yàn)閎lob對(duì)象內(nèi)容全部都是數(shù)據(jù),如兩個(gè)文件在一個(gè)目錄樹(shù)(或是一個(gè)版本倉(cāng)庫(kù))中有同樣的數(shù)據(jù)內(nèi)容兑燥,那么它們將會(huì)共享同一個(gè)blob對(duì)象亮瓷。Blob對(duì)象和其所對(duì)應(yīng)的文件所在路徑、文件名是否改被更改都完全沒(méi)有關(guān)系降瞳。
2. Tree
git ls-tree 31adb53
一串直線blob對(duì)象或者其他tree對(duì)象的指針嘱支,一般表示內(nèi)容之間的目錄層次關(guān)系。
一個(gè)tree對(duì)象包括一串(list)條目力崇,每一個(gè)條目包括:mode斗塘、對(duì)象類型、SHA1值 和名字(這串條目是按名字排序的)亮靴。它用來(lái)表示一個(gè)目錄樹(shù)的內(nèi)容馍盟。
(注意:在submodules里,trees對(duì)象也可以指向commits對(duì)象. 請(qǐng)參見(jiàn) Submodules 章節(jié))
注意:所有的文件的mode位都是644 或 755茧吊,這意味著Git只關(guān)心文件的可執(zhí)行位.
3. Commit
可以用git show -s --pretty=raw 31adb53f48cc43f72ee325cac509bf120357657e
查看
指向一個(gè)tree對(duì)象贞岭,并帶有相關(guān)描述信息
4. Tag
一個(gè)標(biāo)簽對(duì)象包括一個(gè)對(duì)象名(譯者注:就是SHA1簽名), 對(duì)象類型, 標(biāo)簽名, 標(biāo)簽創(chuàng)建人的名字("tagger"), 還有一條可能包含有簽名(signature)的消息. 你可以用 git cat-file
命令來(lái)查看這些信息:
Git目錄與工作目錄
Git目錄:為你的項(xiàng)目存儲(chǔ)所有歷史和元信息的目錄,包括所有對(duì)象搓侄。
Git工作目錄:存儲(chǔ)著你現(xiàn)在遷出(checkout)來(lái)用來(lái)編輯的文件瞄桨。
Git索引
Git索引是一個(gè)在你的工作目錄和項(xiàng)目倉(cāng)庫(kù)間的暫存區(qū)(Staging area),每次commit提交的內(nèi)容就是當(dāng)前索引(Index)里的內(nèi)容
Git Start
1. Git安裝
1.從源代碼開(kāi)始安裝
2.通過(guò)一些應(yīng)用包來(lái)安裝
Linux讶踪,Mac芯侥,windows
2. 安裝與初始化
設(shè)置名字和email,這些都是提交commit的時(shí)候的前簽名
$ git config --global user.name "Scott Chacon" $ git config --global user.email "schacon@gmail.com"
git config --list:查看配置信息
- 獲取git倉(cāng)庫(kù) 三種途徑
- git clone git@gitlab.lukou.com:develop/iLukou.git(配置SSH,Add SSH public key)
- git clone http://gitlab.lukou.com/develop/iLukou.git
- git init in your project
3.工作流程開(kāi)始
- git add file(添加到file索引) / git commit -a(自動(dòng)添加索引修改到索引并提交) / 縮寫 gaa(git add .)
- git commit -m / 縮寫 gcmsg xxx
- git push originName originBranch / 縮寫 gp originName originBranch
4.分支合并
now in branch yyy
git branch 得到當(dāng)前倉(cāng)庫(kù)的所有分支
git branch XXX 創(chuàng)建分支XXX
git checkout XXX (gco) 切換到XXX分支 (checkout 會(huì)改index柱查,Workspace 廓俭,head to the last commit in XXX,所以需要先commit再co)
git merge xxx 合并xxx到y(tǒng)yy現(xiàn)有分支
git diff if 有沖突唉工,diff來(lái)查看沖突研乒,然后解決沖突再commit,commit之后淋硝,gitk(這個(gè)命令不知用)
git branch -d xxx 刪除xxx
reset and checkout
reset
- git reset --hard commitID
change head to the commit ID,暫存區(qū)雹熬,工作區(qū)和引用指向的目錄樹(shù)三者一致
- git reset (--mixed) commitID
change head to the commitID,暫存區(qū)和引用指向的目錄樹(shù)相同,工作區(qū)不變
- git reset --soft commitID
change head to the commitID,暫存區(qū)和工作區(qū)不變
checkout
git checkout (commit) paths , commit可選谣膳,若省略則工作區(qū)與暫存區(qū)指向的內(nèi)容相同竿报,修改工作區(qū),不修改HEAD指針
git checkout branch ,暫存區(qū)工作區(qū)和branch下上次commit時(shí)引用指向的目錄樹(shù)一致参歹,改變HEAD指針仰楚,HEAd只有在切換到一個(gè)分支時(shí)才可以對(duì)提交進(jìn)行跟蹤,犬庇,否則仍然會(huì)進(jìn)入分離頭指針的狀態(tài)僧界,在分離頭指針額狀態(tài)下的提交并不能被引用關(guān)聯(lián)到,從而可能丟失臭挽,所以該命令的主要作用是切換分支.
git checkout 匯總工作區(qū)捂襟,暫存區(qū)和HEAd的差異
- git checkout branch -- filename
維持HEAD的指向不變.用branch所指向的提交中的filename替換暫存區(qū)和工作區(qū)中相應(yīng)的文件.會(huì)將暫存區(qū)和工作區(qū)中的filename直接覆蓋
撒銷一個(gè)合并
如果你覺(jué)得你合并后的狀態(tài)是一團(tuán)亂麻,想把當(dāng)前的修改都放棄欢峰,你可以用下面的命令回到合并之前的狀態(tài):
$ git reset --hard HEAD
或者你已經(jīng)把合并后的代碼提交葬荷,但還是想把它們?nèi)鲣N:
$ git reset --hard ORIG_HEAD
但是剛才這條命令在某些情況會(huì)很危險(xiǎn),如果你把一個(gè)已經(jīng)被另一個(gè)分支合并的分支給刪了纽帖,那么 以后在合并相關(guān)的分支時(shí)會(huì)出錯(cuò)宠漩。
快速向前合并
還有一種需要特殊對(duì)待的情況,在前面沒(méi)有提到懊直。通常扒吁,一個(gè)合并會(huì)產(chǎn)生一個(gè)合并提交(commit), 把兩個(gè)父分支里的每一行內(nèi)容都合并進(jìn)來(lái)。
但是室囊,如果當(dāng)前的分支和另一個(gè)分支沒(méi)有內(nèi)容上的差異雕崩,就是說(shuō)當(dāng)前分支的每一個(gè)提交(commit)都已經(jīng)存在另一個(gè)分支里了,git 就會(huì)執(zhí)行一個(gè)“快速向前"(fast forward)操作融撞;git 不創(chuàng)建任何新的提交(commit),只是將當(dāng)前分支指向合并進(jìn)來(lái)的分支
查看git日志
git log
git diff branchA..branchB a到b的工作區(qū)改動(dòng)
git diff branchB 當(dāng)前工作目錄與另一個(gè)分支的差別
分布式工作流程
兩個(gè)分支的修改同一份內(nèi)容
git pull oringinName branchName
git pull : 從遠(yuǎn)程分支抓取修改的內(nèi)容盼铁,然后把他合并到當(dāng)前分支(git fetch + git merge)
將修改推到公共倉(cāng)庫(kù)
git push ssh://yourserver.com/~you/proj.git master
和git-fetch命令一樣git-push如果命令的執(zhí)行結(jié)果不是"快速向前"(fast forward) 就會(huì)報(bào)錯(cuò)
Git標(biāo)簽
用git tag
創(chuàng)建標(biāo)簽制定某個(gè)提交
git tag tagName commitID
當(dāng)這樣的一條命令執(zhí)行后,一個(gè)新的對(duì)象被添加到Git對(duì)象庫(kù)中尝偎,并且標(biāo)簽引用就指向了 一個(gè)標(biāo)簽對(duì)象饶火,而不是指向一個(gè)提交(commit). 這樣做的好處就是:你可以為一個(gè)標(biāo)簽 打處簽名(sign), 方便你以后來(lái)查驗(yàn)這是不是一個(gè)正確的提交(commit).
下面是一個(gè)創(chuàng)建標(biāo)簽對(duì)象的例子:
$ git tag -a stable-1 1b2e1d63ff
標(biāo)簽對(duì)象可以指向任何對(duì)象,但是在通常情況下是一個(gè)提交(commit). (在Linux內(nèi)核代 碼中,第一個(gè)標(biāo)簽對(duì)象是指向一個(gè)樹(shù)對(duì)象(tree),而不是指向一個(gè)提交(commit)).
忽略文件
vim .gitignore
.gitignor文件同樣可以像其它文件一樣加到項(xiàng)目倉(cāng)庫(kù)里( 直接用 git add .gitignore 和 git commit等命令), 這樣項(xiàng)目里的其它開(kāi)發(fā)者也能共享同一套忽略 文件規(guī)則肤寝。
如果你想忽略規(guī)則只對(duì)特定的倉(cāng)庫(kù)起作用,你可以把這些忽略規(guī)則寫到你的倉(cāng)庫(kù)下 .git/info/exclude文件中牧挣,或是寫在Git配置變量core.excludesfile中指定的 文件里。
rebase
git checkout -b mywork rogin
基于遠(yuǎn)程分支醒陆,創(chuàng)建mywork分支
在分支mywork中,生成兩次提交,此時(shí)裆针,在origin分支刨摩,有其他人生成了兩次提交,則兩個(gè)分支都各自向前進(jìn)了世吨,出現(xiàn)了分叉澡刹,這時(shí),
1.我們可以merge耘婚,合并origin分支生成一個(gè)新的提交罢浇,該提交指向兩個(gè)父commit
2.也可以rebase,將mywork指向origin的最新提交
這些命令會(huì)把你的"mywork"分支里的每個(gè)提交(commit)取消掉沐祷,并且把它們臨時(shí) 保存為補(bǔ)丁(patch)(這些補(bǔ)丁放到".git/rebase"目錄中),然后把"mywork"分支更新 到最新的"origin"分支嚷闭,最后把保存的這些補(bǔ)丁應(yīng)用到"mywork"分支上。
當(dāng)'mywork'分支更新之后赖临,它會(huì)指向這些新創(chuàng)建的提交(commit),而那些老的提交會(huì)被丟棄胞锰。 如果運(yùn)行垃圾收集命令(pruning garbage collection), 這些被丟棄的提交就會(huì)刪除。
在rebase的過(guò)程中兢榨,也許會(huì)出現(xiàn)沖突(conflict). 在這種情況嗅榕,Git會(huì)停止rebase并會(huì)讓你去解決 沖突;在解決完沖突后吵聪,用"git-add"命令去更新這些內(nèi)容的索引(index), 然后凌那,你無(wú)需執(zhí)行 git-commit,只要執(zhí)行:
$ git rebase --continue
這樣git會(huì)繼續(xù)應(yīng)用(apply)余下的補(bǔ)丁。
在任何時(shí)候吟逝,你可以用--abort參數(shù)來(lái)終止rebase的行動(dòng)帽蝶,并且"mywork" 分支會(huì)回到rebase開(kāi)始前的狀態(tài)。
$ git rebase --abort
交互式rebase
你亦可以選擇進(jìn)行交互式的rebase澎办。這種方法通常用于在向別處推送提交之前對(duì)它們進(jìn)行重寫嘲碱。交互式rebase提供了一個(gè)簡(jiǎn)單易用的途徑讓你在和別人分享提交之前對(duì)你的提交進(jìn)行分割、合并或者重排序
局蚀。在把從其他開(kāi)發(fā)者處拉取的提交應(yīng)用到本地時(shí)麦锯,你也可以使用交互式rebase對(duì)它們進(jìn)行清理。
如果你想在rebase的過(guò)程中對(duì)一部分提交進(jìn)行修改琅绅,你可以在'git rebase'命令中加入'-i'或'--interactive'參數(shù)去調(diào)用交互模式扶欣。
這個(gè)命令會(huì)執(zhí)行交互式rebase操作,操作對(duì)象是那些自最后一次從origin倉(cāng)庫(kù)拉取或者向origin推送之后的所有提交。
若想查看一下將被rebase的提交料祠,可以用如下的log命令:
git rebase -i origin/master
一旦運(yùn)行了'rebase -i'命令骆捧,你所預(yù)設(shè)的編輯器會(huì)被調(diào)用,其中含有如下的內(nèi)容:
pick fc62e55 added file_size
pick 9824bf4 fixed little thing
pick 21d80a5 added number to log
pick 76b9da6 added the apply command
pick c264051 Revert "added file_size" - not implemented correctly
Rebase f408319..b04dc3d onto f408319
#
Commands:
p, pick = use commit
e, edit = use commit, but stop for amending
s, squash = use commit, but meld into previous commit
#
If you remove a line here THAT COMMIT WILL BE LOST.
However, if you remove everything, the rebase will be aborted.
#
這些信息表示從你上一次推送操作起有5個(gè)提交髓绽。每個(gè)提交都用一行來(lái)表示敛苇,行格式如下:
(action) (partial-sha) (short commit message)
1.如果指定進(jìn)行'pick'操作,git會(huì)應(yīng)用這個(gè)補(bǔ)丁顺呕,以同樣的提交信息(commit message)保存提交枫攀。
2.如果指定進(jìn)行'squash'操作,git會(huì)把這個(gè)提交和前一個(gè)提交合并成為一個(gè)新的提交株茶。這會(huì)再次調(diào)用編輯器来涨,你在里面合并這兩個(gè)提交的提交信息。所以启盛,如果你(在上一步)以如下的內(nèi)容離開(kāi)編輯器:
3.如果指定進(jìn)行'edit'操作蹦掐,git會(huì)完成同樣的工作,但是在對(duì)下一提交進(jìn)行操作之前僵闯,它會(huì)返回到命令行讓你對(duì)提交進(jìn)行修正卧抗,或者對(duì)提交內(nèi)容進(jìn)行修改。
$ git reset HEAD^
$ git add file1
$ git commit 'first part of split commit'
$ git add file2
$ git commit 'second part of split commit'
$ git rebase --continue
4.交互式rebase的最后一個(gè)作用是丟棄提交鳖粟。如果把一行刪除而不是指定'pick'颗味、'squash'和'edit'中的任何一個(gè),git會(huì)從歷史中移除該提交牺弹。
交互式添加
git add -i
$>git add -i
staged unstaged path
1: unchanged +4/-0 assets/stylesheets/style.css
2: unchanged +23/-11 layout/book_index_template.html
3: unchanged +7/-7 layout/chapter_template.html
4: unchanged +3/-3 script/pdf.rb
5: unchanged +121/-0 text/14_Interactive_Rebasing/0_ Interactive_Rebasing.markdown
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now>
我們可以進(jìn)行數(shù)個(gè)有用的操作浦马,包括取消文件的暫存(3: revert),加入未跟蹤的文件(4: add untracked)和查看差異(6: diff)张漂。這些功能都很易懂晶默。還有一個(gè)很“酷”的功能,就是暫存補(bǔ)逗皆堋(staging patches)(5: patch)磺陡。
儲(chǔ)藏
當(dāng)你正在做一項(xiàng)復(fù)雜的工作時(shí), 發(fā)現(xiàn)了一個(gè)和當(dāng)前工作不相關(guān)但是又很討厭的bug. 你這時(shí)想先修復(fù)bug再做手頭的工作, 那么就可以用 git stash 來(lái)保存當(dāng)前的工作狀態(tài), 等你修復(fù)完bug后,執(zhí)行'反儲(chǔ)藏'(unstash)操作就可以回到之前的工作里.
git stach save "work in progress for foo feature"
上面這條命令會(huì)保存你的本地修改到儲(chǔ)藏(stash)中, 然后將你的工作目錄和索引里的內(nèi)容全部重置, 回到你當(dāng)前所在分支的上次提交時(shí)的狀態(tài)(git reset --hard HEAD)
after do some debug and git commit -a -m "fixed bug"
you can git stash apply
back to your work before
you can run several git stash
, to stash your work,
see the stash with git stash list
可以用類似'git stash apply stash@{1}'的命令來(lái)使用在隊(duì)
列中的任意一個(gè)'儲(chǔ)藏'(stashes). 'git stash clear‘則是用來(lái)清空這個(gè)隊(duì)列.
Git樹(shù)名
不用40個(gè)字節(jié)長(zhǎng)的SHA串來(lái)表示一個(gè)提交(commit)或是其它git對(duì)象, 有很多種名字表示方法. 在Git里,這些名字就叫'樹(shù)名'(treeish).
Sha短名
以下等價(jià)
980e3ccdaac54a0d4de358f3fe5d718027d96aae
980e3ccdaac54a0d4
980e3cc
分支,remote,標(biāo)簽
使用分支漠畜,remote币他,標(biāo)簽來(lái)代替sha串名,他們只是指向某個(gè)對(duì)象的指針憔狞,
日期標(biāo)識(shí)符
追蹤分支
在Git中蝴悉,追蹤分支是用于聯(lián)系本地分支和遠(yuǎn)程分支的,如果你在’追蹤分支'(Tracking Branches)上執(zhí)行推送(push)或拉取(pull)時(shí), 它會(huì)自動(dòng)推送(push)或拉取(pull)到關(guān)聯(lián)的遠(yuǎn)程分支上.
如果你經(jīng)常要從遠(yuǎn)程倉(cāng)庫(kù)里拉取(pull)分支到本地,并且不想很麻煩的使用"git pull "這種格式; 那么就應(yīng)當(dāng)使用‘追蹤分支'(Tracking Branches).
‘git clone‘命令會(huì)自動(dòng)在本地建立一個(gè)'master'分支瘾敢,它是'origin/master'的‘追蹤分支’. 而'origin/master'就是被克隆(clone)倉(cāng)庫(kù)的'master'分支.
譯者注: origin一般是指原始倉(cāng)庫(kù)地址的別名.
你可以在使用'git branch'命令時(shí)加上'--track'參數(shù), 來(lái)手動(dòng)創(chuàng)建一個(gè)'追蹤分支'.
git branch --track experimental origin/experimental
當(dāng)你運(yùn)行下命令時(shí):
$ git pull experimental
它會(huì)自動(dòng)從‘origin'抓取(fetch)內(nèi)容拍冠,再把遠(yuǎn)程的'origin/experimental'分支合并進(jìn)(merge)本地的'experimental'分支.
當(dāng)要把修改推送(push)到origin時(shí), 它會(huì)將你本地的'experimental'分支中的修改推送到origin的‘experimental'分支里, 而無(wú)需指定它(origin).
搜索
git grep
git grep -c XXXX 文件名
Git的撤銷操作-重置尿这,簽出
http://gitbook.liuhui998.com/4_9.html
git revert commitID
Git維護(hù)
git gc :壓縮歷史信息來(lái)節(jié)約磁盤和內(nèi)存空間
git fsck :云心一些倉(cāng)庫(kù)的一致性檢查,有問(wèn)題就回報(bào)告庆杜,這項(xiàng)操作也有點(diǎn)耗時(shí), 通常報(bào)的警告就是“懸空對(duì)象"(dangling objects).“懸空對(duì)象"(dangling objects)并不是問(wèn)題, 最壞的情況只是它們多占了一些磁盤空間. 有時(shí)候它們是找回丟失的工作的最后一絲希望)
創(chuàng)建公共倉(cāng)庫(kù)Git
假設(shè)你個(gè)人的倉(cāng)庫(kù)在目錄 ~/proj. 我們先克隆一個(gè)新的“裸倉(cāng)庫(kù)“,并且創(chuàng)建一個(gè)標(biāo)志文件告訴git-daemon這是個(gè)公共倉(cāng)庫(kù).
$ git clone --bare ~/proj proj.git
$ touch proj.git/git-daemon-export-ok
上面的命令創(chuàng)建了一個(gè)proj.git目錄, 這個(gè)目錄里有一個(gè)“裸git倉(cāng)庫(kù)" -- 即只有'.git'目錄里的內(nèi)容,沒(méi)有任何簽出(checked out)的文件.
下一步就是你把這個(gè) proj.git 目錄拷到你打算用來(lái)托管公共倉(cāng)庫(kù)的主機(jī)上. 你可以用scp, rsync或其它任何方式.
- 通過(guò)git協(xié)議導(dǎo)出git倉(cāng)庫(kù)
用git協(xié)議導(dǎo)出git倉(cāng)庫(kù), 這是推薦的方法.
如果這臺(tái)服務(wù)器上有管理員射众,TA們要告訴你把倉(cāng)庫(kù)放在哪一個(gè)目錄中, 并且“git:// URL”除倉(cāng)庫(kù)目錄部分外是什么.
你現(xiàn)在要做的是啟動(dòng) git daemon; 它會(huì)監(jiān)聽(tīng)在 9418端口. 默認(rèn)情況下它會(huì)允許你訪問(wèn)所有的git目錄(看目錄中是否有g(shù)it-daemon-export-ok文件). 如果以某些目錄做為 git-daemon 的參數(shù), 那么 git-daemon 會(huì)限制用戶通過(guò)git協(xié)議只能訪問(wèn)這些目錄.
你可以在inetd service模式下運(yùn)行 git-daemon; 點(diǎn)擊 git daemon 可以查看幫助信息.
- 通過(guò)http協(xié)議導(dǎo)出git倉(cāng)庫(kù)
git協(xié)議有不錯(cuò)的性能和可靠性, 但是如果主機(jī)上已經(jīng)配好了一臺(tái)web服務(wù)器,使用http協(xié)議(git over http)可能會(huì)更容易配置一些.
你需要把新建的"裸倉(cāng)庫(kù)"放到Web服務(wù)器的可訪問(wèn)目錄里, 同時(shí)做一些調(diào)整,以便讓web客戶端獲得它們所需的額外信息.
$ mv proj.git /home/you/public_html/proj.git
$ cd proj.git
$ git --bare update-server-info
$ chmod a+x hooks/post-update
(最后兩行命令的解釋可以點(diǎn)擊這里查看: git update-server-info & githooks.)
拼好了proj.git的web URL, 任何人都可以從這個(gè)地址來(lái)克隆(clone)或拉取(pull) git倉(cāng)庫(kù)內(nèi)容. 下面這個(gè)命令就是例子:
$ git clone http://yourserver.com/~you/proj.git
修改你的歷史
交互式?jīng)櫤鲜切薷膯蝹€(gè)提交的好方法。
git filter-branch是修改大量提交的好方法
git bisect
二分查找問(wèn)題分支
git blame
如果你要查看文件的每個(gè)部分是誰(shuí)修改的, 那么 git blame 就是不二選擇. 只要運(yùn)行'git blame [filename]', 你就會(huì)得到整個(gè)文件的每一行的詳細(xì)修改信息:包括SHA串,日期和作者:
Git是如何物理存儲(chǔ)對(duì)象的
所有的對(duì)象都以SHA值為索引用gzip格式壓縮存儲(chǔ), 每個(gè)對(duì)象都包含了對(duì)象類型, 大小和內(nèi)容.
Git中存在兩種對(duì)象 - 松散對(duì)象(loose object)和打包對(duì)象(packed object).
1. 松散對(duì)象
松散對(duì)象是一種比較簡(jiǎn)單格式. 它就是磁盤上的一個(gè)存儲(chǔ)壓縮數(shù)據(jù)的文件. 每一個(gè)對(duì)象都被寫入一個(gè)單獨(dú)文件中.
如果你對(duì)象的SHA值是ab04d884140f7b0cf8bbf86d6883869f16a46f65, 那么對(duì)應(yīng)的文件會(huì)被存儲(chǔ)在:
GIT_DIR/objects/ab/04d884140f7b0cf8bbf86d6883869f16a46f65
Git使用SHA值的前兩個(gè)字符作為子目錄名字, 所以一個(gè)目錄中永遠(yuǎn)不會(huì)包含過(guò)多的對(duì)象. 文件名則是余下的38個(gè)字符.
2. 打包對(duì)象
另外一種對(duì)象存儲(chǔ)方式是使用打包文件(packfile). 由于Git把每個(gè)文件的每個(gè)版本都作為一個(gè)單獨(dú)的對(duì)象, 它的效率可能會(huì)十分的低. 設(shè)想一下在一個(gè)數(shù)千行的文件中改動(dòng)一行, Git會(huì)把修改后的文件整個(gè)存儲(chǔ)下來(lái), 很浪費(fèi)空間.(git GC)
查看Git對(duì)象
git-cat-file -t 54196cc2對(duì)象 (-p:對(duì)象內(nèi)容 -t:對(duì)象類型)
git ls-tree 92b8b694 樹(shù)
`