git如何查看缓存区文件内容_详解Git工作区、暂存区、历史记录区以及git reset、git revert、git checkout等撤销命令的区别...
一、可以將git簡單的分為三個區(qū)域?? 1、工作區(qū)(working directory)??? 2、暫緩區(qū)(stage index)??? 3、歷史記錄區(qū)(history)????如圖:
其中g(shù)it add files 把當(dāng)前工作目錄中的文件放入暫存區(qū)域
這其實做了兩件事:???? 1、將本地文件的時間戳、長度,當(dāng)前文檔對象的id等信息保存到一個樹形目錄中去(index,即平時說的暫存區(qū))???? 2、將本地文件的內(nèi)容做快照并保存到Git 的對象庫?。
綜上2點(diǎn)來說,暫存區(qū)實際上就是一個包含文件索引的目錄樹,像是一個虛擬的工作區(qū)。在這個虛擬工作區(qū)的目錄樹中,記錄了文件名、文件的狀態(tài)信息(時間戳、文件長度等),文件的內(nèi)容并不存儲其中,而是保存在 Git 對象庫(.git/objects)中,文件索引建立了文件和對象庫中對象實體之間的對應(yīng)。???? 如圖:
在這個圖中,我們可以看到部分 Git 命令是如何影響工作區(qū)和暫存區(qū)(stage, index)的:??? 圖中左側(cè)為工作區(qū),右側(cè)為版本庫。在版本庫中標(biāo)記為 "index" 的區(qū)域是暫存區(qū)(stage, index),標(biāo)記為 "master" 的是 master 分支所代表的目錄樹。??? 圖中我們可以看出此時 "HEAD" 實際是指向 master 分支的一個“游標(biāo)”。所以圖示的命令中出現(xiàn) HEAD 的地方可以用 master 來替換。??? 圖中的 objects 標(biāo)識的區(qū)域為 Git 的對象庫,實際位于 ".git/objects" 目錄下??? 當(dāng)對工作區(qū)修改(或新增)的文件執(zhí)行 "git add" 命令時,暫存區(qū)的目錄樹被更新,同時工作區(qū)修改(或新增)的文件內(nèi)容被寫入到對象庫中的一個新的對象中,而該對象的ID 被記錄在暫存區(qū)的文件索引中?? 當(dāng)執(zhí)行提交操作(git commit)時,暫存區(qū)的目錄樹寫到版本庫(對象庫)中,master 分支會做相應(yīng)的更新。即 master 指向的目錄樹就是提交時暫存區(qū)的目錄樹 ?。
當(dāng)執(zhí)行 "git status" 命令掃描工作區(qū)改動的時候,先依據(jù) .git/index 文件中記錄的(工作區(qū)跟蹤文件的)時間戳、長度等信息判斷工作區(qū)文件是否改變。如果工作區(qū)的文件時間戳改變,說明文件的內(nèi)容可能被改變了,需要打開文件,讀取文件內(nèi)容,和更改前的原始文件相比較(本地文件和與之對應(yīng)的object庫中的文件的內(nèi)容進(jìn)行對比),判斷文件內(nèi)容是否被更改。如果文件內(nèi)容沒有改變,則將該文件新的時間戳記錄到 .git/index 文件中。因為判斷文件是否更改,使用時間戳、文件長度等信息進(jìn)行比較要比通過文件內(nèi)容比較要快的多,所以 Git 這樣的實現(xiàn)方式可以讓工作區(qū)狀態(tài)掃描更快速的執(zhí)行,這也是 Git 高效的因素之一。
git diff files用來進(jìn)行具體文件的變動對比,通常用來進(jìn)行工作區(qū)與暫存區(qū)之間的對比,實質(zhì)上是用 git objects 庫中的快照與工作區(qū)文件的內(nèi)容的對比。
另外,Git中提供了幾個相關(guān)的撤銷操作的命令,如git reset、git revert、git checkout,這幾者之間的用法各有不同。
二、git reset的用法
從上圖可知:git reset -- files 用來撤銷最后一次的git add files(因為每git add file一次,暫存區(qū)的文件都會被更改一次),你也可以用git reset 撤銷所有暫存區(qū)域文件。
另外:
一、git reset的用法:git reset + commit號
1、git reset命令后面需要加2種參數(shù):"--hard"和"--soft",如果不加,默認(rèn)情況下是"--soft"。
2、--soft表示該條commit號之后(時間作為參考點(diǎn))的所有commit的修改都會退回到git緩沖區(qū)中。所以使用git status命令可以在緩沖區(qū)中看到這些修改。
3、"--hard"則表示緩沖區(qū)中不會存儲這些修改,git會直接丟棄這部分內(nèi)容,但需要注意的一個問題是:這樣的重置是直接在本地的修改,無法提交到遠(yuǎn)程服務(wù)器,如果直接丟棄的內(nèi)容已經(jīng)被推到遠(yuǎn)程服務(wù)器上了,則會造成本地和服務(wù)器無法同步的問題,即git reset --hard只能針對本地操作,不能針對遠(yuǎn)程服務(wù)器進(jìn)行同樣操作。如果從本地刪掉的內(nèi)容沒有推到服務(wù)器上,則不會有副作用,如果被推到服務(wù)器,則下次本地和服務(wù)器進(jìn)行同步時,這
部分刪掉的內(nèi)容仍然會回來。
(其實這個問題則可以很好的被git revert 命令解決,使用git revert + commit號,該命令撤銷對某個commit的提交,這一撤銷動作會作為一個新的修改存儲起來,這樣,當(dāng)你和服務(wù)器同步時,就不會產(chǎn)生什么副作用。)
其實在merge的時候,也有可能會用到git reset.
如果我們當(dāng)前使用git pull的時候,可能會出現(xiàn)merge沖突,在沖突狀態(tài)下,需要解決沖突的文件會從index暫存區(qū)打回到工作區(qū)。
如果有沖突的時候,一般用如下步驟解決沖突:
1、用工具或者手工解決沖突
2、git add 命令來表明沖突已經(jīng)解決。
3、再次commit已解決沖突的文件。
這當(dāng)中,可以使用git reset --hard ORIG_HEAD用來撤銷已經(jīng)commit的merge.
使用git reset --hard HEAD 用來撤銷還沒commit 的merge,其實原理就是放棄index和工作區(qū)的改動。
也可以使用git reset --merge ORIG_HEAD,注意其中的--hard 換成了 --merge,這樣就可以避免在回滾時清除working tree。
三、git checkout的用法
從上圖可知,git checkout -- files 把文件從暫存區(qū)域復(fù)制到工作目錄,用來丟棄本地修改。 需要另外注意的是:
1、當(dāng)執(zhí)行 "git rm --cached " 命令時,會直接從暫存區(qū)刪除文件,工作區(qū)則不做出改變。? ? ? ?2、當(dāng)執(zhí)行 "git checkout ." 或者 "git checkout -- " 命令時,會用暫存區(qū)全部或指定的文件替換工作區(qū)的文件。這個操作很危險,會清除工作區(qū)中未添加到暫存區(qū)的改動
3、當(dāng)執(zhí)行 "git checkout HEAD ." 或者 "git checkout HEAD " 命令時,會用 HEAD 指向的 master 分支中的全部或者部分文件替換暫存區(qū)以及工作區(qū)中的文件。這個命令也是極具危險性的,因為不但會清除工作區(qū)中未提交的改動,也會清除暫存區(qū)中未提交的改動。
四、git revert的用法
git revert 也是撤銷命令,區(qū)別在于reset是指向原地或者向前移動指針,git revert是創(chuàng)建一個commit來覆蓋當(dāng)前的commit,指針向后移動。
那么兩者的具體區(qū)別有:
1)git revert 是撤銷某次操作,此次操作之前的commit都會被保留,而git reset 是撤銷某次提交,但是此次之后的修改都會被退回到暫存區(qū)中。
具體一個例子,假設(shè)有三個commit(commit1,commit2,commit3),使用 git status:
commit3: add test3.c
commit2: add test2.c
commit1: add test1.c
當(dāng)執(zhí)行g(shù)it revert HEAD~1時(撤銷倒數(shù)第二個操作),第二個操作即commit2這個操作被撤銷了,使用git log可以看到:
commit1:add test1.c
commit3:add test3.c
由于git revert不會回退到暫存區(qū)中,所以使用git status 沒有任何變化
如果換做執(zhí)行g(shù)it reset --soft(默認(rèn)) HEAD~1后,運(yùn)行g(shù)it log可以看到
commit2: add test2.c
commit1: add test1.c
運(yùn)行g(shù)it status,可以看到test3.c處于暫存區(qū)了,準(zhǔn)備提交。
但如果換做執(zhí)行g(shù)it revert后,
顯示:HEAD is now at commit2,運(yùn)行g(shù)it log可以看到
commit2: add test2.c
commit1: add test1.c
運(yùn)行g(shù)it status, 則沒有任何變化
所以,git revert與git reset最大的不同是,git revert 僅僅是撤銷某次提交,而git reset會將撤銷點(diǎn)之后的操作
都回退到暫存區(qū)中。
1、git revert是用一次新的commit來回滾之前的commit,git reset是直接刪除指定的commit。
2、在回滾這一操作上看,效果差不多。但是在日后繼續(xù)merge以前的老版本時有區(qū)別。
因為git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch時,導(dǎo)致這部分改變不會再次出現(xiàn),但是git reset是之間把某些commit在某個branch上刪除,因而和老的branch再次merge時,這些被回滾的commit應(yīng)該還會被引入。
3、git reset 是把HEAD向后移動了一下,而git revert是HEAD繼續(xù)前進(jìn),只是新的commit的內(nèi)容和要revert的內(nèi)容正好相反,能夠抵消要被revert的內(nèi)容。
六、不得不提的git的其它刪除命令(類似于Linux的命令):
git rm --cached readme.txt 只從緩存區(qū)中刪除readme.txt,保留物理文件
git rm readme.txt 不但從緩存區(qū)中刪除,同時刪除物理文件
git mv a.txt b.txt 把a(bǔ).txt改名為b.txt
綜上所以我們有時如果是想撤銷對單個文件的更改:
、如果已經(jīng)用add命令把文件加入stage暫存區(qū)了:
1、就先需要從stage暫存區(qū)中撤銷:
"git reset HEAD ..."
2、然后再從工作區(qū)撤銷,即將暫存區(qū)的文件替換工作區(qū)當(dāng)前的文件
"git checkout -- ..." to discard changes in working directory
如:git checkout a.txt ?撤銷a.txt的變動(工作區(qū)上的文件)
如果是多個文件:git chenkout .
、如果已經(jīng)commit了,則需要
1、使用git commit --amend來進(jìn)行修改,這個只能修改最近一次的,也就是用一個新的提交來覆蓋上一次的提交。因此如果push以后再做這個動作就會有危險。
2、git reset --hard HEAD 放棄工作區(qū)和index的改動,HEAD指針仍然指向當(dāng)前的commit.(參照第一幅圖)
這條命令同時還可以用來撤銷還沒commit的merge,其實原理就是放棄index暫存區(qū)和工作區(qū)的改動,因為沒commit的改動只存在于index暫存區(qū)和工作區(qū)中。
而git reset --hard HEAD^ 用來撤銷已經(jīng)commit的內(nèi)容(等價于 git reset --hard HEAD~1) 。原理就是放棄工作區(qū)和index的改動,同時HEAD指針指向前一個commit對象。
總結(jié)
以上是生活随笔為你收集整理的git如何查看缓存区文件内容_详解Git工作区、暂存区、历史记录区以及git reset、git revert、git checkout等撤销命令的区别...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle数据库恢复aul_RMAN备
- 下一篇: android imageview 设置