前言
Git簡介
實用主義
深入探索
總結
參考資料
Git簡介
Git
是一種分散式版本控制系統,它可以不受網路連線的限制,加上其它眾多優點,目前已經成為程式開發人員做專案版本管理時的首選,非開發人員也可以用
Git
來做自己的文件版本管理工具。
大概是大二的時候開始接觸和使用 Git ,從一開始的零接觸到現在的重度依賴,真是感嘆
Git
的強大。
Git
的api很多,但其實平時專案中90%的需求都只需要用到幾個基本的功能即可,所以本文將從
實用主義
和
深入探索
2個方面去談談如何在專案中使用
Git
,一般來說,看完
實用主義
這一節就可以開始在專案中動手用。
“
說明:本文的操作都是基於 Mac 系統
實用主義
準備階段
進入 Git官網 下載合適你的安裝包, 安裝好
Git
後,開啟命令列工具,進入工作資料夾(
為了便於理解我們在系統桌面上演示
),建立一個新的demo資料夾。
進入 Github網站 註冊一個賬號並登入,進入 我的部落格,點選
Clone or download
,再點選
Use HTTPS
,複製專案地址
https://github。com/gafish/gafish。github。com。git
備用。
再回到命令列工具,一切就緒,接下來進入本文的重點。
常用操作
所謂實用主義,就是掌握了以下知識就可以玩轉
Git
,輕鬆應對90%以上的需求。以下是實用主義型的Git命令列表,先大致看一下
git clone
git config
git branch
git checkout
git status
git add
git commit
git push
git pull
git log
git tag
接下來,將透過對 我的部落格 倉庫進行例項操作,講解如何使用
Git
拉取程式碼到提交程式碼的整個流程。
git clone
“
從git伺服器拉取程式碼
git clone https://github。com/gafish/gafish。github。com。git
程式碼下載完成後在當前資料夾中會有一個
gafish。github。com
的目錄,透過
cd gafish。github。com
命令進入目錄。
git config
“
配置開發者使用者名稱和郵箱
git config user。name gafishgit config user。email gafish@qqqq。com
每次程式碼提交的時候都會生成一條提交記錄,其中會包含當前配置的使用者名稱和郵箱。
git branch
“
建立、重新命名、檢視、刪除專案分支,透過
Git
做專案開發時,一般都是在開發分支中進行,開發完成後合併分支到主幹。
git branch daily/0。0。0
建立一個名為
daily/0。0。0
的日常開發分支,分支名只要不包括特殊字元即可。
git branch -m daily/0。0。0 daily/0。0。1
如果覺得之前的分支名不合適,可以為新建的分支重新命名,重新命名分支名為
daily/0。0。1
git branch
透過不帶引數的branch命令可以檢視當前專案分支列表
git branch -d daily/0。0。1
如果分支已經完成使命則可以透過
-d
引數將分支刪除,這裡為了繼續下一步操作,暫不執行刪除操作
git checkout
“
切換分支
git checkout daily/0。0。1
切換到
daily/0。0。1
分支,後續的操作將在這個分支上進行
git status
“
檢視檔案變動狀態
透過任何你喜歡的編輯器對專案中的
README。md
檔案做一些改動,儲存。
git status
透過
git status
命令可以看到檔案當前狀態
Changes not staged for commit:
(
改動檔案未提交到暫存區
)
On branch daily/0。0。1Changes not staged for commit: (use “git add
git add
“
新增檔案變動到暫存區
git add README。md
透過指定檔名
README。md
可以將該檔案新增到暫存區,如果想新增所有檔案可用
git add 。
命令,這時候可透過
git status
看到檔案當前狀態
Changes to be committed:
(
檔案已提交到暫存區
)
On branch daily/0。0。1Changes to be committed: (use “git reset HEAD
git commit
“
提交檔案變動到版本庫
git commit -m ‘這裡寫提交原因’
透過
-m
引數可直接在命令列裡輸入提交描述文字
git push
“
將本地的程式碼改動推送到伺服器
git push origin daily/0。0。1
origin
指代的是當前的git伺服器地址,這行命令的意思是把
daily/0。0。1
分支推送到伺服器,當看到命令列返回如下字元表示推送成功了。
Counting objects: 3, done。Delta compression using up to 8 threads。Compressing objects: 100% (2/2), done。Writing objects: 100% (3/3), 267 bytes | 0 bytes/s, done。Total 3 (delta 1), reused 0 (delta 0)remote: Resolving deltas: 100% (1/1), completed with 1 local objects。To https://github。com/gafish/gafish。github。com。git * [new branch] daily/0。0。1 -> daily/0。0。1
現在我們回到Github網站的專案首頁,點選
Branch:master
下拉按鈕,就會看到剛才推送的
daily/00。1
分支了
git pull
“
將伺服器上的最新程式碼拉取到本地
git pull origin daily/0。0。1
如果其它專案成員對專案做了改動並推送到伺服器,我們需要將最新的改動更新到本地,這裡我們來模擬一下這種情況。
進入Github網站的專案首頁,再進入
daily/0。0。1
分支,線上對
README。md
檔案做一些修改並儲存,然後在命令中執行以上命令,它將把剛才在線修改的部分拉取到本地,用編輯器開啟
README。md
,你會發現檔案已經跟線上的內容同步了。
如果線上程式碼做了變動,而你本地的程式碼也有變動,拉取的程式碼就有可能會跟你本地的改動衝突,一般情況下
Git
會自動處理這種衝突合併,但如果改動的是同一行,那就需要手動來合併程式碼,編輯檔案,儲存最新的改動,再透過
git add 。
和
git commit -m ‘xxx’
來提交合並。
git log
“
檢視版本提交記錄
git log
透過以上命令,我們可以檢視整個專案的版本提交記錄,它裡面包含了
提交人
、
日期
、
提交原因
等資訊,得到的結果如下:
commit c334730f8dba5096c54c8ac04fdc2b31ede7107aAuthor: gafish
提交記錄可能會非常多,按
J
鍵往下翻,按
K
鍵往上翻,按
Q
鍵退出檢視
git tag
“
為專案標記里程碑
git tag publish/0。0。1git push origin publish/0。0。1
當我們完成某個功能需求準備釋出上線時,應該將此次完整的專案程式碼做個標記,並將這個標記好的版本釋出到線上,這裡我們以
publish/0。0。1
為標記名併發布,當看到命令列返回如下內容則表示釋出成功了
Total 0 (delta 0), reused 0 (delta 0)To https://github。com/gafish/gafish。github。com。git * [new tag] publish/0。0。1 -> publish/0。0。1
。gitignore
“
設定哪些內容不需要推送到伺服器,這是一個配置檔案
touch 。gitignore
。gitignore
不是
Git
命令,而在專案中的一個檔案,透過設定
。gitignore
的內容告訴
Git
哪些檔案應該被忽略不需要推送到伺服器,透過以上命令可以建立一個
。gitignore
檔案,並在編輯器中開啟檔案,每一行代表一個要忽略的檔案或目錄,如:
demo。htmlbuild/
以上內容的意思是
Git
將忽略
demo。html
檔案 和
build/
目錄,這些內容不會被推送到伺服器上
小結
透過掌握以上這些基本命令就可以在專案中開始用起來了,如果追求實用,那關於
Git
的學習就可以到此結束了,偶爾遇到的問題也基本上透過
也能找到答案,如果想深入探索
Git
的高階功能,那就繼續往下看
深入探索
部分。
深入探索
基本概念
工作區( Working Directory )
就是你在電腦裡能看到的目錄,比如上文中的
gafish。github。com
資料夾就是一個工作區
本地版本庫( 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
透過輸入序列號或首字母可以選擇相應的功能,具體的功能解釋如下:
status
:功能上和
git add -i
相似,沒什麼鳥用
update
:詳見下方
git add -u
revert
:把已經新增到暫存區的檔案從暫存區剔除,其操作方式和
update
類似
add untracked
:可以把新增的檔案新增到暫存區,其操作方式和
update
類似
patch
:詳見下方
git add -p
diff
:比較暫存區檔案和本地版本庫的差異,其操作方式和
update
類似
quit
:退出
git add -i
命令系統
help
:檢視幫助資訊
git add -p
直接進入互動命令中最有用的
patch
模式
這是互動命令中最有用的模式,其操作方式和
update
類似,選擇後
Git
會顯示這些檔案的當前內容與本地版本庫中的差異,然後您可以自己決定是否新增這些修改到暫存區,在命令列
Stage deletion [y,n,q,a,d,/,?]?
後輸入
y,n,q,a,d,/,?
其中一項選擇操作方式,具體功能解釋如下:
y:接受修改
n:忽略修改
q:退出當前命令
a:新增修改
d:放棄修改
/:透過正則表示式匹配修改內容
?:檢視幫助資訊
git add -u
直接進入互動命令中的
update
模式
它會先列出工作區
修改
或
刪除
的檔案列表,
新增
的檔案不會被顯示,在命令列
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
“
將其它分支合併到當前分支
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 create09eb9a97ad632d0825be1ece361936d1d0bdb5c7$ git stash store 09eb9a97ad632d0825be1ece361936d1d0bdb5c7$ git stash liststash@{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/gafish。github。com。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/demo。git demo
將
demo
倉庫新增為子模組
git submodule update demo
更新子模組
demo
git gc
“
執行Git的垃圾回收功能,清理冗餘的歷史快照
git archive
“
將加了tag的某個版本打包提取
git archive -v ——format=zip v0。1 > v0。1。zip
——formatzip-vv0。1
感謝閱讀!如果你覺得文章寫的對你有幫助的話,大家可以轉發關注支援一下!