初始化一個Git倉庫,使用git init命令开财。
添加?文件到Git倉庫汉柒,分兩步:
? 第一步,使用命令git add 责鳍,注意碾褂,可反復多次使用,添加多個文件历葛;
? 第二步正塌,使用命令git commit,完成恤溶。
git status命令可以讓我們時刻掌握倉庫當前的狀態(tài)乓诽,上?面的命令告訴我們,readme.txt被
修改過了咒程,但還沒有準備提交的修改鸠天。
的。比如你休假兩周從國外回來帐姻,第?一天上班時稠集,已經(jīng)記不清上次怎么修改的
readme.txt,所以卖宠,需要用git diff這個命令看看:
?git diff readme.txt
當然了巍杈,在實際?工作中,我們腦子里怎么可能記得?一個?幾千?行的文件每次都改了什么內(nèi)容扛伍,
不然要版本控制系統(tǒng)干什么筷畦。版本控制系統(tǒng)肯定有某個命令可以告訴我們歷史記錄,在Git
中,我們用git log命令查看:
如果嫌輸出信息太多鳖宾,看得眼花繚亂的吼砂,可以試試加上
--pretty=oneline參數(shù):
git log --pretty=oneline
首先,Git必須知道當前版本是哪個版本鼎文,在Git中渔肩,用HEAD表?示當前版本,也就是最新的
提交“ 3628164...882e1e0”(注意我的提交ID和你的肯定不一樣)拇惋,上一個版本就是
HEAD^周偎,上上一個版本就是HEAD^^,當然往上100 個版本寫100個^比較容易數(shù)不過來撑帖,
所以寫成HEAD~100蓉坎。
現(xiàn)在,我們要把當前版本“append GPL”回退到上?一個版本“add distributed”胡嘿,就可
以使?用git reset命令:
git reset --hard HEAD^
Git提供了一個命令git reflog?用來記錄你的每一次命令:
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)在衷敌,你?又可以乘
坐時光機回到未來了勿侯。
現(xiàn)在總結(jié)?一下:
? HEAD指向的版本就是當前版本,因此缴罗,Git允許我們在版本的歷史之間穿梭助琐,使用命
令? git reset --hard commit_id。
? 穿梭前瞒爬,?用git log可以查看提交歷史弓柱,以便確定要回退到哪個版本。
? 要重返未來侧但,?用git reflog查看命令歷史矢空,以便確定要回到未來的哪個版本。
git checkout -- readme.txt
命令git checkout -- readme.txt意思就是禀横,把readme.txt?文件在?工作區(qū)的修改全部撤銷屁药,這
?里有兩種情況:
一種是readme.txt自修改后還沒有被放到暫存區(qū),現(xiàn)在柏锄,撤銷修改就回到和版本庫一模一
樣的狀態(tài)酿箭;
一種是readme.txt已經(jīng)添加到暫存區(qū)后,又作了修改趾娃,現(xiàn)在缭嫡,撤銷修改就回到添加到暫存
區(qū)后的狀態(tài)。
總之抬闷,就是讓這個文件回到最近一次git commit或git add時的狀態(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)容果然復原了。
git checkout -- file命令中的“--”很重要评架,沒有“--”眷茁,就變成了“創(chuàng)建?一個新分?支”的命
令,我們在后?面的分?支管理中會再次遇到git checkout命令纵诞。
Git同樣告訴我們上祈,.用命令git reset HEAD file可以把暫存區(qū)的修改撤銷掉(unstage),重
新放回.工作區(qū):
git reset HEAD readme.txt
git reset命令既可以回退版本浙芙,也可以把暫存區(qū)的修改回退到.工作區(qū)登刺。當我們.用HEAD時,
表.示最新的版本茁裙。
還記得如何丟棄.工作區(qū)的修改嗎塘砸?
git checkout -- readme.txt
git status
# On branch master
nothing to commit (working directory clean)
整個世界終于清靜了!
現(xiàn)在晤锥,假設(shè)你不但改錯了東.西,還從暫存區(qū)提交到了版本庫廊宪,怎么辦呢矾瘾?還記得版本回退.一
節(jié)嗎?可以回退到上.一個版本箭启。不過壕翩,這是有條件的,就是你還沒有把.自.己的本地版本庫推
送到遠程傅寡。還記得Git是分布式版本控制系統(tǒng)嗎放妈?我們后.面會講到遠程版本庫,.一旦你
把“stupid boss”提交推送到遠程版本庫荐操,你就真的慘了……
############### 重點
總結(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 , 你沒得救了.
場景1:當你改亂了.工作區(qū)某個.文件的內(nèi)容,想直接丟棄.工作區(qū)的修改時托启,.用命令git
checkout -- file宅倒。? (git add 之前 )
場景2:當你不但改亂了.工作區(qū)某個.文件的內(nèi)容,還添加到了暫存區(qū)時屯耸,想丟棄修改拐迁,分兩
步,第.一步.用命令git reset HEAD file疗绣,就回到了場景1线召,第.二步按場景1操作。(git add之后)
場景3:已經(jīng)提交了不合適的修改到版本庫時多矮,想要撤銷本次提交缓淹,參考版本回退.一節(jié),不
過前提是沒有推送到遠程庫。(git commit 之后)
############### 重點
一是確實要從版本庫中刪除該?文件割卖,那就用命令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)在,?文件就從版本庫中被刪除了鹏溯。
另一種情況是刪錯了罢维,因為版本庫?里還有呢,所以可以很輕松地把誤刪的?文件恢復到最新版
本:
git checkout -- test.txt
git checkout其實是?用版本庫?里的版本替換?工作區(qū)的版本丙挽,?無論?工作區(qū)是修改還是刪除肺孵,都
可以“一鍵還原”。
要關(guān)聯(lián).一個遠程庫颜阐,使.用命令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)的最.大好處之.一是在本地.工作完全不需要考慮遠程庫的存在,也就是有沒有
聯(lián)..網(wǎng)都可以正常.工作李剖,.而SVN在沒有聯(lián)..網(wǎng)的時候是拒絕干活的芒率!當有..網(wǎng)絡(luò)的時候,再把本地
提交推送.一下就完成了同步篙顺,真是太.方便了偶芍!
分支:
首先,我們創(chuàng)建dev分?支德玫,然后切換到dev分?支:
git checkout -b dev
Switched to a new branch 'dev'
git checkout命令加上-b參數(shù)表?示創(chuàng)建并切換匪蟀,相當于以下兩條命令:
git branch dev
git checkout dev
Switched to branch 'dev'
然后,?用git branch命令查看當前分?支:
git branch
* dev
master
git branch命令會列出所有分?支化焕,當前分?支前?面會標?一個*號萄窜。
現(xiàn)在,我們把dev分?支的?工作成果合并到master分?支上:
$ git merge dev
Updating d17efd8..fec145a
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
git merge命令?用于合并指定分?支到當前分?支撒桨。合并后查刻,再查看readme.txt的內(nèi)容,就可以
看到凤类,和dev分支的最新提交是完全一樣的穗泵。
注意到上面的Fast-forward信息,Git告訴我們谜疤,這次合并是“快進模式”佃延,也就是直接把
master指向dev的當前提交现诀,所以合并速度非常快履肃。
當然仔沿,也不是每次合并都能Fast-forward,我們后?面會將其他?方式的合并尺棋。
合并完成后封锉,就可以放?心地刪除dev分支了:
$ git branch -d dev
Deleted branch dev (was fec145a).
刪除后,查看branch膘螟,就只剩下master分?支了:
$ git branch
* master
因為創(chuàng)建成福、合并和刪除分?支?非常快荆残,所以Git?鼓勵你使用分支完成某個任務(wù)奴艾,合并后再刪掉
分支,這和直接在master分?支上工作效果是一樣的内斯,但過程更安全蕴潦。
Git鼓勵?大量使用分支:
查看分支:git branch
創(chuàng)建分支:git branch name
切換分支:git checkout name
創(chuàng)建+切換分支:git checkout -b name
合并某分支到當前分支: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'
準備合并dev分.支俘闯,請注意--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(+)
因為本次合并要創(chuàng)建.一個新的commit,所以加上-m參數(shù)备徐,把commit描述寫進去。
合并后甚颂,我們.用git log看看分.支歷史:
$ git log --graph --pretty=oneline --abbrev-commit
開發(fā).一個新feature蜜猾,最好新建.一個分支;
如果要丟棄.一個沒有被合并過的分支振诬,可以通過git branch -D name強.行刪除蹭睡。
信可以用git branch命令看看:
$ git branch
* master
現(xiàn)在,你的?小伙伴要在dev分支上開發(fā)赶么,就必須創(chuàng)建遠程origin的dev分支到本地肩豁,于是他
?用這個命令創(chuàng)建本地dev分支:
$ git checkout -b dev origin/dev
現(xiàn)在,他就可以在dev上繼續(xù)修改辫呻,然后清钥,時不時地把dev分支push到遠程:
git pull也失敗了,原因是沒有指定本地dev分支與遠程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成功,但是合并有沖突怖侦,需要?手動解決篡悟,解決的方法和分支管理中的解決沖突完
全?一樣谜叹。解決后,提交搬葬,再push.
多人協(xié)作的?工作模式通常是這樣:
1. ?首先荷腊,可以試圖用git push origin branch-name推送自己的修改;
2. 如果推送失敗急凰,則因為遠程分?支?比你的本地更新女仰,需要先用git pull試圖合并;
3. 如果合并有沖突香府,則解決沖突董栽,并在本地提交;
4. 沒有沖突或者解決掉沖突后企孩,再?用git push origin branch-name推送就能成功锭碳!
如果git pull提示“no tracking information”,則說明本地分支和遠程分支的鏈接關(guān)系沒
有創(chuàng)建勿璃,用命令git branch --set-upstream branch-name origin/branch-name擒抛。
這就是多人協(xié)作的工作模式,一旦熟悉了补疑,就非常簡單.
查看遠程庫信息歧沪,使?用git remote -v;
? 本地新建的分支如果不推送到遠程莲组,對其他?人就是不可見的诊胞;
? 從本地推送分支,使?用git push origin branch-name锹杈,如果推送失敗撵孤,先?用git pull抓
取遠程的新提交;
? 在本地創(chuàng)建和遠程分支對應的分?支竭望,使用git checkout -b branch-name origin/branchname邪码,
本地和遠程分支的名稱最好一致;
? 建?立本地分支和遠程分支的關(guān)聯(lián)咬清,使?用git branch --set-upstream branch-name
origin/branch-name闭专;
? 從遠程抓取分支,使?用git pull旧烧,如果有沖突影钉,要先處理沖突。
創(chuàng)建標簽:
命令git tag name?用于新建?一個標簽粪滤,默認為HEAD斧拍,也可以指定?一個commit id;
-a tagname -m "blablabla..."可以指定標簽信息杖小;
命令git tag可以查看所有標簽肆汹;
命令git push origin tagname可以推送?一個本地標簽愚墓;
? 命令git push origin --tags可以推送全部未推送過的本地標簽;
? 命令git tag -d tagname可以刪除?一個本地標簽昂勉;
? 命令git push origin :refs/tags/tagname可以刪除?一個遠程標簽浪册。
...