參考博文:廖雪峰Git教程
1. 管理修改
現在,假定你已經完全掌握了暫存區的概念。下面,我們要討論的就是,為什么Git比其他版本控制系統設計得優秀,因為Git跟蹤並管理的是修改,而非文件。
你會問,什么是修改?比如你新增了一行,這就是一個修改,刪除了一行,也是一個修改,更改了某些字符,也是一個修改,刪了一些又加了一些,也是一個修改,甚至創建一個新文件,也算一個修改。
為什么說Git管理的是修改,而不是文件呢?我們還是做實驗。第一步,對README.txt做一個修改,比如加一行內容:
1 [root@mini05 zhangtest]# cat README.md 2 # zhangtest 3 zhangtest 4 張三 5 Git is a distributed version control system. 6 Git is free software. 7 111 8 222 9 Git tracks changes. # 添加的內容 10 [root@mini05 zhangtest]# git add README.md 11 [root@mini05 zhangtest]# git status 12 # On branch master 13 # Your branch is ahead of 'origin/master' by 3 commits. 14 # (use "git push" to publish your local commits) 15 # 16 # Changes to be committed: 17 # (use "git reset HEAD <file>..." to unstage) 18 # 19 # modified: README.md 20 #
然后,再修改readme.txt:
1 [root@mini05 zhangtest]# cat README.md 2 # zhangtest 3 zhangtest 4 張三 5 Git is a distributed version control system. 6 Git is free software. 7 111 8 222 9 Git tracks changes of files. # 之前行字符串,換為了這個
之后提交:
1 [root@mini05 zhangtest]# git commit -m "git tracks changes" 2 [master b293c46] git tracks changes 3 1 file changed, 1 insertion(+)
提交后,再看看狀態:
1 [root@mini05 zhangtest]# git status 2 # On branch master 3 # Your branch is ahead of 'origin/master' by 4 commits. 4 # (use "git push" to publish your local commits) 5 # 6 # Changes not staged for commit: 7 # (use "git add <file>..." to update what will be committed) 8 # (use "git checkout -- <file>..." to discard changes in working directory) 9 # 10 # modified: README.md 11 # 12 no changes added to commit (use "git add" and/or "git commit -a")
怎么第二次的修改沒有被提交?
別激動,我們回顧一下操作過程:
第一次修改 -> git add
-> 第二次修改 -> git commit
,中間缺少了一個git add
我們前面講了,Git管理的是修改,當你用git add
命令后,在工作區的第一次修改被放入暫存區,准備提交,但是,在工作區的第二次修改並沒有放入暫存區,所以,git commit
只負責把暫存區的修改提交了,也就是第一次的修改被提交了,第二次的修改不會被提交。
提交后,用git diff HEAD -- README.txt
命令可以查看工作區和版本庫里面最新版本的區別:
1 [root@mini05 zhangtest]# git diff HEAD -- README.md 2 diff --git a/README.md b/README.md 3 index 8de2e69..3b892c6 100644 4 --- a/README.md 5 +++ b/README.md 6 @@ -5,4 +5,4 @@ Git is a distributed version control system. 7 Git is free software. 8 111 9 222 10 -Git tracks changes. 11 +Git tracks changes of files.
可見,第二次修改確實沒有被提交。
那怎么提交第二次修改呢?你可以繼續git add
再git commit
,也可以別着急提交第一次修改,先git add
第二次修改,再git commit
,就相當於把兩次修改合並后一塊提交了:
第一次修改 -> git add
-> 第二次修改 -> git add
-> git commit
2. 撤銷修改
2.1. 場景1
當你改亂了工作區某個文件的內容,想直接丟棄工作區的修改時,用命令git checkout -- file
。
添加了如下信息:
1 [root@mini05 zhangtest]# cat README.md 2 # zhangtest 3 zhangtest 4 張三 5 Git is a distributed version control system. 6 Git is free software. 7 111 8 222 9 Git tracks changes of files. 10 aabbccdd # 添加的信息
查看狀態信息
1 [root@mini05 zhangtest]# git status 2 # On branch master 3 # Your branch is ahead of 'origin/master' by 4 commits. 4 # (use "git push" to publish your local commits) 5 # 6 # Changes not staged for commit: 7 # (use "git add <file>..." to update what will be committed) 8 # (use "git checkout -- <file>..." to discard changes in working directory) 9 # 10 # modified: README.md 11 # 12 no changes added to commit (use "git add" and/or "git commit -a")
丟棄工作區的修改並再次查看信息
1 [root@mini05 zhangtest]# git checkout -- README.md # 丟棄工作區的修改 2 [root@mini05 zhangtest]# cat README.md 3 # zhangtest 4 zhangtest 5 張三 6 Git is a distributed version control system. 7 Git is free software. 8 111 9 222 10 Git tracks changes. 11 [root@mini05 zhangtest]# git status 12 # On branch master 13 # Your branch is ahead of 'origin/master' by 4 commits. 14 # (use "git push" to publish your local commits) 15 # 16 nothing to commit, working directory clean
說明:這里有兩種情況
一種是README.txt
自修改后還沒有被放到暫存區,現在,撤銷修改就回到和版本庫一模一樣的狀態;
一種是README.txt
已經添加到暫存區后,又作了修改,現在,撤銷修改就回到添加到暫存區后的狀態。
總之,就是讓這個文件回到最近一次git commit
或git add
時的狀態。
git checkout -- file
命令中的--
很重要,沒有--
,就變成了“切換到另一個分支”的命令。
2.2. 場景2
你不但寫了一些廢話,還git add
到暫存區了。
用命令git reset HEAD <file>
可以把暫存區的修改撤銷掉(unstage),重新放回工作區:
git reset
命令既可以回退版本,也可以把暫存區的修改回退到工作區。當我們用HEAD
時,表示最新的版本。
增加信息並添加到暫存區
1 [root@mini05 zhangtest]# cat README.md 2 # zhangtest 3 zhangtest 4 張三 5 Git is a distributed version control system. 6 Git is free software. 7 111 8 222 9 Git tracks changes. 10 aabbccdd # 添加的信息 11 [root@mini05 zhangtest]# git add README.md # 添加到暫存區
查看狀態信息
1 [root@mini05 zhangtest]# git status 2 # On branch master 3 # Your branch is ahead of 'origin/master' by 4 commits. 4 # (use "git push" to publish your local commits) 5 # 6 # Changes to be committed: 7 # (use "git reset HEAD <file>..." to unstage) 8 # 9 # modified: README.md 10 #
回到最新版本
1 [root@mini05 zhangtest]# git reset HEAD README.md 2 Unstaged changes after reset: 3 M README.md
再次查看狀態信息
再用git status
查看一下,現在暫存區是干凈的,工作區有修改:
1 [root@mini05 zhangtest]# git status 2 # On branch master 3 # Your branch is ahead of 'origin/master' by 4 commits. 4 # (use "git push" to publish your local commits) 5 # 6 # Changes not staged for commit: 7 # (use "git add <file>..." to update what will be committed) 8 # (use "git checkout -- <file>..." to discard changes in working directory) 9 # 10 # modified: README.md 11 # 12 no changes added to commit (use "git add" and/or "git commit -a")
丟棄工作區的修改
1 [root@mini05 zhangtest]# git checkout -- README.md 2 [root@mini05 zhangtest]# git status 3 # On branch master 4 # Your branch is ahead of 'origin/master' by 4 commits. 5 # (use "git push" to publish your local commits) 6 # 7 nothing to commit, working directory clean 8 [root@mini05 zhangtest]# cat README.md 9 # zhangtest 10 zhangtest 11 張三 12 Git is a distributed version control system. 13 Git is free software. 14 111 15 222 16 Git tracks changes.
說明:
現在,假設你不但改錯了東西,還從暫存區提交到了版本庫,怎么辦呢?還記得版本回退一節嗎?可以回退到上一個版本。不過,這是有條件的,就是你還沒有把自己的本地版本庫推送到遠程。一旦你提交推送到遠程版本庫,你就真的慘了……
2.3. 小結
場景1:當你改亂了工作區某個文件的內容,想直接丟棄工作區的修改時,用命令git checkout -- file
。
場景2:當你不但改亂了工作區某個文件的內容,還添加到了暫存區時,想丟棄修改,分兩步,第一步用命令git reset HEAD <file>
,就回到了場景1,第二步按場景1操作。
場景3:已經提交了不合適的修改到版本庫時,想要撤銷本次提交,參考版本回退一節,不過前提是沒有推送到遠程庫。
3. 刪除文件
3.1. 刪除文件
添加文件並提交
1 [root@mini05 zhangtest]# echo "111" > aaa.txt 2 [root@mini05 zhangtest]# git add aaa.txt 3 [root@mini05 zhangtest]# git commit -m "add aaa.txt" 4 [master 6d0226b] add aaa.txt 5 1 file changed, 1 insertion(+) 6 create mode 100644 aaa.txt
本地刪除文件並查看狀態
1 [root@mini05 zhangtest]# rm -f aaa.txt # 本地刪除 2 [root@mini05 zhangtest]# git status 3 # On branch master 4 # Your branch is ahead of 'origin/master' by 5 commits. 5 # (use "git push" to publish your local commits) 6 # 7 # Changes not staged for commit: 8 # (use "git add/rm <file>..." to update what will be committed) 9 # (use "git checkout -- <file>..." to discard changes in working directory) 10 # 11 # deleted: aaa.txt 12 # 13 no changes added to commit (use "git add" and/or "git commit -a")
git 刪除文件並查看狀態
1 [root@mini05 zhangtest]# git rm aaa.txt 2 rm 'aaa.txt' 3 [root@mini05 zhangtest]# git commit -m "del aaa.txt" 4 [master c795cfc] del aaa.txt 5 1 file changed, 1 deletion(-) 6 delete mode 100644 aaa.txt 7 [root@mini05 zhangtest]# git status 8 # On branch master 9 # Your branch is ahead of 'origin/master' by 6 commits. 10 # (use "git push" to publish your local commits) 11 # 12 nothing to commit, working directory clean
現在,文件就從版本庫中被刪除了。
3.2. 誤刪恢復
如果誤刪除本地文件了,但是沒有刪除版本庫中的,因為版本庫里還有呢,所以可以很輕松地把誤刪的文件恢復到最新版本.
1 [root@mini05 zhangtest]# git checkout -- aaa.txt
git checkout
其實是用版本庫里的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”。
3.3. 小結
命令git rm
用於刪除一個文件。如果一個文件已經被提交到版本庫,那么你永遠不用擔心誤刪,但是要小心,你只能恢復文件到最新版本,你會丟失最近一次提交后你修改的內容。