Git探祕:深入探索(2/2)
概念
通過上篇文章,初步接觸Git的朋友應該已經對Git有所瞭解了,既然你已經開啟了這篇文章,說明你對深入瞭解Git有強烈的慾望,那就跟著我一起先來深入瞭解一下Git相關的概念。
工作區(Working Directory)
就是你在電腦裡能看到的目錄,比如上文中的 reading-ist 資料夾就是一個工作區
本地版本庫(Local Repository)
工作區有一個隱藏目錄.git,這個不算工作區,而是Git的版本庫。
暫存區(stage)
本地版本庫裡存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區,還有Git為我們自動建立的第一個分支 master,以及指向master的一個指標叫 HEAD。
遠端版本庫(Remote Repository)
一般指的是git伺服器上所對應的倉庫,本文的示例所在的github倉庫就是一個遠端版本庫
工作區、暫存區、本地版本庫、遠端版本庫之間幾個常用的git操作流程如下圖所示:
分支 (Branch)
分支是為了將修改記錄的整個流程分開儲存,讓分開的分支不受其它分支的影響,所以在同一個資料庫裡可以同時進行多個不同的修改
主分支(Master)
前面提到過 master 是git為我們自動建立的第一個分支,也叫主分支,其它分支開發完成後都要合併到master
標籤(Tag)
標籤是用於標記特定的點或提交的歷史,通常會用來標記釋出版本的名稱或版本號(如:publish/0.0.1),雖然標籤看起來有點像分支,但打上標籤的提交是固定的,不能隨意的改動,參見上圖中的1.0 / 2.0 / 3.0
HEAD
HEAD指向的就是當前分支的最新提交
以上概念瞭解的差不多,那就可以繼續往下看,下面將以具體的操作型別來講解Git的高階用法
操作檔案
git add
新增檔案到暫存區
git add -i
通過此命令將開啟互動式子命令系統,你將看到如下子命令
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
通過輸入序列號或首字母可以選擇相應的功能,具體的功能解釋如下:
1、status:功能上和 git add -i 相似,沒什麼鳥用
2、update:功能跟 git add -u 一樣,但它會先列出工作區 修改 或 刪除 的檔案列表,新增 的檔案不會被顯示,在命令列 Update>> 後輸入相應的列表序列號表示選中該項,回車繼續選擇,如果已選好,直接回車回到命令主介面
3、revert:把已經新增到暫存區的檔案從暫存區剔除,其操作方式和 update 類似
4、add untracked:可以把新增的檔案新增到暫存區,其操作方式和 update 類似
5、patch:詳見下方
6、diff:比較暫存區檔案和本地版本庫的差異,其操作方式和 update 類似
7、quit:退出git add -i命令系統
8、help:檢視幫助資訊
patch
這是互動命令中最有用的模式,其操作方式和 update 類似,選擇後Git會顯示這些檔案的當前內容與本地版本庫中的差異,然後您可以自己決定是否新增這些修改到暫存區,在命令列 Stage deletion [y,n,q,a,d,/,?]? 後輸入 y,n,q,a,d,/,? 其中一項選擇操作方式,具體功能解釋如下:
- y:接受修改
- n:忽略修改
- q:退出當前命令
- a:新增修改
- d:放棄修改
- /:通過正規表示式匹配修改內容
- ?:檢視幫助資訊
git add -p
直接進入互動命令中最有用的patch模式
git add -u
直接進入互動命令中的update模式
git add –ignore-removal .
新增工作區 修改 或新增 的檔案列表, 刪除 的檔案不會被新增
git commit
把暫存區的檔案提交到本地版本庫
git commit -m `第一行提交原因` -m `第二行提交原因`
不開啟編輯器,直接在命令列中輸入多行提交原因
git commit -am `提交原因`
將工作區 修改 或刪除 的檔案提交到本地版本庫, 新增 的檔案不會被提交
git commit –amend -m `提交原因`
修改最新一條提交記錄的提交原因
git commit -C HEAD
將當前檔案改動提交到 HEAD 或當前分支的歷史ID
git mv
移動或重新命名檔案、目錄
git mv a.md b.md -f
將 a.md 重新命名為 b.md ,同時新增變動到暫存區,加-f引數可以強制重新命名,相比用 mv a.md b.md 命令省去了 git add 操作
git rm
從工作區和暫存區移除檔案
git rm b.md
從工作區和暫存區移除檔案 b.md ,同時新增變動到暫存區,相比用 rm b.md 命令省去了 git add 操作
git rm src/ -r
允許從工作區和暫存區移除目錄
git status
git status -s
以簡短方式檢視工作區和暫存區檔案狀態,示例如下:
M demo.html
?? test.html
git status –ignored
檢視工作區和暫存區檔案狀態,包括被忽略的檔案
操作分支
git branch
檢視、建立、刪除分支
git branch -a
檢視本地版本庫和遠端版本庫上的分支列表
git branch -r
檢視遠端版本庫上的分支列表,加上 -d 引數可以刪除遠端版本庫上的分支
git branch -D
分支未提交到本地版本庫前強制刪除分支
git branch -vv
檢視帶有最後提交id、最近提交原因等資訊的本地版本庫分支列表
git merge
將其它分支合併到當前分支
A---B---C topic
/
D—E—F—G—H master
git merge –squash
將待合併分支上的commit合併成一個新的commit放入當前分支,適用於待合併分支的提交記錄不需要保留的情況
git merge –no-ff
預設情況下,Git執行”快進式合併”(fast-farward merge),會直接將Master分支指向Develop分支,使用–no-ff引數後,會執行正常合併,在Master分支上生成一個新節點,保證版本演進更清晰。
git merge –no-edit
在沒有衝突的情況下合併,不想手動編輯提交原因,而是用git自動生成的類似 Merge branch `test` 的文字直接提交
git checkout
切換分支
git checkout -b daily/0.0.1
建立 daily/0.0.1 分支,同時切換到這個新建立的分支
git checkout HEAD demo.html
從本地版本庫的 HEAD(也可以是提交ID、分支名、Tag名) 歷史中檢出 demo.html 覆蓋當前工作區的檔案,如果省略 HEAD則是從暫存區檢出
git checkout –orphan new_branch
這個命令會建立一個全新的,完全沒有歷史記錄的新分支,但當前源分支上所有的最新檔案都還在,真是強迫症患者的福音,但這個新分支必須做一次 git commit 操作後才會真正成為一個新分支。
git checkout -p other_branch
這個命令主要用來比較兩個分支間的差異內容,並提供互動式的介面來選擇進一步的操作,這個命令不僅可以比較兩個分支間的差異,還可以比較單個檔案的差異。
git stash
在Git的棧中儲存當前修改或刪除的工作進度,當你在一個分支裡做某項功能開發時,接到通知把昨天已經測試完沒問題的程式碼釋出到線上,但這時你已經在這個分支里加入了其它未提交的程式碼,這個時候就可以把這些未提交的程式碼存到棧裡。
git stash
將未提交的檔案儲存到Git棧中
git stash list
檢視棧中儲存的列表
git stash show stash@{0}
顯示棧中其中一條記錄
git stash drop stash@{0}
移除棧中其中一條記錄
git stash pop
從Git棧中檢出最新儲存的一條記錄,並將它從棧中移除
git stash apply stash@{0}
從Git棧中檢出其中一條記錄,但不從棧中移除
git stash branch new_banch
把當前棧中最近一次記錄檢出並建立一個新分支
git stash clear
清空棧裡的所有記錄
git stash create
為當前修改或刪除的檔案建立一個自定義的棧並返回一個ID,此時並未真正儲存到棧裡
git stash store xxxxxx
將 create 方法裡返回的ID放到 store 後面,此時在棧裡真正建立了一個記錄,但當前修改或刪除的檔案並未從工作區移除
$ git stash create
09eb9a97ad632d0825be1ece361936d1d0bdb5c7
$ git stash store 09eb9a97ad632d0825be1ece361936d1d0bdb5c7
$ git stash list
stash@{0}: Created via "git stash store".
操作歷史
git log
顯示提交歷史記錄
git log -p
顯示帶提交差異對比的歷史記錄
git log demo.html
顯示 demo.html 檔案的歷史記錄
git log –since=”2 weeks ago”
顯示2周前開始到現在的歷史記錄,其它時間可以類推
git log –before=”2 weeks ago”
顯示截止到2周前的歷史記錄,其它時間可以類推
git log -10
顯示最近10條歷史記錄
git log f5f630a..HEAD
顯示從提交ID f5f630a 到 HEAD 之間的記錄,HEAD可以為空或其它提交ID
git log –pretty=oneline
在一行中輸出簡短的歷史記錄
git log –pretty=format:”%h”
格式化輸出歷史記錄
git用各種placeholder來決定各種顯示內容,我挑幾個常用的顯示如下:
- %H: commit hash
- %h: 縮短的commit hash
- %T: tree hash
- %t: 縮短的 tree hash
- %P: parent hashes
- %p: 縮短的 parent hashes
- %an: 作者名字
- %aN: mailmap的作者名
- %ae: 作者郵箱
- %ad: 日期 (–date= 制定的格式)
- %ar: 日期, 相對格式(1 day ago)
- %cn: 提交者名字
- %ce: 提交者 email
- %cd: 提交日期 (–date= 制定的格式)
- %cr: 提交日期, 相對格式(1 day ago)
- %d: ref名稱
- %s: commit資訊標題
- %b: commit資訊內容
- %n: 換行
git cherry-pick
合併分支的一條或幾條提交記錄到當前分支末梢
git cherry-pick 170a305
合併提交ID 170a305 到當前分支末梢
git reset
將當前的分支重設(reset)到指定的或者HEAD
git reset –mixed
–mixed 是不帶引數時的預設引數,它退回到某個版本,保留檔案內容,回退提交歷史
git reset –soft
暫存區和工作區中的內容不作任何改變,僅僅把HEAD指向
git reset –hard
自從以來在工作區中的任何改變都被丟棄,並把HEAD指向
git rebase
重新定義分支的版本庫狀態
git rebase branch_name
合併分支,這跟 merge 很像,但還是有本質區別,看下圖:
合併過程中可能需要先解決衝突,然後執行 git rebase –continue
git rebase -i HEAD~~
開啟文字編輯器,將看到從HEAD到HEAD~~的提交如下
pick 9a54fd4 新增commit的說明
pick 0d4a808 新增pull的說明
# Rebase 326fc9f..0d4a808 onto d286baa
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit`s log message
# x, exec = run command (the rest of the line) using shell
#
將第一行的“pick”改成Commands中所列出來的命令,然後儲存並退出,所對應的修改將會生效。
如果移動提交記錄的順序,將改變歷史記錄中的排序。
git revert
撤銷某次操作,此次操作之前和之後的commit和history都會保留,並且把這次撤銷作為一次最新的提交
git revert HEAD
撤銷前一次提交操作
git revert HEAD –no-edit
撤銷前一次提交操作,並以預設的 Revert “xxx” 為提交原因
git revert -n HEAD
需要撤銷多次操作的時候加 -n 引數,這樣不會每次撤銷操作都提交,而是等所有撤銷都完成後一起提交
git diff
檢視工作區、暫存區、本地版本庫之間的檔案差異,用一張圖來解釋
git diff –stat
通過 –stat 引數可以檢視變更統計資料
test.md | 1 -
1 file changed, 1 deletion(-)
git reflog
reflog 可以檢視所有分支的所有操作記錄(包括commit和reset的操作、已經被刪除的commit記錄,跟 git log 的區別在於它不能檢視已經刪除了的commit記錄
遠端版本庫連線
如果在GitHub專案初始化之前,檔案已經存在於本地目錄中,那可以在本地初始化本地版本庫,再將本地版本庫跟遠端版本庫連線起來
git init
在本地目錄內部會生成.git資料夾
git remote
git remote -v
不帶引數,列出已經存在的遠端分支,加上 -v 列出詳細資訊,在每一個名字後面列出其遠端url
git remote add origin https://github.com/gafish/reading-list.git
新增一個新的遠端倉庫,指定一個名字,以便引用後面帶的URL
git fetch
將遠端版本庫的更新取回到本地版本庫
git fetch origin daily/0.0.1
預設情況下,git fetch取回所有分支的更新。如果只想取回特定分支的更新,可以指定分支名。
問題排查
git blame
檢視檔案每行程式碼塊的歷史資訊
git blame -L 1,10 demo.html
擷取 demo.html 檔案1-10行歷史資訊
git bisect
二分查詢歷史記錄,排查BUG
git bisect start
開始二分查詢
git bisect bad
標記當前二分提交ID為有問題的點
git bisect good
標記當前二分提交ID為沒問題的點
git bisect reset
查到有問題的提交ID後回到原分支
更多操作
git submodule
通過 Git 子模組可以跟蹤外部版本庫,它允許在某一版本庫中再儲存另一版本庫,並且能夠保持2個版本庫完全獨立
git submodule add https://github.com/gafish/movie-list.git movie
將 movie-list 倉庫新增為子模組
git submodule update movie
更新子模組 movie
git gc
執行Git的垃圾回收功能,清理冗餘的歷史快照
git archive
將加了tag的某個版本打包提取
git archive -v –format=zip v0.1 > v0.1.zip
–format表示打包的格式,如zip,-v表示對應的tag名,後面跟的是tag名,如v0.1。
總結
本文只是對Git的所有功能中的部分實用功能做了一次探祕,Git非常強大,還有很多功能有待我們去發現,限於本文篇幅,我們就此打住吧,預知更多好用功能,請聽下回分解。
歡迎大家關注我的微信公眾號,將不定期推送前端開發相關原創文章
相關文章
- 探索JAVA系列(一)探祕Java反射(Reflect)Java反射
- 深入理解 RxJava2:揭祕 subscribeOn(3)RxJava
- 現代瀏覽器探祕(part2):導航瀏覽器
- 全景探祕遊戲設計藝術(2):遊戲機制遊戲設計
- Git教程2Git
- (譯)窺探Blocks(2)BloC
- 室友的Zip加密檔案探祕,Python解決Zip加密檔案探索祕密!加密Python
- 探祕WKWebViewWebView
- Git——分支管理(2)Git
- 【深入學習JVM 02】HotSpot虛擬機器物件探祕JVMHotSpot虛擬機物件
- 深入理解JVM(③)——之HotSpot虛擬機器物件探祕JVMHotSpot虛擬機物件
- 深入理解 RxJava2:Scheduler(2)RxJava
- Node 深入Stream(2)
- 深入剖析ConcurrentHashMap(2)HashMap
- 深入一些!巴貝爾的地下城探祕之旅
- Web列印探祕Web
- Cglib proxy探祕CGLib
- 探祕intern()方法
- git探索Git
- 深入理解h2和r2dbc-h2
- 深入淺出:HTTP/2HTTP
- TaskContinuationsOptions.ExecuteSynchronously探祕
- 深度探祕.NET 5.0
- 探祕Java9Java
- Ubuntu下Git的使用2UbuntuGit
- 深入虛幻5引擎:Epic次世代視覺奇觀探祕視覺
- Go語言HTTP/2探險之旅GoHTTP
- 深入探討 UndefinedUndefined
- 深入探討HBASE
- Promise深入探索Promise
- Java 隨機數探祕Java隨機
- 【NIO系列】——之TCP探祕TCP
- Git原理與高階使用(2)Git
- Git(標籤、分支和合並)2Git
- DC-2-WordPress-git提權Git
- Git學習2 --- Git安裝詳細步驟Git
- 探索奧祕~閉包
- 【vue深入學習第1章】探索 Vue 2 的生命週期:從建立到銷燬Vue
- 深入學習 Redis(2):持久化Redis持久化