初始化一個(gè)Git倉(cāng)庫(kù),使用git init命令。
添加?文件到Git倉(cāng)庫(kù),分兩步:
? 第一步,使用命令git add ,注意,可反復(fù)多次使用,添加多個(gè)文件;
? 第二步,使用命令git commit,完成。
git status命令可以讓我們時(shí)刻掌握倉(cāng)庫(kù)當(dāng)前的狀態(tài),上?面的命令告訴我們,readme.txt被
修改過了,但還沒有準(zhǔn)備提交的修改。
的。比如你休假兩周從國(guó)外回來(lái),第?一天上班時(shí),已經(jīng)記不清上次怎么修改的
readme.txt,所以,需要用git diff這個(gè)命令看看:
?git diff readme.txt
當(dāng)然了,在實(shí)際?工作中,我們腦子里怎么可能記得?一個(gè)?幾千?行的文件每次都改了什么內(nèi)容,
不然要版本控制系統(tǒng)干什么。版本控制系統(tǒng)肯定有某個(gè)命令可以告訴我們歷史記錄,在Git
中,我們用git log命令查看:
如果嫌輸出信息太多,看得眼花繚亂的,可以試試加上
--pretty=oneline參數(shù):
git log --pretty=oneline
首先,Git必須知道當(dāng)前版本是哪個(gè)版本,在Git中,用HEAD表?示當(dāng)前版本,也就是最新的
提交“ 3628164...882e1e0”(注意我的提交ID和你的肯定不一樣),上一個(gè)版本就是
HEAD^,上上一個(gè)版本就是HEAD^^,當(dāng)然往上100 個(gè)版本寫100個(gè)^比較容易數(shù)不過來(lái),
所以寫成HEAD~100。
現(xiàn)在,我們要把當(dāng)前版本“append GPL”回退到上?一個(gè)版本“add distributed”,就可
以使?用git reset命令:
git reset --hard HEAD^
Git提供了一個(gè)命令git reflog?用來(lái)記錄你的每一次命令:
git reflog
ea34578 HEAD@{0}: reset: moving to HEAD^
3628164 HEAD@{1}: commit: append GPL
ea34578 HEAD@{2}: commit: add distributed
cb926e7 HEAD@{3}: commit (initial): wrote a readme file
終于舒了?口?氣,第二行顯?示“append GPL”的commit id是3628164,現(xiàn)在,你?又可以乘
坐時(shí)光機(jī)回到未來(lái)了。
現(xiàn)在總結(jié)?一下:
? HEAD指向的版本就是當(dāng)前版本,因此,Git允許我們?cè)诎姹镜臍v史之間穿梭,使用命
令? git reset --hard commit_id。
? 穿梭前,?用git log可以查看提交歷史,以便確定要回退到哪個(gè)版本。
? 要重返未來(lái),?用git reflog查看命令歷史,以便確定要回到未來(lái)的哪個(gè)版本。

git checkout -- readme.txt
命令git checkout -- readme.txt意思就是,把readme.txt?文件在?工作區(qū)的修改全部撤銷,這
?里有兩種情況:
一種是readme.txt自修改后還沒有被放到暫存區(qū),現(xiàn)在,撤銷修改就回到和版本庫(kù)一模一
樣的狀態(tài);
一種是readme.txt已經(jīng)添加到暫存區(qū)后,又作了修改,現(xiàn)在,撤銷修改就回到添加到暫存
區(qū)后的狀態(tài)。
總之,就是讓這個(gè)文件回到最近一次git commit或git add時(shí)的狀態(tài)。
現(xiàn)在,看看readme.txt的?文件內(nèi)容:
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
文件內(nèi)容果然復(fù)原了。
git checkout -- file命令中的“--”很重要,沒有“--”,就變成了“創(chuàng)建?一個(gè)新分?支”的命
令,我們?cè)诤?面的分?支管理中會(huì)再次遇到git checkout命令。
Git同樣告訴我們,.用命令git reset HEAD file可以把暫存區(qū)的修改撤銷掉(unstage),重
新放回.工作區(qū):
git reset HEAD readme.txt
git reset命令既可以回退版本,也可以把暫存區(qū)的修改回退到.工作區(qū)。當(dāng)我們.用HEAD時(shí),
表.示最新的版本。
還記得如何丟棄.工作區(qū)的修改嗎?
git checkout -- readme.txt
git status
# On branch master
nothing to commit (working directory clean)
整個(gè)世界終于清靜了!
現(xiàn)在,假設(shè)你不但改錯(cuò)了東.西,還從暫存區(qū)提交到了版本庫(kù),怎么辦呢?還記得版本回退.一
節(jié)嗎?可以回退到上.一個(gè)版本。不過,這是有條件的,就是你還沒有把.自.己的本地版本庫(kù)推
送到遠(yuǎn)程。還記得Git是分布式版本控制系統(tǒng)嗎?我們后.面會(huì)講到遠(yuǎn)程版本庫(kù),.一旦你
把“stupid boss”提交推送到遠(yuǎn)程版本庫(kù),你就真的慘了……
############### 重點(diǎn)
總結(jié): 沒有 git add 之前的修改? ?用??git checkout -- readme.txt 撤銷修改
git add 之后的修改:? 先執(zhí)行 git reset HEAD file,后 執(zhí)行?git checkout -- readme.txt?
git commit之后的修改 用? ?git reset --hard commit_id?
如果已經(jīng) git push了, ohYear , 你沒得救了.
場(chǎng)景1:當(dāng)你改亂了.工作區(qū)某個(gè).文件的內(nèi)容,想直接丟棄.工作區(qū)的修改時(shí),.用命令git
checkout -- file。? (git add 之前 )
場(chǎng)景2:當(dāng)你不但改亂了.工作區(qū)某個(gè).文件的內(nèi)容,還添加到了暫存區(qū)時(shí),想丟棄修改,分兩
步,第.一步.用命令git reset HEAD file,就回到了場(chǎng)景1,第.二步按場(chǎng)景1操作。(git add之后)
場(chǎng)景3:已經(jīng)提交了不合適的修改到版本庫(kù)時(shí),想要撤銷本次提交,參考版本回退.一節(jié),不
過前提是沒有推送到遠(yuǎn)程庫(kù)。(git commit 之后)
############### 重點(diǎn)
一是確實(shí)要從版本庫(kù)中刪除該?文件,那就用命令git rm刪掉,并且
commit:
git rm test.txt
rm 'test.txt'
git commit -m "remove test.txt"
[master d17efd8] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
現(xiàn)在,?文件就從版本庫(kù)中被刪除了。
另一種情況是刪錯(cuò)了,因?yàn)榘姹編?kù)?里還有呢,所以可以很輕松地把誤刪的?文件恢復(fù)到最新版
本:
git checkout -- test.txt
git checkout其實(shí)是?用版本庫(kù)?里的版本替換?工作區(qū)的版本,?無(wú)論?工作區(qū)是修改還是刪除,都
可以“一鍵還原”。
要關(guān)聯(lián).一個(gè)遠(yuǎn)程庫(kù),使.用命令git remote add origin git@server-name:path/repo-name.git;
關(guān)聯(lián)后,使.用命令git push -u origin master第.一次推送master分.支的所有內(nèi)容;
此后,每次本地提交后,只要有必要,就可以使.用命令git push origin master推送最新修
改;
分布式版本系統(tǒng)的最.大好處之.一是在本地.工作完全不需要考慮遠(yuǎn)程庫(kù)的存在,也就是有沒有
聯(lián)..網(wǎng)都可以正常.工作,.而SVN在沒有聯(lián)..網(wǎng)的時(shí)候是拒絕干活的!當(dāng)有..網(wǎng)絡(luò)的時(shí)候,再把本地
提交推送.一下就完成了同步,真是太.方便了!
分支:
首先,我們創(chuàng)建dev分?支,然后切換到dev分?支:
git checkout -b dev
Switched to a new branch 'dev'
git checkout命令加上-b參數(shù)表?示創(chuàng)建并切換,相當(dāng)于以下兩條命令:
git branch dev
git checkout dev
Switched to branch 'dev'
然后,?用git branch命令查看當(dāng)前分?支:
git branch
* dev
master
git branch命令會(huì)列出所有分?支,當(dāng)前分?支前?面會(huì)標(biāo)?一個(gè)*號(hào)。
現(xiàn)在,我們把dev分?支的?工作成果合并到master分?支上:
$ git merge dev
Updating d17efd8..fec145a
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
git merge命令?用于合并指定分?支到當(dāng)前分?支。合并后,再查看readme.txt的內(nèi)容,就可以
看到,和dev分支的最新提交是完全一樣的。
注意到上面的Fast-forward信息,Git告訴我們,這次合并是“快進(jìn)模式”,也就是直接把
master指向dev的當(dāng)前提交,所以合并速度非常快。
當(dāng)然,也不是每次合并都能Fast-forward,我們后?面會(huì)將其他?方式的合并。
合并完成后,就可以放?心地刪除dev分支了:
$ git branch -d dev
Deleted branch dev (was fec145a).
刪除后,查看branch,就只剩下master分?支了:
$ git branch
* master
因?yàn)閯?chuàng)建、合并和刪除分?支?非??欤訥it?鼓勵(lì)你使用分支完成某個(gè)任務(wù),合并后再刪掉
分支,這和直接在master分?支上工作效果是一樣的,但過程更安全。
Git鼓勵(lì)?大量使用分支:
查看分支:git branch
創(chuàng)建分支:git branch name
切換分支:git checkout name
創(chuàng)建+切換分支:git checkout -b name
合并某分支到當(dāng)前分支:git merge name
刪除分支:git branch -d name
.用帶參數(shù)的git log也可以看到分?支的合并情況:
$ git log --graph --pretty=oneline --abbrev-commit
現(xiàn)在,我們切換回master:
$ git checkout master
Switched to branch 'master'
準(zhǔn)備合并dev分.支,請(qǐng)注意--no-ff參數(shù),表.示禁.用“Fast forward”:
$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)
因?yàn)楸敬魏喜⒁獎(jiǎng)?chuàng)建.一個(gè)新的commit,所以加上-m參數(shù),把commit描述寫進(jìn)去。
合并后,我們.用git log看看分.支歷史:
$ git log --graph --pretty=oneline --abbrev-commit
開發(fā).一個(gè)新feature,最好新建.一個(gè)分支;
如果要丟棄.一個(gè)沒有被合并過的分支,可以通過git branch -D name強(qiáng).行刪除。
信可以用git branch命令看看:
$ git branch
* master
現(xiàn)在,你的?小伙伴要在dev分支上開發(fā),就必須創(chuàng)建遠(yuǎn)程origin的dev分支到本地,于是他
?用這個(gè)命令創(chuàng)建本地dev分支:
$ git checkout -b dev origin/dev
現(xiàn)在,他就可以在dev上繼續(xù)修改,然后,時(shí)不時(shí)地把dev分支push到遠(yuǎn)程:
git pull也失敗了,原因是沒有指定本地dev分支與遠(yuǎn)程origin/dev分支的鏈接,根據(jù)提示,
設(shè)置dev和origin/dev的鏈接:
$ git branch --set-upstream dev origin/dev
Branch dev set up to track remote branch dev from origin.
再pull:
$ git pull
Auto-merging hello.py
CONFLICT (content): Merge conflict in hello.py
Automatic merge failed; fix conflicts and then commit the result.
這回git pull成功,但是合并有沖突,需要?手動(dòng)解決,解決的方法和分支管理中的解決沖突完
全?一樣。解決后,提交,再push.
多人協(xié)作的?工作模式通常是這樣:
1. ?首先,可以試圖用git push origin branch-name推送自己的修改;
2. 如果推送失敗,則因?yàn)檫h(yuǎn)程分?支?比你的本地更新,需要先用git pull試圖合并;
3. 如果合并有沖突,則解決沖突,并在本地提交;
4. 沒有沖突或者解決掉沖突后,再?用git push origin branch-name推送就能成功!
如果git pull提示“no tracking information”,則說(shuō)明本地分支和遠(yuǎn)程分支的鏈接關(guān)系沒
有創(chuàng)建,用命令git branch --set-upstream branch-name origin/branch-name。
這就是多人協(xié)作的工作模式,一旦熟悉了,就非常簡(jiǎn)單.
查看遠(yuǎn)程庫(kù)信息,使?用git remote -v;
? 本地新建的分支如果不推送到遠(yuǎn)程,對(duì)其他?人就是不可見的;
? 從本地推送分支,使?用git push origin branch-name,如果推送失敗,先?用git pull抓
取遠(yuǎn)程的新提交;
? 在本地創(chuàng)建和遠(yuǎn)程分支對(duì)應(yīng)的分?支,使用git checkout -b branch-name origin/branchname,
本地和遠(yuǎn)程分支的名稱最好一致;
? 建?立本地分支和遠(yuǎn)程分支的關(guān)聯(lián),使?用git branch --set-upstream branch-name
origin/branch-name;
? 從遠(yuǎn)程抓取分支,使?用git pull,如果有沖突,要先處理沖突。
創(chuàng)建標(biāo)簽:
命令git tag name?用于新建?一個(gè)標(biāo)簽,默認(rèn)為HEAD,也可以指定?一個(gè)commit id;
-a tagname -m "blablabla..."可以指定標(biāo)簽信息;
命令git tag可以查看所有標(biāo)簽;
命令git push origin tagname可以推送?一個(gè)本地標(biāo)簽;
? 命令git push origin --tags可以推送全部未推送過的本地標(biāo)簽;
? 命令git tag -d tagname可以刪除?一個(gè)本地標(biāo)簽;
? 命令git push origin :refs/tags/tagname可以刪除?一個(gè)遠(yuǎn)程標(biāo)簽。
...