一、git簡(jiǎn)介
git
是目前世界上被最廣泛使用的現(xiàn)代軟件版本管理系統(tǒng)思灰。git
本身亦是一個(gè)成熟并處于活躍開(kāi)發(fā)狀態(tài)的開(kāi)源項(xiàng)目祷舀,它最初是由Linux操作系統(tǒng)內(nèi)核的創(chuàng)造者Linus Torvalds在2005年創(chuàng)造本涕。
二、在Mac OS X上安裝git
如果你正在使用Mac做開(kāi)發(fā)毕莱,有兩種安裝git
的方法器贩。
- 安裝
homebrew
,然后通過(guò)homebrew
安裝git
朋截,具體方法請(qǐng)參考homebrew
的文檔:http://brew.sh/蛹稍。 - 直接從
AppStore
安裝Xcode
巧勤,Xcode
集成了git
度迂。不過(guò)默認(rèn)沒(méi)有安裝尚骄,你需要運(yùn)行Xcode
脯颜,選擇菜單“Xcode”->“Preferences”
,在彈出窗口中找到“Downloads”
寂呛,選擇“Command Line Tools”
其馏,點(diǎn)“Install”就可以完成安裝了骗奖。
三剧蹂、創(chuàng)建本地倉(cāng)庫(kù)
倉(cāng)庫(kù):英文名repository
声功,可以簡(jiǎn)單理解成一個(gè)目錄,這個(gè)目錄里面的所有文件都可以被git
管理起來(lái)宠叼,每個(gè)文件的修改先巴、刪除,git
都能記錄冒冬,以便任何時(shí)刻都可以查找歷史記錄伸蚯,或者在回滾到以前修改的狀態(tài)。
1简烤、首先剂邮,選擇一個(gè)合適的地方,創(chuàng)建一個(gè)空目錄横侦,執(zhí)行:
git init
創(chuàng)建新的git
倉(cāng)庫(kù)挥萌,會(huì)發(fā)下在當(dāng)前的創(chuàng)建的目錄下面多了一個(gè).git
的目錄绰姻,這個(gè)目錄是git
來(lái)管理倉(cāng)庫(kù)的。
注意:
沒(méi)事千萬(wàn)不要手動(dòng)修改這個(gè)目錄里面的文件瑞眼,不然就把會(huì)git
倉(cāng)庫(kù)給破壞了龙宏。
2棵逊、添加文件到git倉(cāng)庫(kù)
把文件添加到倉(cāng)庫(kù):
git add <filename>
git add .
注意:
git add <filename>
是把某一個(gè)文件添加到git
的緩存區(qū)里面伤疙。
git add .
是把所有的文件添加到git
的緩存區(qū)里面。
3辆影、把文件提交到本地倉(cāng)庫(kù)
git commit -m "代碼提交信息"
注意:
-
git commit
命令徒像,一般會(huì)在后面加上-m
表示本次提交到本地倉(cāng)庫(kù)的記錄。 -
commit message
言簡(jiǎn)意賅蛙讥,不要寫無(wú)用信息锯蛀,這樣讓別人不能看懂這次提交的意義。 - 在開(kāi)發(fā)時(shí)次慢,良好的習(xí)慣是根據(jù)工作進(jìn)度及時(shí)
commit
旁涤,并務(wù)必注意附上有意義的commit message
。創(chuàng)建完項(xiàng)目目錄后迫像,第一次提交的commit message
一般為Initial commit.
劈愚。 - 添加一個(gè)新的
Pod
庫(kù)或pod update
后,要單獨(dú)提交一個(gè)commit
闻妓,統(tǒng)一commit message
為pod add xxx
或pod update xxx
菌羽。
四、遠(yuǎn)程倉(cāng)庫(kù)
一般使用git
的公司都會(huì)有自己的git
服務(wù)器或者使用第三方git
服務(wù)器由缆,比如coding.net
注祖、碼云等。
由于你的本地git
倉(cāng)庫(kù)和git
服務(wù)器倉(cāng)庫(kù)之間的傳輸是通過(guò)SSH
加密的均唉,需要設(shè)置:
- 創(chuàng)建
SSH Key
是晨。在用戶主目錄下,看看有沒(méi)有.ssh
目錄舔箭。如果有罩缴,再看看這個(gè)目錄下有沒(méi)有id_rsa
和id_rsa.pub
這兩個(gè)文件,如果已經(jīng)有限嫌,可直接跳到下一步靴庆。如果沒(méi)有,打開(kāi)Shell
怒医,創(chuàng)建SSH Key
:
ssh-keygen -t rsa -C "your.email@example.com" -b 4096
- 將公共SSH密鑰復(fù)制到剪貼板:
pbcopy < ~/.ssh/id_rsa.pub
- 登陸
git
服務(wù)器炉抒,打開(kāi)“Account settings”
,“SSH Keys”
頁(yè)面: - 點(diǎn)
“Add SSH Key”
稚叹,填上任意Title焰薄,在Key
文本框里粘貼id_rsa.pub
文件的內(nèi)容:
注意:
為什么git
服務(wù)器需要SSH Key
呢拿诸?因?yàn)?code>git服務(wù)器需要識(shí)別出你推送的提交確實(shí)是你推送的,而不是別人冒充的塞茅,而git
支持SSH
協(xié)議亩码,所以,git
服務(wù)器只要知道了你的公鑰野瘦,就可以確認(rèn)只有你自己才能推送描沟。
當(dāng)然,git
服務(wù)器允許你添加多個(gè)Key
鞭光。假定你有若干電腦吏廉,你一會(huì)兒在公司提交,一會(huì)兒在家里提交惰许,只要把每臺(tái)電腦的Key
都添加到git
服務(wù)器席覆,就可以在每臺(tái)電腦上往git
服務(wù)器推送了。
五汹买、添加遠(yuǎn)程倉(cāng)庫(kù)
- 登陸
git
服務(wù)器佩伤,然后,找到“Create a new repo”
按鈕晦毙,創(chuàng)建一個(gè)新的倉(cāng)庫(kù): - 在
Repository name
填入learngit
生巡,其他保持默認(rèn)設(shè)置,點(diǎn)擊“Create repository”
按鈕结序,就成功地創(chuàng)建了一個(gè)新的git
倉(cāng)庫(kù)障斋。
注意:
目前,在git
服務(wù)器上的這個(gè)learngit
倉(cāng)庫(kù)還是空的徐鹤,git
服務(wù)器告訴我們垃环,可以從這個(gè)倉(cāng)庫(kù)克隆出新的倉(cāng)庫(kù),也可以把一個(gè)已有的本地倉(cāng)庫(kù)與之關(guān)聯(lián)返敬,然后遂庄,把本地倉(cāng)庫(kù)的內(nèi)容推送到git
服務(wù)器倉(cāng)庫(kù)。
通過(guò)上圖可以看出:
1劲赠、如果在本地沒(méi)有創(chuàng)建倉(cāng)庫(kù)涛目,可以通過(guò)下面命令從git
服務(wù)器clone
出一個(gè)新的倉(cāng)庫(kù):
git clone http://michael@git.51fanxing.com:88/fxbest/ios/learngit.git
cd learngit
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
2、如果本地已經(jīng)創(chuàng)建了凛澎,可以通過(guò)下面命令把本地倉(cāng)庫(kù)與git
服務(wù)器倉(cāng)庫(kù)進(jìn)行關(guān)聯(lián):
cd existing_folder
git init
git remote add origin http://michael@git.51fanxing.com:88/fxbest/ios/learngit.git
git add .
git commit
git push -u origin master
注意:
1霹肝、git remote add origin
表示將本地服務(wù)器與git
服務(wù)器進(jìn)行關(guān)聯(lián)。
2塑煎、origin
是git
服務(wù)器的別名沫换,取什么名字都可以,你也可以在push
時(shí)將git
服務(wù)器替換為 origin最铁。但為了以后push
方便讯赏,我們第一次一般都會(huì)先remote add
垮兑。
3、git push -u origin master
將你修改或者添加的文件提交到git
服務(wù)器漱挎。
3系枪、git remote
git remote
命令允許你創(chuàng)建、查看和刪除和其它倉(cāng)庫(kù)之間的遠(yuǎn)程連接磕谅。
git remote
列出和其他倉(cāng)庫(kù)之間的遠(yuǎn)程連接私爷。
git remote -v
列出和其他倉(cāng)庫(kù)之間的遠(yuǎn)程連接,但同時(shí)顯示每個(gè)連接的URL
怜庸。
git remote add <name> <url>
創(chuàng)建一個(gè)新的遠(yuǎn)程倉(cāng)庫(kù)連接当犯。在添加之后,可以將<name>
作為<url>
便捷的別名在其他git
命令中使用割疾。
git remote rm <name>
移除名為的遠(yuǎn)程倉(cāng)庫(kù)的連接。
git remote rename <old-name> <new-name>
將遠(yuǎn)程連接從<old-name>
重命名為<new-name>
嘉栓。
六宏榕、檢查倉(cāng)庫(kù)狀態(tài)
1、git status
git status
命令顯示工作目錄和緩存區(qū)的狀態(tài)侵佃。你可以看到哪些更改被緩存了麻昼,哪些還沒(méi)有,以及哪些還未被git
記錄馋辈。
2抚芦、git log
git log
命令查看每次commit
的歷史記錄。
git log
使用默認(rèn)格式顯示完整地commit
記錄迈螟,如果輸出超過(guò)一屏叉抡,你可以用空格鍵來(lái)滾動(dòng),按q退出答毫。
git log -n <limit>
用<limit>限制提交的數(shù)量褥民,比如git log -n 3
只會(huì)顯示3個(gè)提交。
git log --oneline
將每個(gè)提交壓縮到一行洗搂,當(dāng)你需要查看項(xiàng)目歷史的上層情況時(shí)這會(huì)很有用消返。
git log --stat
除了git log
信息之外,包含哪些文件被更改了耘拇,以及每個(gè)文件相對(duì)的增刪行數(shù)撵颊。
git log -p
顯示代表每個(gè)提交的一堆信息,顯示每個(gè)提交全部的差異(diff)惫叛,這也是項(xiàng)目歷史中最詳細(xì)的視圖倡勇。
git log --author="<pattern>"
搜索特定作者的提交。<pattern>
可以是字符串或正則表達(dá)式挣棕。
git log --grep="<pattern>"
搜索提交信息匹配特定<pattern>
的提交译隘。<pattern>
可以是字符串或正則表達(dá)式亲桥。
七、git reset固耘、git checkout和git revert
git
倉(cāng)庫(kù)有三個(gè)主要組成——工作目錄题篷,緩存區(qū)和提交歷史。
git reset
厅目、git checkout
和git revert
是你的git
工具箱中最有用的一些命令番枚。它們都用來(lái)撤銷代碼倉(cāng)庫(kù)中的某些更改,而前兩個(gè)命令不僅可以作用于提交损敷,還可以作用于特定文件葫笼。
因?yàn)樗鼈兎浅O嗨疲晕覀兘?jīng)常會(huì)搞混拗馒,不知道什么場(chǎng)景下該用哪個(gè)命令路星。
1、git reset
git reset
操作會(huì)將當(dāng)前分支的HEAD
指向另外一個(gè)commit
記錄诱桂,這樣可以在當(dāng)前分支上移除部分commit
記錄洋丐。例如,在hotfix分支上回滾前兩次的commit
狀態(tài):
git reset HEAD~2
當(dāng)執(zhí)行git reset
時(shí)挥等,hotfix分支上最后兩次提交的狀態(tài)會(huì)變成空狀態(tài)友绝,等到git
執(zhí)行垃圾回收的時(shí)候,hotfix分支上最后兩次提交的狀態(tài)會(huì)被回收肝劲。
- --soft – 緩存區(qū)和工作目錄都不會(huì)被改變
- --mixed – 默認(rèn)選項(xiàng)迁客。緩存區(qū)和你指定的提交同步,但工作目錄不受影響
- --hard – 緩存區(qū)和工作目錄都同步到你指定的提交
git reset
一般配合這些參數(shù)使用辞槐,git reset --mixed HEAD
將你當(dāng)前的改動(dòng)從緩存區(qū)中移除掷漱,但是這些改動(dòng)還留在工作目錄中。如果你想完全舍棄你沒(méi)有提交的改動(dòng)催蝗,你可以使用git reset --hard HEAD
切威,這是git reset
最常用的兩種用法。
注意:
git reset
是不可逆的丙号,因?yàn)?code>git reset操作會(huì)重寫當(dāng)前分支的歷史先朦,用來(lái)撤銷緩存區(qū)和工作目錄的修改。git reset
只適用于本地修改犬缨,不能重設(shè)服務(wù)器上的commit
記錄喳魏。
2、git checkout
- 切換分支:
git checkout hotfix
注意:
使用git checkout
之前怀薛,要把工作區(qū)的內(nèi)容提交到git
服務(wù)器或者緩存區(qū)刺彩。git checkout
是將HEAD
指針從一個(gè)分支切換到另一個(gè)分支,然后更新工作目錄。因?yàn)檫@可能會(huì)覆蓋本地的修改创倔,git
會(huì)強(qiáng)制你提交或者緩存工作目錄中的所有更改嗡害,不然在checkout的時(shí)候這些更改都會(huì)丟失。
- 查看文件之前的版本
除了切換分支之外畦攘,git checkout
還可以將HEAD
指針移動(dòng)到當(dāng)前分支其他的commit
記錄霸妹。
git checkout HEAD~2
git checkout
更改的是工作目錄而不是緩存區(qū)
git checkout HEAD~2 xxx
如果你緩存并且提交了checkout
的文件,它具備將某個(gè)文件回撤到之前版本的效果知押,注意它撤銷了這個(gè)文件后面所有的更改叹螟。不影響你倉(cāng)庫(kù)的當(dāng)前狀態(tài)。你可以在新的快照中像其他文件一樣重新提交舊版本台盯。所以罢绽,在效果上,git checkout
的這個(gè)用法可以用來(lái)將單個(gè)文件回滾到舊版本静盅。
注意:
git checkout
是可逆的良价。
3、git revert
git revert
撤銷一個(gè)commit
記錄的同時(shí)會(huì)創(chuàng)建另一個(gè)新的commit
記錄温亲,這是一個(gè)安全的方法棚壁,而不是從項(xiàng)目歷史中移除這個(gè)提交。這避免了git
丟失項(xiàng)目歷史記錄栈虚,這一點(diǎn)對(duì)于你的版本歷史和協(xié)作的可靠性來(lái)說(shuō)是很重要的。
比如史隆,下面的命令會(huì)找出倒數(shù)第二個(gè)提交魂务,然后創(chuàng)建一個(gè)新的提交來(lái)撤銷這些更改,然后把這個(gè)提交加入項(xiàng)目中泌射。
git revert HEAD~2
git revert
應(yīng)該用在你想要在項(xiàng)目歷史中移除一整個(gè)提交的時(shí)候粘姜。比如說(shuō),你在追蹤一個(gè) bug熔酷,然后你發(fā)現(xiàn)它是由一個(gè)提交造成的孤紧,這時(shí)候撤銷就很有用。與其說(shuō)自己去修復(fù)它拒秘,然后提交一個(gè)新的快照号显,不如用git revert
,它幫你做了所有的事情躺酒。
git revert
回滾了單獨(dú)一個(gè)提交押蚤,它沒(méi)有移除后面的提交記錄,同時(shí)會(huì)創(chuàng)建另一個(gè)新的commit
記錄羹应。
git reset
回滾了單獨(dú)一個(gè)提交揽碘,并且移除后面的提交記錄,是不可逆的。
git revert
可以針對(duì)歷史記錄中任何一個(gè)提交雳刺,而git reset
只能從當(dāng)前提交向前回滾劫灶。比如,你想用git reset
重設(shè)一個(gè)舊的提交掖桦,你不得不移除那個(gè)提交后的所有提交本昏,再移除那個(gè)提交,然后重新提交后面的所有提交滞详。一般公司不提倡這么做凛俱。因此,git revert
可以用在公共分支上料饥,git reset
應(yīng)該用在私有分支上蒲犬。
4、git reset
用慎用
當(dāng)有commit
之后的提交被推送到公共分支上岸啡,你絕不應(yīng)該使用git reset
原叮。使用git reset
回滾了單獨(dú)一個(gè)提交,并且移除后面的提交記錄巡蘸。當(dāng)團(tuán)隊(duì)成員在上面繼續(xù)開(kāi)發(fā)的提交在協(xié)作時(shí)會(huì)引發(fā)嚴(yán)重的問(wèn)題奋隶。當(dāng)他們?cè)囍湍愕膫}(cāng)庫(kù)同步時(shí),他們會(huì)發(fā)現(xiàn)項(xiàng)目歷史的一部分突然消失了悦荒。
下面的序列展示了如果你嘗試重設(shè)公共提交時(shí)會(huì)發(fā)生什么唯欣。origin/master
是你本地master
分支對(duì)應(yīng)的中央倉(cāng)庫(kù)中的分支。
一旦你在重設(shè)之后又增加了新的提交搬味,git
會(huì)認(rèn)為你的本地歷史已經(jīng)和 origin/master
分叉了境氢,同步你的倉(cāng)庫(kù)時(shí)的合并提交(merge commit)會(huì)使你的同事困惑。
5碰纬、git clean
git clean
命令將未記錄的文件從你的工作目錄中移除萍聊。它只是提供了一條捷徑,因?yàn)橛?code>git status查看未記錄的文件悦析,然后手動(dòng)移除它們也很方便寿桨。和一般的rm
命令一樣,git clean
是無(wú)法撤消的强戴,所以在刪除未記錄的文件之前想清楚亭螟,你是否真的要這么做。
git clean
命令經(jīng)常和git reset --hard
一起使用酌泰。記住媒佣,git reset
只影響被記錄的文件,所以還需要一個(gè)單獨(dú)的命令來(lái)清理未被記錄的文件陵刹。這個(gè)兩個(gè)命令相結(jié)合默伍,你就可以將工作目錄回到之前特定提交時(shí)的狀態(tài)欢嘿。
注意:
git clean
也是不可逆的。
八也糊、分支
1炼蹦、git branch
分支代表了一條獨(dú)立的開(kāi)發(fā)流水線,git branch
命令允許你創(chuàng)建狸剃、列出掐隐、重命名和刪除分支。一般git branch
和git checkout
钞馁、git merge
這兩個(gè)命令通常緊密地結(jié)合在一起使用虑省。一般使用過(guò)git
的同學(xué)都知道:
-
master
是長(zhǎng)期分支,一般用于管理對(duì)外發(fā)布版本僧凰,每個(gè)commit
對(duì)一個(gè)tag
探颈,也就是一個(gè)發(fā)布版本。 -
develop
是長(zhǎng)期分支训措,一般用于作為日常開(kāi)發(fā)匯總伪节,即開(kāi)發(fā)版的代碼 -
feature
是短期分支,一般用于一個(gè)新功能的開(kāi)發(fā)绩鸣。 -
hotfix
是短期分支 怀大,一般用于正式發(fā)布以后,出現(xiàn)bug呀闻,需要?jiǎng)?chuàng)建一個(gè)分支化借,進(jìn)行bug修補(bǔ)。 -
release
是短期分支捡多,一般用于發(fā)布正式版本之前(即合并到master
分支之前)屏鳍,需要有的預(yù)發(fā)布的版本進(jìn)行測(cè)試。release
分支在經(jīng)歷測(cè)試之后局服,測(cè)試確認(rèn)驗(yàn)收,將會(huì)被合并的develop
和master
驳遵。
git branch
列出倉(cāng)庫(kù)中所有分支淫奔。
git branch <branch>
創(chuàng)建一個(gè)名為 <branch> 的分支。不會(huì)自動(dòng)切換到那個(gè)分支去堤结。
git branch -d <branch>
刪除指定分支唆迁。這是一個(gè)安全的操作,git
會(huì)阻止你刪除包含未合并更改的分支竞穷。
git branch -D <branch>
強(qiáng)制刪除指定分支唐责,即使包含未合并更改。如果你希望永遠(yuǎn)刪除某條開(kāi)發(fā)線的所有提交瘾带,你應(yīng)該用這個(gè)命令鼠哥。
git branch -m <branch>
將當(dāng)前分支命名為<branch>。
2、git merge
用于合并指定分支到當(dāng)前分支朴恳,git merge
命令允許你將git branch
創(chuàng)建的多條分支合并成一個(gè)抄罕。
注意:
合并指定分支到當(dāng)前分支,當(dāng)前分支會(huì)被更新于颖,以響應(yīng)合并操作呆贿,但目標(biāo)分支完全不受影響。也就是說(shuō)git merge
經(jīng)常和git checkout
一起使用森渐,選擇當(dāng)前分支做入,然后用git branch -d
刪除廢棄的目標(biāo)分支。
git merge <branch>
將指定分支并入當(dāng)前分支同衣。
git merge --no-ff <branch>
將指定分支并入當(dāng)前分支竟块,但 總是 生成一個(gè)合并提交(即使是快速向前合并)。這可以用來(lái)記錄倉(cāng)庫(kù)中發(fā)生的所有合并乳怎。
3彩郊、git merge幾種方法
- 快速向前合并
當(dāng)當(dāng)前分支頂端到目標(biāo)分支路徑是線性之時(shí),我們可以采取快速向前合并蚪缀。git
只需要將當(dāng)前分支頂端(快速向前地)移動(dòng)到目標(biāo)分支頂端秫逝,即可整合兩個(gè)分支的歷史,而不需要“真正”合并分支询枚。它在效果上合并了歷史违帆,因?yàn)槟繕?biāo)分支上的提交現(xiàn)在在當(dāng)前分支可以訪問(wèn)到。比如金蜀,some-feature
到master
分支的快速向前合并會(huì)是這樣的:
- 三路合并
如果分支已經(jīng)分叉了刷后,那么就無(wú)法進(jìn)行快速向前合并。當(dāng)和目標(biāo)分支之間的路徑不是線性之時(shí)渊抄,git
只能執(zhí)行三路合并尝胆。三路合并使用一個(gè)專門的提交來(lái)合并兩個(gè)分支的歷史。這個(gè)術(shù)語(yǔ)取自這樣一個(gè)事實(shí)护桦,git
使用三個(gè)提交來(lái)生成合并提交:兩個(gè)分支頂端和它們共同的祖先含衔。
很多開(kāi)發(fā)者喜歡使用git rebase
快速向前合并,來(lái)合并微小的功能或者修復(fù)bug二庵,使用三路合并來(lái)整合長(zhǎng)期運(yùn)行的功能贪染。后者導(dǎo)致的合并提交作為兩個(gè)分支的連接標(biāo)志。
4催享、解決沖突
如果你嘗試合并的兩個(gè)分支同一個(gè)文件的同一個(gè)部分杭隙,git
將無(wú)法決定使用哪個(gè)版本。當(dāng)這種情況發(fā)生時(shí)因妙,它會(huì)停在合并提交痰憎,讓你手動(dòng)解決這些沖突票髓。
當(dāng)你遇到合并沖突時(shí),運(yùn)行git status
命令來(lái)查看哪些文件存在需要解決的沖突信殊。
當(dāng)你手動(dòng)修復(fù)完沖突之后炬称,只需對(duì)沖突的文件運(yùn)行git add
告訴git
沖突已解決。然后涡拘,運(yùn)行git commit
生成一個(gè)合并提交玲躯。
使用git log --graph
命令可以看到分支合并圖。
團(tuán)隊(duì)合作的分支看起來(lái)就像這樣:
注意:
提交沖突只會(huì)出現(xiàn)在三路合并中鳄乏。在快速向前合并中跷车,我們不可能出現(xiàn)沖突的更改。
九橱野、創(chuàng)建標(biāo)簽
一般在公司每一個(gè)上線版本都會(huì)打一個(gè)標(biāo)簽朽缴,為了記錄和維護(hù),當(dāng)線上版本出現(xiàn)緊急bug水援,我們就可以通過(guò)git checkout
檢出項(xiàng)目密强,然后創(chuàng)建hotfix分支進(jìn)行bug的修復(fù)。
git tag
查看所有標(biāo)簽
git tag <name>
git tag <name> commit id
用于新建一個(gè)標(biāo)簽蜗元,默認(rèn)為HEAD
或渤,也可以指定一個(gè)commit id
git show <tagname>
查看標(biāo)簽信息
git push origin <tagname>
可以推送一個(gè)本地標(biāo)簽
git push origin --tags
可以推送全部未推送過(guò)的本地標(biāo)簽
git tag -d <tagname>
可以刪除一個(gè)本地標(biāo)簽
git push origin :refs/tags/<tagname>
可以刪除一個(gè)遠(yuǎn)程標(biāo)簽
Reference:
https://www.atlassian.com/git/tutorials/merging-vs-rebasing
https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000