今日份雞湯:努力從來不嫌晚冗栗,只要你堅(jiān)定開始就可以啦~
進(jìn)入正題:
1演顾、Git ?clone(遠(yuǎn)程項(xiàng)目clone到本地):
參數(shù)挺多,但常用的就幾個(gè):
1> 最簡(jiǎn)單直接的命令:git clone xxx.git
2> 如果想clone到指定目錄:git clone xxx.git "指定目錄"
3> clone時(shí)創(chuàng)建新的分支替代默認(rèn)Origin HEAD(master):git clone -b new_branch_name xxx.git
4> clone 遠(yuǎn)程分支
git clone 命令默認(rèn)的只會(huì)建立master分支隅居,如果你想clone指定的某一遠(yuǎn)程分支(如:dev)的話钠至,可以如下:
A. 查看所有分支(包括隱藏的) ?git branch -a?顯示所有分支,如:
* master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/master
B. ?在本地新建同名的("dev")分支胎源,并切換到該分支
git?checkout?-t?origin/dev?該命令等同于:git?checkout?-b?dev?origin/dev
2棉钧、分支查看:
1> 查看本地分支:git branch
2> 查看遠(yuǎn)程分支:git branch -r
3> 查看跟蹤分支:git branch -vv
3、git checkout -b(從已有本地分支拉新分支):
開發(fā)過程中經(jīng)常用到從master分支copy一個(gè)開發(fā)分支涕蚤,下面我們就用命令行完成這個(gè)操作:
1> 切換到被copy的分支(master)宪卿,并且從遠(yuǎn)端拉取最新版本
git checkout master
git pull
2> 從當(dāng)前分支拉copy開發(fā)分支:git checkout -b dev
執(zhí)行上面的命令后提示 Switched to a new branch 'dev'的诵,證明已經(jīng)切換到新的分支上
3> 把新建的分支push到遠(yuǎn)端:git push origin dev
4> 拉取遠(yuǎn)端分支:git pull
執(zhí)行上述命令提示:
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=origin/<branch> dev
經(jīng)過驗(yàn)證,當(dāng)前的分支并沒有和本地分支關(guān)聯(lián)佑钾,根據(jù)提示進(jìn)行下一步:
5> 關(guān)聯(lián):git branch --set-upstream-to=origin/dev
6> 再次拉取 驗(yàn)證:git pull
看到提示:Already up-to-date西疤,到此完事。
4休溶、git tag(給當(dāng)前分支打標(biāo)簽):
列出tag:
git tag:在控制臺(tái)打印出當(dāng)前倉(cāng)庫(kù)的所有tag
git tag -l 'v0.1.*': 搜索符合模式的Tag
打tag:
git tag分為兩種類型:輕量tag和附注tag代赁。輕量tag是指向提交對(duì)象的引用,附注Tag則是倉(cāng)庫(kù)中的一個(gè)獨(dú)立對(duì)象兽掰。建議使用附注Tag芭碍。
創(chuàng)建輕量Tag:git tag v0.1.2-light
創(chuàng)建附注Tag:git tag -a v0.1.2 -m "0.1.2版本" (我一般上線前打tag都用這種)
創(chuàng)建輕量Tag不需要傳遞參數(shù),直接指定Tag名稱即可禾进。
創(chuàng)建附注Tag時(shí)豁跑,參數(shù)a即annotated的縮寫,指定Tag類型泻云,后附Tag名。參數(shù)m指定Tag說明狐蜕,說明信息會(huì)保存在Tag對(duì)象中宠纯。
切換到Tag:git checkout tagName (與切換分支命令相同)
查看Tag信息:git show v0.1.2(用git show命令可以查看Tag的版本信息)
刪除Tag:git tag -d v0.1.2(誤打或需要修改Tag時(shí),需要先將Tag刪除层释,參數(shù)d即delete的縮寫婆瓜,意為刪除其后指定的Tag。)
刪除遠(yuǎn)程tag:git?push?origin?--delete?tag tagName
給指定的commit打Tag
打Tag不必要在head之上贡羔,也可在之前的版本上打廉白,這需要你知道某個(gè)提交對(duì)象的校驗(yàn)和(通過git log獲取)乖寒。
補(bǔ)打Tag:git tag -a v0.1.1 9fbc3d0
Tag推送到服務(wù)器
通常的git push不會(huì)將Tag對(duì)象提交到git服務(wù)器猴蹂,我們需要進(jìn)行顯式的操作:
git push origin v0.1.2:將v0.1.2 Tag提交到git服務(wù)器
git push origin --tags: 將本地所有Tag一次性提交到git服務(wù)器
注意:如果想看之前某個(gè)Tag狀態(tài)下的文件,可以這樣操作
1> git tag:查看當(dāng)前分支下的Tag
2> git checkout v0.21 :此時(shí)會(huì)指向打v0.21 Tag時(shí)的代碼狀態(tài)楣嘁,(但現(xiàn)在處于一個(gè)空的分支上)
5磅轻、git reset(本地版本回滾):
當(dāng)我們?cè)诤洗a的時(shí)候經(jīng)常會(huì)遇到一些問題,這時(shí)候分支就處于merging狀態(tài)逐虚,這時(shí)候可以用下面的命令撤銷
?git reset --hard HEAD(這個(gè)實(shí)際工作場(chǎng)景確實(shí)用過幾次)
1> git reset HEAD^ :回退版本聋溜,一個(gè)^表示一個(gè)版本,可以多個(gè)叭爱,另外也可以使用 git reset HEAD~n這種形式撮躁。?
如果HEAD指針指向的是master分支,那么HEAD還可以換成master买雾,如果知道特定的commit-id把曼,那么還可以直接使用 git reset commit-id 如果不加參數(shù)杨帽,實(shí)際上使用的是默認(rèn)的參數(shù)mixed,
我們可以使用git log -3來查看最近三次的提交祝迂,形如 git log -n 睦尽,n就是想要輸出的個(gè)數(shù),可以看到commit-id型雳,author当凡,date等信息
下面介紹三種參數(shù):
(1) soft 參數(shù):git reset --soft HEAD~1 意為將版本庫(kù)軟回退1個(gè)版本缀磕,所謂軟回退表示將本地版本庫(kù)的頭指針全部重置到指定版本毫炉,且將這次提交之后的所有變更都移動(dòng)到暫存區(qū)
(2) 默認(rèn)的mixed參數(shù):git reset HEAD~1 意為將版本庫(kù)回退1個(gè)版本涤浇,將本地版本庫(kù)的頭指針全部重置到指定版本乘陪,且會(huì)重置暫存區(qū)深员,即這次提交之后的所有變更都移動(dòng)到未暫存階段
(3) hard參數(shù):git reset --hard HEAD~1 意將版本庫(kù)為回退1個(gè)版本玷过,但是不僅僅是將本地版本庫(kù)的頭指針全部重置到指定版本肄鸽,也會(huì)重置暫存區(qū)社证,并且會(huì)將工作區(qū)代碼也回退到這個(gè)版本 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
了解這三個(gè)參數(shù)已足夠我們?nèi)粘i_發(fā)使用了钓简, 注意soft參數(shù)與默認(rèn)參數(shù)都不會(huì)修改工作區(qū)代碼乌妒,只有hard參數(shù)才會(huì)修改工作區(qū)代碼。
2> git reset 配合 git commit 追加提交?
什么時(shí)候會(huì)用到追加提交外邓,追加提交有什么優(yōu)點(diǎn)撤蚊?
(1)對(duì)未merge的版本庫(kù)中的提交不滿意,希望修改其中的某些信息损话,如代碼侦啸,如提交描述等,可以使用git commit --amend進(jìn)行追加提交丧枪,優(yōu)點(diǎn)是不會(huì)產(chǎn)生新的commit-id
(2)修改方法:如果想修改的不是最新一版的提交光涂,那么可以通過git reset --hard HEAD~n將版本回退到需要的那版,如果想修改代碼拧烦,那么直接在工作區(qū)進(jìn)行代碼修改忘闻,
修改完之后git add到暫存區(qū)而不必再git pull,而如果是修改其他信息屎篱,那么可以直接使用git commit --amend進(jìn)行追加提交服赎,git commit --amend命令會(huì)打開一個(gè)編輯器,可以修改其中的信息交播,
如果修改了代碼而不修改其他信息重虑,則直接 Ctrl + X離開編輯器,再git push推送到遠(yuǎn)程服務(wù)器秦士,如果也修改了其他信息缺厉,那么需要先使用Ctrl + M寫入信息,再Ctrl + X離開編輯器,再推送提针。
3> 查看幫助:git reset -h | git reset --help?
6命爬、刪除分支:
git 刪除本地分支:git branch -D branchName
git 刪除遠(yuǎn)程分支:git push origin :branchName? (origin 后面有空格)
在Git v1.7.0 之后,可以使用這種語法刪除遠(yuǎn)程分支:git?push?origin?--delete branchName
7辐脖、git 遠(yuǎn)程分支回滾
簡(jiǎn)單的辦法:
先用git log 查找出commit_id
? ? git?reset?--hard commit_id
????git push origin HEAD --force
其他:
????根據(jù)–soft –mixed –hard饲宛,會(huì)對(duì)working tree和index和HEAD進(jìn)行重置:
????git reset –mixed:此為默認(rèn)方式,不帶任何參數(shù)的git reset嗜价,即時(shí)這種方式艇抠,它回退到某個(gè)版本,只保留源碼久锥,回退commit和index信息
????git reset –soft:回退到某個(gè)版本家淤,只回退了commit的信息,不會(huì)恢復(fù)到index file一級(jí)瑟由。如果還要提交絮重,直接commit即可
????git reset –hard:徹底回退到某個(gè)版本,本地的源碼也會(huì)變?yōu)樯弦粋€(gè)版本的內(nèi)容
????HEAD 最近一個(gè)提交
????HEAD^ 上一次
? ? <commit_id>?每次commit的SHA1值.?可以用git?log?看到,也可以在頁面上commit標(biāo)簽頁里找到.
麻煩的辦法:
這個(gè)是重點(diǎn)要說的內(nèi)容歹苦,過程比本地回滾要復(fù)雜
應(yīng)用場(chǎng)景:自動(dòng)部署系統(tǒng)發(fā)布后發(fā)現(xiàn)問題青伤,需要回滾到某一個(gè)commit,再重新發(fā)布
原理:先將本地分支退回到某個(gè)commit殴瘦,刪除遠(yuǎn)程分支潮模,再重新push本地分支
操作步驟:
1>、git checkout the_branch
2>痴施、git pull
3>、git branch the_branch_backup //備份一下這個(gè)分支當(dāng)前的情況
4>究流、git reset --hard the_commit_id //把the_branch本地回滾到the_commit_id
5>辣吃、git push origin :the_branch //刪除遠(yuǎn)程 the_branch
6>、git push origin the_branch //用回滾后的本地分支重新建立遠(yuǎn)程分支
7>芬探、git push origin :the_branch_backup //如果前面都成功了神得,刪除這個(gè)備份分支
如果使用了gerrit做遠(yuǎn)程代碼中心庫(kù)和code review平臺(tái),需要確保操作git的用戶具備分支的push權(quán)限偷仿,并且選擇了 Force Push選項(xiàng)(在push權(quán)限設(shè)置里有這個(gè)選項(xiàng))
另外哩簿,gerrit中心庫(kù)是個(gè)bare庫(kù),將HEAD默認(rèn)指向了master酝静,因此master分支是不能進(jìn)行刪除操作的节榜,最好不要選擇刪除master分支的策略,換用其他分支别智。如果一定要這樣做宗苍,可以考慮到gerrit服務(wù)器上修改HEAD指針。。讳窟。不建議這樣做
8让歼、git stash(git 儲(chǔ)藏工具)
儲(chǔ)藏(Stashing)
經(jīng)常有這樣的事情發(fā)生,當(dāng)你正在進(jìn)行項(xiàng)目中某一部分的工作丽啡,里面的東西處于一個(gè)比較雜亂的狀態(tài)谋右,而你想轉(zhuǎn)到其他分支上進(jìn)行一些工作。問題是补箍,你不想提交進(jìn)行了一半的工作改执,否則以后你無法回到這個(gè)工作點(diǎn)。解決這個(gè)問題的辦法就是git stash命令馏予。
“‘儲(chǔ)藏”“可以獲取你工作目錄的中間狀態(tài)——也就是你修改過的被追蹤的文件和暫存的變更——并將它保存到一個(gè)未完結(jié)變更的堆棧中天梧,隨時(shí)可以重新應(yīng)用。
儲(chǔ)藏你的工作
為了演示這一功能霞丧,你可以進(jìn)入你的項(xiàng)目呢岗,在一些文件上進(jìn)行工作,有可能還暫存其中一個(gè)變更蛹尝。如果你運(yùn)行?git status后豫,你可以看到你的中間狀態(tài):
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
# modified: index.html
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# modified: lib/simplegit.rb
現(xiàn)在你想切換分支,但是你還不想提交你正在進(jìn)行中的工作突那;所以你儲(chǔ)藏這些變更挫酿。為了往堆棧推送一個(gè)新的儲(chǔ)藏,只要運(yùn)行?git stash:
$ git stash
Saved working directory and index state \
"WIP on master: 049d078 added the index file"
HEAD is now at 049d078 added the index file
(To restore them type "git stash apply")
你的工作目錄就干凈了:
$ git status
# On branch master
nothing to commit, working directory clean
這時(shí)愕难,你可以方便地切換到其他分支工作早龟;你的變更都保存在棧上。要查看現(xiàn)有的儲(chǔ)藏猫缭,你可以使用?git stash list:
$ git stash list
stash@{0}: WIP on master: 049d078 added the index file
stash@{1}: WIP on master: c264051 Revert "added file_size"
stash@{2}: WIP on master: 21d80a5 added number to log
在這個(gè)案例中葱弟,之前已經(jīng)進(jìn)行了兩次儲(chǔ)藏,所以你可以訪問到三個(gè)不同的儲(chǔ)藏猜丹。你可以重新應(yīng)用你剛剛實(shí)施的儲(chǔ)藏芝加,所采用的命令就是之前在原始的 stash 命令的幫助輸出里提示的:git stash apply。如果你想應(yīng)用更早的儲(chǔ)藏射窒,你可以通過名字指定它藏杖,像這樣:git stash apply stash@{2}。如果你不指明脉顿,Git 默認(rèn)使用最近的儲(chǔ)藏并嘗試應(yīng)用它:
$ git stash apply
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# modified: index.html
# modified: lib/simplegit.rb
你可以看到 Git 重新修改了你所儲(chǔ)藏的那些當(dāng)時(shí)尚未提交的文件蝌麸。在這個(gè)案例里,你嘗試應(yīng)用儲(chǔ)藏的工作目錄是干凈的弊予,并且屬于同一分支祥楣;但是一個(gè)干凈的工作目錄和應(yīng)用到相同的分支上并不是應(yīng)用儲(chǔ)藏的必要條件。你可以在其中一個(gè)分支上保留一份儲(chǔ)藏,隨后切換到另外一個(gè)分支误褪,再重新應(yīng)用這些變更责鳍。在工作目錄里包含已修改和未提交的文件時(shí),你也可以應(yīng)用儲(chǔ)藏——Git 會(huì)給出歸并沖突如果有任何變更無法干凈地被應(yīng)用兽间。
對(duì)文件的變更被重新應(yīng)用历葛,但是被暫存的文件沒有重新被暫存。想那樣的話嘀略,你必須在運(yùn)行?git stash apply?命令時(shí)帶上一個(gè)?--index?的選項(xiàng)來告訴命令重新應(yīng)用被暫存的變更恤溶。如果你是這么做的,你應(yīng)該已經(jīng)回到你原來的位置:
$ git stash apply --index
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
# modified: index.html
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# modified: lib/simplegit.rb
apply 選項(xiàng)只嘗試應(yīng)用儲(chǔ)藏的工作——儲(chǔ)藏的內(nèi)容仍然在棧上帜羊。要移除它咒程,你可以運(yùn)行?git stash drop,加上你希望移除的儲(chǔ)藏的名字:
$ git stash list
stash@{0}: WIP on master: 049d078 added the index file
stash@{1}: WIP on master: c264051 Revert "added file_size"
stash@{2}: WIP on master: 21d80a5 added number to log
$ git stash drop stash@{0}
Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)
你也可以運(yùn)行?git stash pop?來重新應(yīng)用儲(chǔ)藏讼育,同時(shí)立刻將其從堆棧中移走帐姻。
取消儲(chǔ)藏(Un-applying a Stash)
在某些情況下,你可能想應(yīng)用儲(chǔ)藏的修改奶段,在進(jìn)行了一些其他的修改后饥瓷,又要取消之前所應(yīng)用儲(chǔ)藏的修改。Git沒有提供類似于?stash unapply?的命令痹籍,但是可以通過取消該儲(chǔ)藏的補(bǔ)丁達(dá)到同樣的效果:
$ git stash show -p stash@{0} | git apply -R
同樣的呢铆,如果你沒有指定具體的某個(gè)儲(chǔ)藏,Git 會(huì)選擇最近的儲(chǔ)藏:
$ git stash show -p | git apply -R
你可能會(huì)想要新建一個(gè)別名蹲缠,在你的 Git 里增加一個(gè)?stash-unapply?命令棺克,這樣更有效率。例如:
$ git config --global alias.stash-unapply '!git stash show -p | git apply -R'
$ git stash apply
$ #... work work work
$ git stash-unapply
從儲(chǔ)藏中創(chuàng)建分支
如果你儲(chǔ)藏了一些工作线定,暫時(shí)不去理會(huì)逆航,然后繼續(xù)在你儲(chǔ)藏工作的分支上工作,你在重新應(yīng)用工作時(shí)可能會(huì)碰到一些問題渔肩。如果嘗試應(yīng)用的變更是針對(duì)一個(gè)你那之后修改過的文件,你會(huì)碰到一個(gè)歸并沖突并且必須去化解它拇惋。如果你想用更方便的方法來重新檢驗(yàn)?zāi)銉?chǔ)藏的變更周偎,你可以運(yùn)行?git stash branch,這會(huì)創(chuàng)建一個(gè)新的分支撑帖,檢出你儲(chǔ)藏工作時(shí)的所處的提交蓉坎,重新應(yīng)用你的工作,如果成功胡嘿,將會(huì)丟棄儲(chǔ)藏蛉艾。
$ git stash branch testchanges
Switched to a new branch "testchanges"
# On branch testchanges
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
# modified: index.html
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# modified: lib/simplegit.rb
Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)
這是一個(gè)很棒的捷徑來恢復(fù)儲(chǔ)藏的工作然后在新的分支上繼續(xù)當(dāng)時(shí)的工作。
9、git rebase(git 合并多個(gè) Commit)
在使用 Git 作為版本控制的時(shí)候勿侯,我們可能會(huì)由于各種各樣的原因提交了許多臨時(shí)的 commit拓瞪,而這些 commit 拼接起來才是完整的任務(wù)。那么我們?yōu)榱吮苊馓嗟?commit 而造成版本控制的混亂助琐,通常我們推薦將這些 commit 合并成一個(gè)祭埂。
首先假設(shè)我們有3個(gè) commit,用git log -3命令來查看兵钮。
我們需要將 2dfbc7e8 和 c4e858b5 合并成一個(gè) commit蛆橡,那么我們輸入如下命令
其中,-i 的參數(shù)是不需要合并的 commit 的 hash 值掘譬,這里指的是第一條 commit泰演, 接著我們就進(jìn)入到 vi 的編輯模式
可以看到其中分為兩個(gè)部分,上方未注釋的部分是填寫要執(zhí)行的指令葱轩,而下方注釋的部分則是指令的提示說明睦焕。指令部分中由前方的命令名稱、commit hash 和 commit message 組成酿箭。
當(dāng)前我們只要知道 pick 和 squash 這兩個(gè)命令即可复亏。
pick 的意思是要會(huì)執(zhí)行這個(gè) commit
squash 的意思是這個(gè) commit 會(huì)被合并到前一個(gè)commit
我們將 c4e858b5 這個(gè) commit 前方的命令改成 squash 或 s,然后輸入:wq以保存并退出
這是我們會(huì)看到 commit message 的編輯界面
其中, 非注釋部分就是兩次的 commit message, 你要做的就是將這兩個(gè)修改成新的 commit message缭嫡。
輸入wq保存并推出, 再次輸入git log查看 commit 歷史信息缔御,你會(huì)發(fā)現(xiàn)這兩個(gè) commit 已經(jīng)合并了。
注意事項(xiàng):如果這個(gè)過程中有操作錯(cuò)誤妇蛀,可以使用 git rebase --abort來撤銷修改耕突,回到?jīng)]有開始操作合并之前的狀態(tài)。