查看倉(cāng)庫(kù)狀態(tài)和文件更改
查看工作區(qū)狀態(tài):
git status
與最近的一次add或commit比較文件的不同:git diff <file-name>
查看該文件與commit庫(kù)中版本的變動(dòng)情況:git diff HEAD -- <file-name>
查看過(guò)修改內(nèi)容后,提交修改和提交新文件是一樣的操作:git add
,在git commit
之前隨時(shí)都可以用git status
確認(rèn)當(dāng)前倉(cāng)庫(kù)的狀態(tài)厌小。
第三條命令在add過(guò)一次修改到緩存區(qū)后用远剩。新到舊順序:工作區(qū)贫奠、緩存區(qū)(add)揍异、版本庫(kù)(commit)
版本回退
回退到某版本:
git reset --hard commit_id
向上回退n個(gè)版本:git reset --hard HEAD~{int n}
创淡。
查看commit歷史:git log
簡(jiǎn)短查看commit歷史:git log --oneline
要重回reset前的版本:git reflog
另绩,查看HEAD
變動(dòng)的歷史記錄儒陨,以確定要回到未來(lái)的版本號(hào)花嘶。
HEAD指向的commit版本就是當(dāng)前正在操作的commit版本,commit歷史記錄由上新下舊排列蹦漠。
撤銷(xiāo)修改
撤銷(xiāo)工作區(qū)修改:
git checkout -- <file-name>
撤銷(xiāo)add
到暫存區(qū)的修改:git reset HEAD <file-name>
(似乎是返回到了再上一次git add
的狀態(tài))椭员。
checkout
用于將工作區(qū)的文件撤銷(xiāo)到上一次git add
或git commit
時(shí)的狀態(tài),丟棄本地修改笛园。
刪除文件
當(dāng)已經(jīng)commit后隘击,本地工作區(qū)刪掉了某些文件時(shí),git status
會(huì)提示有哪些文件相對(duì)于上一個(gè)版本被刪除了研铆,此時(shí)有兩種選擇:
從版本庫(kù)中刪除文件:
git rm <file>
用版本庫(kù)的文件替換掉工作區(qū)的文件:git checkout -- <file>
本地沒(méi)刪錯(cuò)時(shí)埋同,git rm <file>
,并git commit
修改版本庫(kù)狀態(tài)棵红。
刪錯(cuò)文件時(shí)羡微,用git checkout -- <file>
把誤刪的文件還原到之前commit的狀態(tài)静汤,命令中一定記得加--
怖侦,否則就是切換分支的命令了墓捻。
分支操作
查看分支:
git branch
創(chuàng)建分支:git branch <name>
切換分支:git checkout <name>
創(chuàng)建+切換分支:git checkout -b <name>
合并某分支到當(dāng)前分支:git merge <name>
非Fast forward
合并:git merge --no-ff -m <description> <branch>
刪除分支:git branch -d <name>
克隆倉(cāng)庫(kù):git clone git@github.com:<username>/<repository>.git
推送到遠(yuǎn)程分支(遠(yuǎn)程分支不存在將自動(dòng)創(chuàng)建):git push origin local_branch:remote_branch
或git push origin branch-name
查看遠(yuǎn)程分支:
git remote -v
創(chuàng)建遠(yuǎn)程分支到本地:git checkout -b <new-branch-name> origin/<branch>
獲取遠(yuǎn)程分支git fetch origin <branch>
關(guān)聯(lián)本地與遠(yuǎn)程分支:git branch --set-upstream-to=origin/<branch> <branch>
刪除遠(yuǎn)程分支git push origin --delete origin/<btanch>
遠(yuǎn)程同步下來(lái)時(shí),如果提示“Cannot update paths and switch to branch <branch> at the same time.”,那就先git fetch
交煞,再重試咏窿。
安裝后配置
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
創(chuàng)建版本庫(kù)
初始化倉(cāng)庫(kù):
git init
。
添加文件:git add <file>
添加所有文件:git add .
提交版本:git commit -m <description>
使用Commitizen規(guī)范化commit
$ npm install -g commitizen
$ commitizen init cz-conventional-changelog --save --save-exact
add
的文件保存在暫存區(qū)(stage)
不加-m
參數(shù)會(huì)啟動(dòng)文本編輯器以輸入本次提交的說(shuō)明素征。按i
進(jìn)入輸入模式集嵌,輸入內(nèi)容不用帶引號(hào),輸入完按esc
退出輸入模式御毅,按shift + :
進(jìn)入命令模式根欧,輸入wq
保存并退出。
因?yàn)閃indows下的換行符是CRLF亚享,Linux和Mac是LF咽块,跨平臺(tái)開(kāi)發(fā)時(shí)會(huì)存在問(wèn)題,commit時(shí)有可能會(huì)提示:
warning: LF will be replaced by CRLF
fatal: CRLF would be replaced by LF
解決方法绘面,修改core.autocrlf的值:
git config --global core.autocrlf true #這個(gè)是轉(zhuǎn)換欺税,也是默認(rèn)值
git config --global core.autocrlf input #貌似是上庫(kù)轉(zhuǎn)換,從庫(kù)中遷出代碼不轉(zhuǎn)換
git config --global core.autocrlf false #這個(gè)一般是window上的揭璃,不轉(zhuǎn)換
鏈接github
創(chuàng)建ssh key:
ssh-keygen -t rsa -C "youremail@example.com"
添加遠(yuǎn)程庫(kù):git remote add origin git@github.com:<username>/<resposity>.git
關(guān)聯(lián)本地與遠(yuǎn)程分支:git branch --set-upstream-to=origin/<branch> <branch>
第一次遠(yuǎn)程推送:git push -u origin master -f
非第一次推送:git push origin master
同步本地倉(cāng)庫(kù):git pull --rebase origin master
遠(yuǎn)程庫(kù)克隆為本地庫(kù):git clone git@github.com:<username>/<repository>.git
push
時(shí)如果本地與遠(yuǎn)程文件結(jié)構(gòu)差異太大晚凿,git push
后加-f
,強(qiáng)制覆蓋已有分支瘦馍。
如果提示remote origin already exists
歼秽,則先git remote rm origin
在用戶(hù)主目錄下,查看是否有id_rsa
(私鑰)和id_rsa.pub
(公鑰)這兩個(gè)文件情组,如果沒(méi)有燥筷,輸入上面的命令箩祥,創(chuàng)建ssh key,一路回車(chē)肆氓,無(wú)需密碼袍祖,之后在github的ssh key設(shè)置里將.pub的文件中內(nèi)容復(fù)制粘貼過(guò)去。
pull --rebase
:如果本地庫(kù)和倉(cāng)庫(kù)的文件不同步會(huì)提示推送失敗谢揪,這時(shí)將遠(yuǎn)程倉(cāng)庫(kù)的文件與本地合并一下蕉陋。
多人協(xié)作的流程:
- 首先,可以試圖用
git push origin branch-name
推送自己的修改拨扶; - 如果推送失敗凳鬓,則因?yàn)檫h(yuǎn)程分支比你的本地更新,需要先用
git pull
試圖合并患民; - 如果合并有沖突缩举,則解決沖突,并在本地提交匹颤;
- 沒(méi)有沖突或者解決掉沖突后蚁孔,再用
git push origin branch-name
推送就能成功
Git鼓勵(lì)大量使用分支。
使用分支完成某個(gè)任務(wù)惋嚎,合并后再刪掉分支杠氢,這和直接在master分支上工作效果是一樣的,但過(guò)程更安全另伍。
基礎(chǔ)命令
使用git最基礎(chǔ)的操作鼻百。
git-config 配置
用戶(hù)配置
git config --global user.name "John EveryThing"
git config --global user.email yourusername@example.com
配置級(jí)別
--local 默認(rèn),高優(yōu)先級(jí):只影響本倉(cāng)庫(kù)
--global 中優(yōu)先級(jí):影響到所有當(dāng)前用戶(hù)的git倉(cāng)庫(kù)
--system 低優(yōu)先級(jí):影響到全系統(tǒng)的git倉(cāng)庫(kù)
git-init 初始化倉(cāng)庫(kù)
使用git status
查看當(dāng)前倉(cāng)庫(kù)的信息摆尝。
再使用git init
來(lái)在一個(gè)文件夾創(chuàng)建一個(gè)git倉(cāng)庫(kù)温艇,會(huì)在此文件夾創(chuàng)建一個(gè).git文件夾。
這個(gè)目錄默認(rèn)是隱藏的,如果沒(méi)有看到.git
目錄堕汞,用ls -ah
命令顯示勺爱。
git-status 對(duì)狀態(tài)的跟蹤
git對(duì)文件的狀態(tài)跟蹤分內(nèi)容狀態(tài)和文件狀態(tài)。
內(nèi)容狀態(tài):工作目錄讯检、暫存區(qū)琐鲁、提交區(qū)。
文件狀態(tài):未跟蹤人灼、已跟蹤围段。
所有這些狀態(tài)之間都可以相互轉(zhuǎn)化。
git-add 添加跟蹤文件
git add *.*
命令添加單個(gè)文件內(nèi)容到暫存區(qū)投放,同時(shí)文件被跟蹤奈泪。如果要添加當(dāng)前目錄下的所有文件,使用git add .
命令。
gitignore 篩選添加文件
.gitignore在添加時(shí)忽略匹配的文件涝桅,僅作用于未追蹤的文件拜姿。是一個(gè)篩選列表不能用于刪除已經(jīng)添加上的文件。在github已經(jīng)有g(shù)itignore的官方忽略文檔冯遂。
git-rm 從暫存區(qū)刪除文件
git rm --cached
僅從暫存區(qū)刪除砾隅。
git rm
從暫存區(qū)與工作目錄刪除。
git rm $(git ls-files --deleted)
刪除所有被跟蹤债蜜,但是在工作目錄被刪除的文件晴埂。其中l(wèi)s-files是到暫存區(qū)查找。
git-commit 從暫存區(qū)提交
git commit
命令根據(jù)暫存區(qū)內(nèi)容創(chuàng)建一個(gè)提交記錄寻定。
git commit -m 'initial commit'
這個(gè)命令使用-m來(lái)在提交同時(shí)聲明一個(gè)注釋儒洛。
如果想要省略git add這一步直接提交,添加上-a參數(shù)狼速,使用git commit -a -m 'full commit'
命令琅锻,就會(huì)從工作目錄直接提交到提交區(qū)。
git-log 查看歷史信息
git log
命令直接用于查看完整信息的提交歷史向胡。如果只想查看簡(jiǎn)短的配置信息恼蓬,添加--oneline參數(shù),即git log --oneline
僵芹。
如果想讓查看的配置信息完整美觀又簡(jiǎn)潔:
git log --color --graph --pretty=format:'%Cred%h%Creset
-%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset --abbrev-commit
git config alias 配置別名
上面的配置信息太長(zhǎng)了处硬,用alias命令給自己定義縮短。
$ git config --global alias.lg "log --color --graph --pretty=format:
'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset --abbrev-commit"
$ git lg
git-diff 查看差異
直接使用git diff
查看工作目錄與暫存區(qū)的差異拇派。
用git diff -cached [<reference>]
查看暫存區(qū)與某次提交差異荷辕,默認(rèn)為HEAD(指向當(dāng)前的提交),如果只是為了查看暫存區(qū)與上一次提交的差異件豌,最后的這個(gè)參數(shù)可以不傳疮方。git diff HEAD
。
用git diff <reference>
查看工作目錄與某次提交的差異茧彤,后面可以接兩個(gè)參數(shù)骡显。
git-checkout 撤銷(xiāo)本地修改
git checkout -- <file>
將文件內(nèi)容從暫存區(qū)復(fù)制到工作目錄,該操作會(huì)丟棄對(duì)暫存區(qū)內(nèi)容的修改曾掂,使用時(shí)要小心惫谤。
git-reset 撤銷(xiāo)暫存區(qū)內(nèi)容
git reset HEAD <file>
將文件內(nèi)容從上次提交回退到暫存區(qū)。這樣的操作會(huì)造成暫存區(qū)與工作目錄文件的不一致遭殉,git會(huì)提示沒(méi)有用add命令添加修改后的工作目錄內(nèi)容到暫存區(qū)石挂。
如皋想將內(nèi)容從上次提交后在提交區(qū)的內(nèi)容復(fù)制到工作目錄,使用gitcheckout HEAD -- <file>
git branch分支操作
分支的增刪查改都靠它险污。
git branch <branchName>
用來(lái)創(chuàng)建一個(gè)分支。
加入-d參數(shù)后git branch -d <branchName>
可以用來(lái)刪除指定的分支。
git checkout分支
通過(guò)移動(dòng)HEAD檢出版本蛔糯,可用于分支切換拯腮。
git checkout <branchName>
切換到目標(biāo)分支。
加入-b參數(shù)后git checkout -b <branchName>
會(huì)創(chuàng)建并切換到該分支蚁飒。相當(dāng)于先git branch
后緊接一個(gè)git checkout
动壤。
git checkout <reference>
移動(dòng)到任何一個(gè)commit id所在的引用對(duì)象上。
想快速回到上一個(gè)分支淮逻?使用git checkout -
命令即可琼懊。
git branch -v
顯示現(xiàn)在所有的分支信息,分支前面帶星號(hào)的就是當(dāng)前HEAD指針指向的分支爬早。
當(dāng)checkout到一個(gè)不是分支指針?biāo)诘腸ommit id后哼丈,此時(shí)的HEAD指針會(huì)指向一個(gè)非分支指針指向的位置,此時(shí)的狀態(tài)稱(chēng)為detached(分離的) head筛严。如果HEAD處于分離狀態(tài)就要盡量避免在此狀態(tài)提交東西醉旦,因?yàn)闆](méi)有引用會(huì)指向這個(gè)提交記錄,當(dāng)HEAD重新回到master分支時(shí)剛才的提交都會(huì)被視為沒(méi)有做引用桨啃,最后會(huì)在垃圾回收階段被回收车胡。因此當(dāng)HEAD處于分離狀態(tài)是不要進(jìn)行寫(xiě)操作,而只是讀取它的內(nèi)容照瘾。由于HEAD指向的內(nèi)容可以被復(fù)制到暫存區(qū)和工作目錄匈棘,這是可以查看具體提交時(shí)的信息。
git reset回退
如果要回退到其他commit版本git reset --mixed <commit id>
析命,最后的參數(shù)如果不填就回退到上一個(gè)commit版本羹饰。這樣,HEAD,master都會(huì)移動(dòng)到上一個(gè)commit碳却,同時(shí)它們指向的內(nèi)容會(huì)被復(fù)制到暫存區(qū)队秩。
當(dāng)使用head模式git reset --hard <commit id>
,這部分內(nèi)容除了被復(fù)制到暫存區(qū)昼浦,還會(huì)被復(fù)制到工作目錄馍资。
使用soft模式git reset --soft <commit id>
,只有HEAD,master移動(dòng)到這個(gè)commit上关噪,對(duì)暫存區(qū)和工作目錄不會(huì)有處理鸟蟹。這樣上一個(gè)提交沒(méi)有上傳,也沒(méi)有任何指針指向它了使兔,有可能會(huì)被回收建钥,成為了一個(gè)沒(méi)有被索引的提交。怎么找回它呢虐沥?使用git reflog
命令按順序查看之前經(jīng)過(guò)的所有commit路徑熊经,當(dāng)前所在的位置就是列表的頂部泽艘,之前的commit會(huì)按序向下排,但是使用這個(gè)命令找回之前的commit要盡快镐依,否則有的記錄可能會(huì)丟失匹涮。
使用捷徑
可以避免使用不直觀的哈希值,用捷徑,在下面的例子中槐壳,A表示HEAD指針然低,或分支名,或commit id务唐。
A^表示A之上的父提交雳攘。A~n表示在A之前的第n次提交。
reset vs checkout
通過(guò)上面的內(nèi)容可以看出reset和checkout直接有非常多的相似之處枫笛,下面列表以表示一下他們之間的區(qū)別吨灭。
git stash暫時(shí)保存
stash是一個(gè)獨(dú)立在工作目錄和暫存區(qū)之外的一個(gè)臨時(shí)保存區(qū)。
git stash save 'push to stash area'
會(huì)保存目前的工作目錄和暫存區(qū)狀態(tài)崇堰,并返回到干凈的工作空間沃于,同時(shí)保存一條注釋。
使用git stash list
查看stash區(qū)保存的所有信息海诲。
然后使用git stash apply stash@{0}
恢復(fù)stash區(qū)的內(nèi)容到工作目錄繁莹。最后使用git stash drop stash@{0}
將stash上的記錄刪掉。
上面的兩條操作可以合為stash pop
一條命令完成特幔,stash pop = stash apply + stash drop.
git merge合并分支
假設(shè)當(dāng)前的HEAD指向master分支咨演,同時(shí)還有個(gè)分支名為next,使用命令git merge next
由于目前正在master分支所以省略了第二個(gè)參數(shù)蚯斯,合并的結(jié)果會(huì)被復(fù)制到工作目錄和暫存區(qū)薄风,再會(huì)完成一次提交,這個(gè)提交節(jié)點(diǎn)的父節(jié)點(diǎn)有兩個(gè)拍嵌。來(lái)看一下這個(gè)合并后的節(jié)點(diǎn)的具體信息遭赂,使用git cat-gile -p HEAD
命令,會(huì)發(fā)現(xiàn)有兩個(gè)parent commit id横辆,而next分支沒(méi)有改變撇他。
在git merge next master
合并后有很大的幾率會(huì)提示兩個(gè)節(jié)點(diǎn)中有沖突的文件。使用git status
查看沖突的具體信息狈蚤,在文件中做好修改后使用git add和git commit來(lái)解決困肩。
假設(shè)從master分支創(chuàng)建了next分支,但是master分支沒(méi)有向前移動(dòng)僅僅是在next分支上做了修改脆侮,這時(shí)候使用git merge next
命令會(huì)將master分支指向當(dāng)前操作的next分支锌畸,這樣操作就會(huì)變成線(xiàn)性,master分支其實(shí)與next分支合并了靖避。
如果要避免fast-forward式的合并潭枣,使用git merge next --no-ff
比默,這樣原來(lái)的master分支會(huì)向前復(fù)制到一個(gè)新分支,并且與next分支合并卸耘。
git rebase修剪歷史基線(xiàn)
首先現(xiàn)在有兩個(gè)分支:master和feature
對(duì)如圖所示的分支進(jìn)行修剪基線(xiàn)操作
git rebase master
退敦,git首先會(huì)找到兩個(gè)分支節(jié)點(diǎn)的結(jié)束點(diǎn)粘咖,然后會(huì)將head所在的所有歷史節(jié)點(diǎn)分別與master最后的節(jié)點(diǎn)進(jìn)行合并并在master分支上依次將合并結(jié)果保存為新節(jié)點(diǎn)蚣抗,這個(gè)過(guò)程是重演而不是復(fù)制,因?yàn)閯?chuàng)建了2個(gè)新的節(jié)點(diǎn)瓮下。然后HEAD和feather分支都會(huì)指向最后的這次提交翰铡,master分支還保存在原來(lái)的位置,如下圖:然而并不是所有的變基操作都需要將原來(lái)的分支上所有節(jié)點(diǎn)都與master合并一次讽坏,所以這時(shí)候可以用
git rebase --onto master <commit id>
這樣指定feather上某個(gè)特定的節(jié)點(diǎn)之后的節(jié)點(diǎn)與master的最后一個(gè)節(jié)點(diǎn)合并锭魔,指定的節(jié)點(diǎn)在合并時(shí)就被丟棄了。如圖rebase vs merge
rebase和merge沒(méi)有孰好孰壞之說(shuō)路呜,最大的區(qū)別就是合并后是否是線(xiàn)性的迷捧。
切勿在公有分支使用rebase,比如之前例子中的master分支胀葱,否則rebase的后果會(huì)變成這樣:
這樣的master就變化到feather了漠秋。
git tag別名
如果要給一個(gè)commit id 設(shè)置一個(gè)別名就可以使用git tag v0.1 e39d0b2