Git和其他版本控制系統(tǒng)如SVN的一個(gè)不同之處就是有暫存區(qū)的概念
工作區(qū)
就是在你電腦里能看到的目錄.使用git init
初始化的那個(gè)目錄
版本庫
工作區(qū)有一個(gè)隱藏目錄.git
,這個(gè)不算工作區(qū)而是Git的版本庫
Git的版本庫中存了很多東西佣蓉,其中非常重要的就是名為stage(或者叫index)的暫存區(qū)蹦浦,還有一個(gè)Git為我們自動(dòng)創(chuàng)建的默認(rèn)master
分支,以及一個(gè)指向master
的指針叫HEAD
在我們把文件往Git版本庫中添加的時(shí)候,先執(zhí)行的git add
操作是把文件加入到暫存區(qū),然后執(zhí)行git commit
提交修改,是把暫存區(qū)的所有內(nèi)容提交到當(dāng)前分支
因此我們平時(shí)的操作可以理解為,把需要提交的文件全都放到暫存區(qū),然后一次性提交暫存區(qū)的所有修改
管理修改
Git在版本控制之所以設(shè)計(jì)的優(yōu)秀,因?yàn)镚it跟蹤并管理的是修改而非文件
那么什么是修改呢?
eg:比如你新增了一行,這就是一個(gè)修改,刪除一行,更改或者刪除某個(gè)字符都算是一個(gè)修改,并且新增或者刪除了一個(gè)文件,也算是一個(gè)修改
為了說明Git管理的是修改而不是文件,實(shí)驗(yàn)如下:
添加一行內(nèi)容:
$ cat readme.txt
Spring-boot quickstart microservice!
This is a spring-boot combined with mongoDB example.
Test update file
Git tracks change
然后進(jìn)行添加git add
$ git add readme.txt
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: readme.txt
然后,在進(jìn)行修改:
$ cat readme.txt
Spring-boot quickstart microservice!
This is a spring-boot combined with mongoDB example.
Test update file
Git tracks change
提交:
$ git commit -m "git tracks changes"
[master 8b33073] git tracks changes
1 file changed, 1 insertion(+), 1 deletion(-)
提交后,在查看狀態(tài):
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
這時(shí)就會(huì)發(fā)現(xiàn),修改的文件沒有被提交,我們看一下這個(gè)過程:
第一次修改 -> git add
-> 第二次修改 -> git commit
因?yàn)榈诙蔚男薷牟]有執(zhí)行git add
操作加入到暫存區(qū),而是執(zhí)行了git commit
操作,這時(shí)只會(huì)把暫存區(qū)的修改提交到當(dāng)前分支,所以第一次的修改被提交了,而第二次的修改不會(huì)被提交,這樣就證明Git管理的是修改而并非文件
小結(jié):每次修改,如果不add
到暫存區(qū),那就不會(huì)加入到commit
中
撤銷修改
如果我們?cè)谛薷奈募?出現(xiàn)了錯(cuò)誤,但是發(fā)現(xiàn)及時(shí),我們就可以手動(dòng)把文件恢復(fù)到上一個(gè)版本的狀態(tài),使用git status
查看:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
你可以發(fā)現(xiàn),Git告訴你,git checkout -- file
可以丟棄工作區(qū)的修改:
$ git checkout -- readme.txt
命令git checkout -- file
意思就是,把file文件在工作區(qū)的修改全部丟棄,這里會(huì)有兩種情況:
- 一種是
file
自修改后還沒有被放到暫存區(qū),現(xiàn)在,撤銷修改就回到和版本庫當(dāng)前分支一模一樣的狀態(tài); - 一種是
file
已經(jīng)被添加到暫存區(qū)后,又進(jìn)行了修改,現(xiàn)在,撤銷修改就回到添加到暫存區(qū)之后file的狀態(tài);
總之,就是讓這個(gè)文件回到最近一次git commit
或者git add
時(shí)的狀態(tài).
git checkout -- file
命令中的--
很重要,如果沒有--
,就變成了"切換到另一個(gè)分支"的命令;
現(xiàn)在假設(shè)某天凌晨2.30,你昏昏欲睡,寫了一些胡話,還git add
到暫存區(qū)了:
$ cat readme.txt
Spring-boot quickstart microservice!
This is a spring-boot combined with mongoDB example.
Test update file
Git tracks change
my boss is still prefers SVN!
my boss is stupid!
$ git add readme.txt
慶幸的是,在commit
你發(fā)現(xiàn)了這個(gè)問題帅刀。用git status
查看一下,修改只是添加到了暫存區(qū),還沒有提交:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: readme.txt
Git提示我們,可以使用命令git reset HEAD file
把暫存區(qū)的修改撤銷掉,重新放回工作區(qū):
$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
git reset
命令既可以回退版本,也可以把暫存區(qū)的修改回退到工作區(qū).當(dāng)我們用HEAD
時(shí),表示當(dāng)前分支最新的版本,再用git status
查看一下:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
現(xiàn)在暫存區(qū)是干凈的,工作區(qū)有修改.
上面介紹了丟棄工作區(qū)的修改:
$ git checkout -- readme.txt
$ git status
# On branch master
nothing to commit (working directory clean)
這時(shí),四海八荒終于歸于平靜了.
假設(shè)如果你不但改錯(cuò)了東西,而且還提交到了版本庫,怎么辦呢?參考上一篇中版本回退,可以回到上一個(gè)版本沛慢。不過,這個(gè)操作也是有條件的,就是你還沒有把自己的本地版本庫推送到遠(yuǎn)程吵护。
小結(jié)
- 當(dāng)你改亂了工作區(qū)的某個(gè)文件內(nèi)容盒音,想直接丟棄工作區(qū)的修改竖配,用命令
git checkout -- file
; - 當(dāng)你不但改亂了工作區(qū)某個(gè)文件的內(nèi)容,還添加到了暫存區(qū)時(shí),想丟棄修改,分兩步,第一步用命令
git reset HEAD file
.就回到了上面的情況,第二步按上面的場(chǎng)景進(jìn)行操作; - 已經(jīng)提交了不合適的修改到版本庫,想要撤銷本次提交,參考版本回退這篇介紹,不過前提是沒有推送到遠(yuǎn)程版本庫;