主要來源:?廖雪峰git
說明: 只整理了本人所需要用的一些內(nèi)容
Git是什么庐杨?
Git是目前世界上最先進(jìn)的分布式版本控制系統(tǒng)(沒有之一)罪治。
SVN是集中式的版本控制系統(tǒng)
在Windows上安裝Git
實(shí)話實(shí)說,Windows是最爛的開發(fā)平臺,如果不是開發(fā)Windows游戲或者在IE里調(diào)試頁面,一般不推薦用Windows。不過舒萎,既然已經(jīng)上了微軟的賊船,也是有辦法安裝Git的蹭沛。Windows下要使用很多Linux/Unix的工具時臂寝,需要Cygwin這樣的模擬環(huán)境章鲤,Git也一樣。Cygwin的安裝和配置都比較復(fù)雜咆贬,就不建議你折騰了败徊。不過,有高人已經(jīng)把模擬環(huán)境和Git都打包好了素征,名叫msysgit集嵌,只需要下載一個單獨(dú)的exe安裝程序,其他什么也不用裝御毅,絕對好用根欧。
msysgit是Windows版的Git,從https://git-for-windows.github.io下載(網(wǎng)速慢的同學(xué)請移步國內(nèi)鏡像)端蛆,然后按默認(rèn)選項(xiàng)安裝即可凤粗。
安裝完成后,在開始菜單里找到“Git”->“Git Bash”今豆,蹦出一個類似命令行窗口的東西嫌拣,就說明Git安裝成功!
安裝完成后呆躲,還需要最后一步設(shè)置异逐,在命令行輸入:
$git config --global user.name"Your Name"
$git config --global user.email"email@example.com"
因?yàn)镚it是分布式版本控制系統(tǒng),所以插掂,每個機(jī)器都必須自報(bào)家門:你的名字和Email地址灰瞻。你也許會擔(dān)心,如果有人故意冒充別人怎么辦辅甥?這個不必?fù)?dān)心酝润,首先我們相信大家都是善良無知的群眾,其次璃弄,真的有冒充的也是有辦法可查的要销。
注意git config命令的--global參數(shù),用了這個參數(shù)夏块,表示你這臺機(jī)器上所有的Git倉庫都會使用這個配置疏咐,當(dāng)然也可以對某個倉庫指定不同的用戶名和Email地址。
創(chuàng)建版本庫
什么是版本庫呢脐供?版本庫又名倉庫凳鬓,英文名repository,你可以簡單理解成一個目錄患民,這個目錄里面的所有文件都可以被Git管理起來,每個文件的修改垦梆、刪除匹颤,Git都能跟蹤仅孩,以便任何時刻都可以追蹤歷史,或者在將來某個時刻可以“還原”印蓖。
所以辽慕,創(chuàng)建一個版本庫非常簡單,首先赦肃,選擇一個合適的地方溅蛉,創(chuàng)建一個空目錄(可以鼠標(biāo)右鍵創(chuàng)建):
$mkdir learngit
$cd learngit
$pwd/Users/michael/learngit
pwd命令用于顯示當(dāng)前目錄。
如果你使用Windows系統(tǒng)他宛,為了避免遇到各種莫名其妙的問題船侧,請確保目錄名(包括父目錄)不包含中文。
第二步厅各,通過git init命令把這個目錄變成Git可以管理的倉庫:
$ git init
InitializedemptyGitrepositoryin/Users/michael/learngit/.git/
瞬間Git就把倉庫建好了镜撩,而且告訴你是一個空的倉庫(empty Git repository),細(xì)心的讀者可以發(fā)現(xiàn)當(dāng)前目錄下多了一個.git的目錄队塘,這個目錄是Git來跟蹤管理版本庫的袁梗,沒事千萬不要手動修改這個目錄里面的文件,不然改亂了憔古,就把Git倉庫給破壞了遮怜。
如果你沒有看到.git目錄,那是因?yàn)檫@個目錄默認(rèn)是隱藏的鸿市,用ls -ah命令就可以看見锯梁。
把文件添加到版本庫
第一步,用命令git add告訴Git灸芳,把文件添加到倉庫:
$ git add readme.txt
第二步涝桅,用命令git commit告訴Git,把文件提交到倉庫:
$ git commit -m "wrote a readme file"
簡單解釋一下git commit命令烙样,-m后面輸入的是本次提交的說明冯遂,可以輸入任意內(nèi)容,當(dāng)然最好是有意義的谒获,這樣你就能從歷史記錄里方便地找到改動記錄蛤肌。
時光機(jī)穿梭
$ git status命令可以讓我們時刻掌握倉庫當(dāng)前的狀態(tài)(add后commit前的狀態(tài))
$ git diff readme.txt命令可以讓我們知道修改的內(nèi)容
版本回退
$ git log命令可以告訴我們歷史記錄
好了,現(xiàn)在我們啟動時光穿梭機(jī)批狱,準(zhǔn)備把readme.txt回退到上一個版本裸准,也就是“add distributed”的那個版本,怎么做呢赔硫?
首先炒俱,Git必須知道當(dāng)前版本是哪個版本,在Git中,用HEAD表示當(dāng)前版本权悟,也就是最新的提交3628164...882e1e0(注意我的提交ID和你的肯定不一樣)砸王,上一個版本就是HEAD^,上上一個版本就是HEAD^^峦阁,當(dāng)然往上100個版本寫100個^比較容易數(shù)不過來谦铃,所以寫成HEAD~100。
現(xiàn)在榔昔,我們要把當(dāng)前版本“append GPL”回退到上一個版本“add distributed”驹闰,就可以使用git reset命令:
$ git reset --hard HEAD^
HEAD is now a tea34578 add distributed
--hard參數(shù)有啥意義?這個后面再講撒会,現(xiàn)在你先放心使用嘹朗。
最新的那個版本append GPL已經(jīng)看不到了!好比你從21世紀(jì)坐時光穿梭機(jī)來到了19世紀(jì)茧彤,想再回去已經(jīng)回不去了骡显,腫么辦?
辦法其實(shí)還是有的曾掂,只要上面的命令行窗口還沒有被關(guān)掉惫谤,你就可以順著往上找啊找啊,找到那個append GPL的commit id是3628164...珠洗,于是就可以指定回到未來的某個版本:
$ git reset --hard362816
現(xiàn)在溜歪,你回退到了某個版本,關(guān)掉了電腦许蓖,第二天早上就后悔了蝴猪,想恢復(fù)到新版本怎么辦?找不到新版本的commit id怎么辦膊爪?
在Git中自阱,總是有后悔藥可以吃的。當(dāng)你用$ git reset --hard HEAD^回退到add distributed版本時米酬,再想恢復(fù)到append GPL沛豌,就必須找到append GPL的commit id。Git提供了一個命令git reflog用來記錄你的每一次命令:
$ git reflog
工作區(qū)和暫存區(qū)
Git和其他版本控制系統(tǒng)如SVN的一個不同之處就是有暫存區(qū)的概念赃额。
前面講了我們把文件往Git版本庫里添加的時候加派,是分兩步執(zhí)行的:
第一步是用git add把文件添加進(jìn)去,實(shí)際上就是把文件修改添加到暫存區(qū)跳芳;
第二步是用git commit提交更改芍锦,實(shí)際上就是把暫存區(qū)的所有內(nèi)容提交到當(dāng)前分支。
撤銷修改
git checkout 其實(shí)是用版本庫里的版本替換工作區(qū)的版本飞盆,無論工作區(qū)是修改還是刪除娄琉,都可以“一鍵還原”
git checkout -- file命令中的--很重要次乓,沒有--,就變成了“切換到另一個分支”的命令
遠(yuǎn)程倉庫
第1步:創(chuàng)建SSH Key车胡。在用戶主目錄下檬输,看看有沒有.ssh目錄,如果有匈棘,再看看這個目錄下有沒有id_rsa和id_rsa.pub這兩個文件,如果已經(jīng)有了析命,可直接跳到下一步主卫。如果沒有,打開Shell(Windows下打開Git Bash)鹃愤,創(chuàng)建SSH Key:
$ ssh-keygen -t rsa -C"youremail@example.com"
如果一切順利的話簇搅,可以在用戶主目錄里找到.ssh目錄,里面有id_rsa和id_rsa.pub兩個文件软吐,這兩個就是SSH Key的秘鑰對瘩将,id_rsa是私鑰,不能泄露出去凹耙,id_rsa.pub是公鑰姿现,可以放心地告訴任何人。
第2步:登陸GitHub肖抱,打開“Account settings”备典,“SSH Keys”頁面:
然后,點(diǎn)“Add SSH Key”意述,填上任意Title提佣,在Key文本框里粘貼id_rsa.pub文件的內(nèi)容:
添加遠(yuǎn)程庫
$ git remote add origin git@github.com:michaelliao/learngit.git
$ git push -u origin master
從遠(yuǎn)程庫克隆
$ git clone git@github.com:michaelliao/gitskills.git
你也許還注意到,GitHub給出的地址不止一個荤崇,還可以用https://github.com/michaelliao/gitskills.git這樣的地址拌屏。實(shí)際上,Git支持多種協(xié)議术荤,默認(rèn)的git://使用ssh倚喂,但也可以使用https等其他協(xié)議。
使用https除了速度慢以外喜每,還有個最大的麻煩是每次推送都必須輸入口令务唐,但是在某些只開放http端口的公司內(nèi)部就無法使用ssh協(xié)議而只能用https
分支管理
1.創(chuàng)建與合并分支
首先,我們創(chuàng)建dev分支带兜,然后切換到dev分支
$ git checkout -b dev
Switched to a new branch'dev'
然后枫笛,用git branch命令查看當(dāng)前分支:
$ git branch
修改文件然后提交:
$ git add readme.txt
$ git commit -m"branch test"
現(xiàn)在,dev分支的工作完成刚照,我們就可以切換回master分支:
$ git checkout master
切換回master分支后刑巧,再查看一個readme.txt文件,剛才添加的內(nèi)容不見了!因?yàn)槟莻€提交是在dev分支上啊楚,而master分支此刻的提交點(diǎn)并沒有變
現(xiàn)在吠冤,我們把dev分支的工作成果合并到master分支上:
$ git merge dev
git merge命令用于合并指定分支到當(dāng)前分支。
合并完成后恭理,就可以放心地刪除dev分支了:
$ git branch -d dev
刪除后拯辙,查看branch,就只剩下master分支了:
$ git branch
解決沖突
準(zhǔn)備新的feature1分支颜价,繼續(xù)我們的新分支開發(fā):
$ git checkout -b feature1
修改最后一行后提交
切換到master分支:
$ git checkout master
修改最后一行并提交
$ git merge feature1? 進(jìn)行合并 發(fā)生沖突
$ git status 可以告訴我們沖突的文件
手動修改后提交
$ git add readme.txt
$ git commit -m"conflict fixed"
用帶參數(shù)的git log也可以看到分支的合并情況:
$ git log --graph --pretty=oneline --abbrev-commit
最后涯保,刪除feature1分支:
$ git branch -d feature1
通常,合并分支時周伦,如果可能夕春,Git會用Fast forward模式,但這種模式下专挪,刪除分支后及志,會丟掉分支信息。
如果要強(qiáng)制禁用Fast forward模式寨腔,Git就會在merge時生成一個新的commit速侈,這樣,從分支歷史上就可以看出分支信息脆侮。
合并分支時锌畸,加上--no-ff參數(shù)就可以用普通模式合并,合并后的歷史有分支靖避,能看出來曾經(jīng)做過合并潭枣,而fast forward合并就看不出來曾經(jīng)做過合并。
$ git merge --no-ff -m"merge with no-ff"dev
Bug分支
當(dāng)你接到一個修復(fù)一個代號101的bug的任務(wù)時幻捏,很自然地盆犁,你想創(chuàng)建一個分支issue-101來修復(fù)它,但是篡九,等等谐岁,當(dāng)前正在dev上進(jìn)行的工作還沒有提交,
并不是你不想提交榛臼,而是工作只進(jìn)行到一半伊佃,還沒法提交,預(yù)計(jì)完成還需1天時間沛善。但是航揉,必須在兩個小時內(nèi)修復(fù)該bug,怎么辦金刁?
幸好帅涂,Git還提供了一個stash功能议薪,可以把當(dāng)前工作現(xiàn)場“儲藏”起來,等以后恢復(fù)現(xiàn)場后繼續(xù)工作:
$ git stash
首先確定要在哪個分支上修復(fù)bug媳友,假定需要在master分支上修復(fù)斯议,就從master創(chuàng)建臨時分支:
$ git checkout master
現(xiàn)在修復(fù)bug,需要把“Git is free software ...”改為“Git is a free software ...”醇锚,然后提交:
$ git add readme.txt
$ git commit -m"fix bug 101"
修復(fù)完成后哼御,切換到master分支,并完成合并焊唬,最后刪除issue-101分支:
$ git checkout master
$ git merge --no-ff -m"merged bug fix 101"issue-101
$ git branch -d issue-101
現(xiàn)在艇搀,是時候接著回到dev分支干活了!
$ git checkout dev
查看工作區(qū)狀態(tài)求晶,發(fā)現(xiàn)工作區(qū)很干凈
$ git status
用stash list查看剛才的工作現(xiàn)場
$ git stash list
工作現(xiàn)場還在,Git把stash內(nèi)容存在某個地方了衷笋,但是需要恢復(fù)一下芳杏,有兩個辦法:
一是用git stash apply恢復(fù),但是恢復(fù)后辟宗,stash內(nèi)容并不刪除爵赵,你需要用git stash drop來刪除;
另一種方式是用git stash pop泊脐,恢復(fù)的同時把stash內(nèi)容也刪了(常用)
$ git stash pop
你可以多次stash空幻,恢復(fù)的時候,先用git stash list查看容客,然后恢復(fù)指定的stash秕铛,用命令:
$ git stash apply stash@{0}
Feature分支
開發(fā)一個新feature,最好新建一個分支缩挑;
如果要丟棄一個沒有被合并過的分支但两,可以通過git branch -D 強(qiáng)行刪除。
$ git branch -Dfeature-vulcan?
多人協(xié)作
當(dāng)你從遠(yuǎn)程倉庫克隆時供置,實(shí)際上Git自動把本地的master分支和遠(yuǎn)程的master分支對應(yīng)起來了谨湘,并且,遠(yuǎn)程倉庫的默認(rèn)名稱是origin芥丧。
要查看遠(yuǎn)程庫的信息紧阔,用git remote
$ git remote
或者,用git remote -v顯示更詳細(xì)的信息:
$ git remote -v
推送分支续担,就是把該分支上的所有本地提交推送到遠(yuǎn)程庫擅耽。推送時,要指定本地分支赤拒,這樣秫筏,Git就會把該分支推送到遠(yuǎn)程庫對應(yīng)的遠(yuǎn)程分支上:
$ git push origin master
如果要推送其他分支诱鞠,比如dev,就改成:
$ git push origin dev
那么这敬,哪些分支需要推送航夺,哪些不需要呢?
master分支是主分支崔涂,因此要時刻與遠(yuǎn)程同步阳掐;
dev分支是開發(fā)分支,團(tuán)隊(duì)所有成員都需要在上面工作冷蚂,所以也需要與遠(yuǎn)程同步缭保;
bug分支只用于在本地修復(fù)bug,就沒必要推到遠(yuǎn)程了蝙茶,除非老板要看看你每周到底修復(fù)了幾個bug艺骂;
feature分支是否推到遠(yuǎn)程,取決于你是否和你的小伙伴合作在上面開發(fā)隆夯。
現(xiàn)在钳恕,模擬一個你的小伙伴,可以在另一臺電腦(注意要把SSH Key添加到GitHub)或者同一臺電腦的另一個目錄下克绿阒浴:
$ git clone git@github.com:michaelliao/learngit.git
當(dāng)你的小伙伴從遠(yuǎn)程庫clone時忧额,默認(rèn)情況下,你的小伙伴只能看到本地的master分支愧口。不信可以用git branch命令看看:
$ git branch
現(xiàn)在睦番,你的小伙伴要在dev分支上開發(fā),就必須創(chuàng)建遠(yuǎn)程origin的dev分支到本地耍属,于是他用這個命令創(chuàng)建本地dev分支:
$ git checkout -b dev origin/dev
現(xiàn)在托嚣,他就可以在dev上繼續(xù)修改,然后恬涧,時不時地把dev分支push到遠(yuǎn)程:
$ git commit-m"add /usr/bin/env"
$ git push origin dev
你的小伙伴已經(jīng)向origin/dev分支推送了他的提交注益,而碰巧你也對同樣的文件作了修改,并試圖推送:
$ git add hello.py
$ git commit-m"add coding: utf-8"
推送失敗溯捆,因?yàn)槟愕男』锇榈淖钚绿峤缓湍阍噲D推送的提交有沖突丑搔,解決辦法也很簡單,Git已經(jīng)提示我們提揍,先用git pull把最新的提交從origin/dev抓下來啤月,然后,在本地合并劳跃,解決沖突谎仲,再推送:
$ git pull
git pull也失敗了,原因是沒有指定本地dev分支與遠(yuǎn)程origin/dev分支的鏈接刨仑,根據(jù)提示郑诺,設(shè)置dev和origin/dev的鏈接:
$ git branch--set-upstream dev origin/dev
再pull:
$ git pull
這回git pull成功夹姥,但是合并有沖突,需要手動解決辙诞,解決的方法和分支管理中的解決沖突完全一樣辙售。解決后,提交飞涂,再push:
$ git commit-m"merge & fix hello.py"
$ git push origin dev
因此旦部,多人協(xié)作的工作模式通常是這樣:
首先,可以試圖用git push origin branch-name推送自己的修改较店;
如果推送失敗士八,則因?yàn)檫h(yuǎn)程分支比你的本地更新,需要先用git pull試圖合并梁呈;
如果合并有沖突婚度,則解決沖突,并在本地提交官卡;
沒有沖突或者解決掉沖突后陕见,再用git push origin branch-name推送就能成功!
如果git pull提示“no tracking information”味抖,則說明本地分支和遠(yuǎn)程分支的鏈接關(guān)系沒有創(chuàng)建,用命令git branch --set-upstream branch-name origin/branch-name灰粮。
這就是多人協(xié)作的工作模式仔涩,一旦熟悉了,就非常簡單粘舟。
小結(jié)
查看遠(yuǎn)程庫信息熔脂,使用git remote -v;
本地新建的分支如果不推送到遠(yuǎn)程柑肴,對其他人就是不可見的霞揉;
從本地推送分支,使用git push origin branch-name晰骑,如果推送失敗适秩,先用git pull抓取遠(yuǎn)程的新提交;
在本地創(chuàng)建和遠(yuǎn)程分支對應(yīng)的分支硕舆,使用git checkout -b branch-name origin/branch-name秽荞,本地和遠(yuǎn)程分支的名稱最好一致;
建立本地分支和遠(yuǎn)程分支的關(guān)聯(lián)抚官,使用git branch --set-upstream branch-name origin/branch-name扬跋;
從遠(yuǎn)程抓取分支,使用git pull凌节,如果有沖突钦听,要先處理沖突洒试。
自定義Git
比如,讓Git顯示顏色朴上,會讓命令輸出看起來更醒目:
$ git config --global color.uitrue
配置別名
我們只需要敲一行命令垒棋,告訴Git,以后st就表示status:
$ git config --globalalias.st status