Git中~你必須掌握的!

_Dreams發表於2019-04-30

前言:

大佬直接進入下面正題,前言可以略過!

我相信有很多童鞋在剛開始使用git或者使用了許久之後還是對git不怎麼熟悉,尤其是出現了一大堆英文提示的時候手足無措,又或者程式碼"莫名其妙"的發生改動,導致團隊無法繼續正常工作的時候真恨不得不繼續使用git了.

不要慌!這篇文章將帶你完完全全掌握平時常見的場景以及出現的問題如何解決的本領!(同時我自己也可以再複習一遍~?)

那麼本文章預設你已經學習過了git,但只是對git有的知識一知半解的情況下去闡述!(也許熱愛git的你還不熟悉git基礎知識建議可以先去其他地方學習git相關的基礎知識,遇到不理解的也許這篇文章就會幫你解開謎團!)

最小配置

那麼我們會發現在使用git之前需要配置一段這樣的命令(如果不配置以後push之類的操作會有一大堆提示資訊影響我們的後續操作):

$ git config --global user.name 'your_name'

$ git config --global user.email 'your_email@domain.com'
複製程式碼

那麼這段命令中的--global大家有沒有想過是什麼意思呢?究竟有什麼作用?

config三個作用域

來講下剛剛的--global(全域性),那麼既然有全域性就肯定有區域性作用域:在git中叫做--local,其實還有一個是針對系統的:--system

--global是對當前使用者(根據系統使用者名稱判定)所有倉庫有效

--local只對當前工作的這個倉庫有效

--system對系統所有登入的使用者有效(不常用,對整個系統進行配置統一的配置項)

檢視config的設定命令:

$ git config --list --local

$ git config --list --global

$ git config --list --system
複製程式碼

建立git倉庫

把已有的專案程式碼納入Git管理(場景一):

$ cd 專案程式碼所在的資料夾
$ git init
複製程式碼

新建的專案直接用Git管理(場景二):

$ cd 某個資料夾
$ git init your_project #會在當前路徑下建立和專案名稱同名的資料夾
$ cd your_project
複製程式碼

檔案重新命名(方法一)

假設我們重新命名readme.mdread.md 所以我們執行以下命令

$ mv readme.md read.md
複製程式碼

這條命令會被git認為是 readme.md會刪除掉了,然後新增了一個read.md檔案

我們現在要做的是把新增的read.md檔案新增到git管理裡,且刪除原來的readme.md檔案

$ git add read.md
$ git rm readme.md
複製程式碼

然後使用git status檢視管理狀態 結果會發現現在變成了

Changes to be commited:
(use "git reset HEAD <file>..." to unstage)
    renamed: readme.md -> read.md
複製程式碼

至此,說明git已經知道了我們在做重新命名操作

假設現在我們發現自己誤操作了,不想要剛剛的操作了,怎麼辦呢?

$ git reset --hard
複製程式碼

其實這條命令屬於git中比較危險的命令,他的意思是把暫存區工作空間裡內容都清理掉(還原到剛剛操作重新命名之前的狀態)

檔案重新命名(方法二)

細心的童鞋可能發現剛剛重新命名的操作過於複雜,那有沒有簡單的方法重新命名呢?答案是:當然有!(有木有很激動)

$ git mv readme.md read.md
複製程式碼

然後使用git status檢視管理狀態 結果會發現現在也變成了

Changes to be commited:
(use "git reset HEAD <file>..." to unstage)
    renamed: readme.md -> read.md
複製程式碼

這樣一句命令就完成了方法一完成的事情,是不是很簡單呢~ 那麼我們想提交本次操作該怎麼做呢? 我們可以直接使用

$ git commit -m '重新命名readme.md為read.md'
複製程式碼

我們發現現在已經成功的新生成了一個commit記錄

那麼我們突然發現這次commit沒什麼作用想撤銷本次commit提交該怎麼做

$ git log #檢視所有commitId
$ git revert <commit> #找到你想撤銷的commitId複製並替換掉這裡的<commit>
複製程式碼

commitId是類似這樣的:

Git中~你必須掌握的!

刪除暫存區檔案(並不會直接刪除工作區的檔案)

$ git rm 檔名
複製程式碼

暫存區相關

$ git rm --cached . #清理暫存區所有檔案
複製程式碼

git log

通過git log檢視版本演變歷史

其實git log後面還可以攜帶引數

$ git log --oneline --all #可以檢視簡潔的所有commit資訊
$ git log -n4 #代表檢視最近四次的commit資訊
$ git log --all --graph #檢視基於圖形的commit歷史記錄
$ git log --oneline <branch> #檢視某個分支的commit記錄
複製程式碼

分支操作

$ git branch -av #檢視本地共有多少分支
$ git checkout -b temp #建立一個新的temp分支
$ git checkout -b temp <commitId> #基於某一個歷史版本新建一個分支 
複製程式碼

刪除分支

$ git branch -d 分支名
複製程式碼

如果git有提示說明是在一些情況下git不允許刪除,如果確認的確需要刪除,那麼可以把小寫d改成大寫D來強制刪除

圖形介面(git自帶)

gitk
複製程式碼

開啟後也許會是這樣

Git中~你必須掌握的!
當然我們們可以藉助第三方的軟體,肯定比git自帶的使用更加方便快捷,因為這篇文章重點偏向命令式操作,所以這裡就不過多介紹了

分離頭指標(detached HEAD)

有時候我們會做出如下操作

$ git checkout 415c5c8086e16 #後面的隨機字串指的是某一次的commitId
複製程式碼

這時git會給我們出現類似下面的提示

Git中~你必須掌握的!
Git中~你必須掌握的!
what? 這段話大概是在說:

你正在基於415c5c8086e16這個commit正在做一個checkout的操作。 你現在正在處於分離頭指標的狀態,你可以做一些變更,產生一些commit,或者你也可以把你自己生成的這個commit丟棄掉,或者你可以繼續做開發,並不會影響其他分支! 那麼說的明白點就是:

我們現在正工作在沒有分支的情況下,那麼就是說現在沒有branch跟它掛鉤對應,那麼如果當我們在這種情況下做了一些功能的開發後又切換到了其他分支後,最後很可能會被git當做垃圾清理掉,所以這就是分離頭指標危險的地方!

但話又說回來,事物都具有兩面性,用的不好或者在不知情的情況下使用肯定會對我們產生危害,但假設我們知道的他會有什麼影響後,說不定多想想,還可能會帶給我們好處呢。

好處場景舉例:有時候變更只是嘗試性的變更,如果做出來感覺不好或者不想要了,那我們就可以隨時把它扔掉(直接checkout到其他分支,不理會他,過段時間就會自動被git清理掉)!那假設我們坐下來感覺還不錯,那麼我們就可以使用

$ git commit -am '提交資訊' #這條命令意思是直接生成commit不用add,但不推薦
複製程式碼

我們提交後,準備使用git log看下commit記錄,然後就會發現一件奇怪的事情發生:

Git中~你必須掌握的!
我們仔細看下圖片,右邊只有一個HEAD,正常情況下,HEAD總會跟一個分支掛鉤,但現在怎麼沒有分支啦? 說明現在我們還處於分離頭指標狀態!

我們現在嘗試切換一下分支到master分支!

切換後git可能會出來如下提示

Git中~你必須掌握的!

它說有一個commit在後面還沒有加到master分支裡面去,那麼這個其實就是分離頭指標導致的!

然後下面它還會再次提醒你,如果你想儲存這次的commit記錄,那麼你可以新建一個分支和這個3d4731d這個commit相關聯!

如果你看都不看一眼這個提示,繼續任性的往下隨心操作,那麼你剛剛在分離頭指標狀態下做的操作會統統丟掉!所以git的提示要多看

比較兩個commit之間的差異

$ git diff commitId1 commitId2
$ git diff HEAD HEAD~1
$ git diff HEAD HEAD^
複製程式碼

**HEAD可以指代最新的commit記錄

^是指最新的commit的上一個commit

^^就是指上上一個

~1也是指上一個 ~2就是上上一個

所以這三條命令效果是一樣的**

commit相關操作

修改最新commit的message

有時候我們提交的commit了發現描述的資訊不全面,想進行修改,那麼我們可以使用下面這條命令

$ git commit --amend
複製程式碼

然後git會彈出一個新介面,讓我們調整之前的message,修改後我們可以使用:wq!來儲存這個新修改的message並且退出這個視窗

修改前幾次的commit的message

我們先來看張圖

Git中~你必須掌握的!
這裡我們用到了git中的變基指令 那麼本次我們想對圖中標2的commit的message進行變更,那麼我們該怎麼做? 這裡強調下,引數i是指互動式變基就是指會彈出視窗讓我們更方便操作的方式進行變基 還有就是被變基的commit的commitId會發生改變哦!

重點來嘍 這裡我們需要選擇一個,我們這次要變更第二個commit,那麼這個基就要選擇被變(第二個commit)的這個commit的父級(第三個commit),父級的commitId是(27d2f814開頭的那個),自己的commitId是(429243060b開頭的那個),所以要基於父級(27d2f814開頭的那個commit)去做變基操作!

這塊比較繞,大家自己先捋一捋

接下來看命令操作!

$ git rebase -i 27d2f814
複製程式碼

敲下回車後我們發現彈出來了一個互動式的視窗 如圖:

Git中~你必須掌握的!

我們把4292430開頭的那個commitmessage修改成 Add a refering projects

所以我們把pick指令改成reword指令

Git中~你必須掌握的!

所以最終互動式視窗裡的內容就會被我們修改為

$ reword 4292430 Add refering projects #這裡我們只把剛剛的pick修改為了reword
$ pick a7dc188 Move filename readme.md to readme #本句可以無視,本例中只修改了第一句
複製程式碼

修改完畢後我們使用:wq!儲存並退出互動式控制檯 然後接著git又會彈出另一個新視窗

Git中~你必須掌握的!

那麼我們在這裡把Add refering projects修改為Add a refering project

修改完畢後我們使用:wq!儲存並退出互動式控制檯 然後git會做出如下提示:

Git中~你必須掌握的!

說明我們的變基操作順利完成了

變基操作其實是用到了分離頭指標去完成的, 其實git先分離頭指標,然後在上面做了調整,調整完畢後git還把新的commit產生後用一個指標指向了它!

但這裡需要注意:這只是本地的變基行為,如果有多人已經線上上操作正式專案,切不可盲目用該命令隨意操作,不然後果很嚴重!

差異比較

暫存區和HEAD差異比較

說白了就是add後的檔案和最新commit做比較

$ git diff --cached
複製程式碼

工作區和暫存區的差異比較

說白了就是自己最新寫的程式碼和add裡的對比

$ git diff -- 檔名
$ git diff #比較所有工作區和暫存區的差異
複製程式碼

對比不同分支的相同檔案的差異

$ git diff 分支一 分支二 -- 檔名
複製程式碼

恢復相關

暫存區恢復為和HEAD(最新的commit)的內容一樣

有時候我們add後突然發現我們不要暫存區的東西了,所以就要使用到如下命令了

$ git reset HEAD 或 git reset HEAD -- 檔名 #(如果沒有寫檔名就是全部恢復)
複製程式碼

暫存區工作區都恢復為和HEAD(最新的commit)的內容一樣

$ git reset --hard HEAD 或 git reset --hard HEAD -- 檔名 #(如果沒有寫檔名就是全部恢復)
複製程式碼

這裡補充說明下 --hard代表的是工作區

工作區的檔案恢復為和暫存區的一樣

有些時候做了一些變更,我們已經把這部分的程式碼放到了暫存區,然後我們又繼續在工作區做了一些變更,做完之後,思前想後,發現工作區的變更還不如暫存區的好,所以我們就希望把工作區的內容扔掉,變成和暫存區的一模一樣。

$ git checkout . #丟掉工作區全部的變更
$ git checkout -- 檔名 #丟棄這個檔案的變更
複製程式碼

這條命令也要慎用!一旦誤操作,工作區最新的程式碼也就丟失啦!

stash

有時候我們正在寫程式碼,突然加派緊急任務,要修改其他地方的bug,但我們又不想提交正在修改的,所以我們就需要是使用一個命令把當前的狀態臨時儲存起來

$ git stash #儲存
$ git stash list #檢視儲存好的stash
複製程式碼

儲存好之後我們會發現工作區變成了乾淨的了。 那麼假設我們的bug已經修改好了,我們想回到剛剛儲存前的狀態繼續做之前我們做的事情,該怎麼辦?

$ git stash apply #把stash裡面的東西取出來放到工作區,且他不會刪除stash裡的記錄
$ git stash pop  #把stash裡面的東西取出來放到工作區,但他會刪除stash裡的記錄
複製程式碼

以上兩個命令隨便挑選一個使用都可以恢復,看情況而定

.gitignore

我們只需要在專案中新建一個名字為:.gitignore的檔案 我們可以在.gitignore裡配置自己想exclude(排除)的檔案或資料夾。

遠端相關

這裡預設大家都會建立遠端倉庫,還不會的童鞋可以先去學習學習!

git push origin 分支名把本地的某個分支推送到遠端倉庫

git push origin -d 分支名 # 用 -d 引數把遠端倉庫的分支也刪了

假如是某個你自己獨立開發的branch 出錯了,出錯的內容已經合併到 master 同事的工作都在 master 上,你永遠不知道你的一次強制 push 會不會洗掉同事剛發上去的新提交。所以除非你是人員數量和行為都完全可控的超小團隊,可以和同事做到無死角的完美溝通,不然一定別在 master 上強制 push

在這種時候,你只能退一步,選用另一種策略:增加一個新的提交,把之前提交的內容抹掉。例如之前你增加了一行程式碼,你希望撤銷它,那麼你就做一個刪掉這行程式碼的提交;如果你刪掉了一行程式碼,你希望撤銷它,那麼你就做一個把這行程式碼還原回來的提交。這種事做起來也不算麻煩,因為 Git 有一個對應的指令:revert

它的用法很簡單,你希望撤銷哪個 commit,就把它填在後面:

$ git revert HEAD^
複製程式碼

上面這行程式碼就會增加一條新的 commit,它的內容和倒數第二個 commit 是相反的,從而和倒數第二個 commit 相互抵消,達到撤銷的效果。

revert完成之後,把新的 commitpush 上去,這個 commit 的內容就被撤銷了。它和前面所介紹的撤銷方式相比,最主要的區別是,這次改動只是被「反轉」了,並沒有在歷史中消失掉,你的歷史中會存在兩條 commit :一個原始 commit ,一個對它的反轉 commit

總結

git常用的也就這麼多,大家只要常用,記住它們不是啥大問題(當然我也要多記?),大家加油!

宣告:

本文所有文字純手打,遠端相關中的revert命令參考了掘金小冊扔物線大佬創作的小冊,其餘部分都是原創!碼字不易,舉起小手點個贊,你的贊就是作者最大的寫作動力

文中如果出現錯誤,請大家在評論區指正,我會及時修改!

祝大家五一假期玩的愉快!

相關文章