Git 學習筆記
這篇是初學 Git 時期草率寫下的筆記,主要目的是幫助自己能快速查找指令。
環境安裝
在進入正題之前,必須先根據電腦的作業系統安裝 Git 的環境,安裝成功後在 Git 資料夾中會有 “Git Bash” 的應用程式,可以透過它來操作 Git 指令;或是使用自己習慣的終端機也可以。
終端機基本指令
使用 Git 時,通常還會搭配一些終端機的基本指令去輔助操作,常用的指令如下:
移動到指定目錄
指令:cd 資料夾路徑
除了直接輸入路徑,也可以直接將資料夾拖曳至終端機視窗中。
展開當前目錄
指令:ls
列出當前目錄的所有檔案。
回前一層目錄
指令:cd ..
從當前位置回到前一層目錄。
回到根目錄
指令:cd\
直接移動到根目錄。
新增資料夾
指令:mkdir 資料夾名稱
在當前目錄下建立一個資料夾。
新增檔案
指令:touch 檔案名稱.檔案類型
在當前目錄建立一個檔案。
刪除檔案
指令:rm 檔案名稱.檔案類型
刪除當前目錄中指定檔案,若要刪除指定資料夾(含內容所有檔案)可輸入 rm -r 資料夾名稱
。
Git 版本檢視
環境安裝完成後開啟終端機,嘗試輸入指令 $ git version
,如果若出現 Git 版本訊息即表示安裝成功。
版本訊息範例:
1 |
|
Git 環境設定
使用 Git 進行版本控制時,每一個更新紀錄的更新人、更新時間以及部分的內容都會被記錄;因此在開始使用 Git 之前,需要先設定一些基本的資訊。
設定使用者暱稱
指令:$ git config --global user.name "使用者暱稱"
設定使用者信箱
指令:$ git config --global user.email "使用者信箱"
查看設定值
指令:$ git config --list
Git 常用指令
Git 基本操作流程示意圖:
Git 操作方式會根據不同情境而有所差異,但是運作原理相同。
建立本地端儲存庫
指令:$ git init
儲存庫(Repositiory)是用來存放一個專案所有檔案的資料夾;建立方式只需要開啟終端機,並以任意資料夾作為根目錄並輸入上述指令即可。
以檔名為 Project 的資料夾為例,建立成功後會顯示以下訊息:
1 |
|
此外也可以開啟該資料夾,查看根目錄是否多出一個 .git 的資料夾,它主要是用於監控與紀錄資料夾內檔案的所有變動;通常 .git 資料夾預設會隱藏,可以從資料夾上方列的 “檢視” 開啟隱藏的項目。
檢視狀態
指令:$ git status
查看工作目錄與暫存區的檔案是否有變動;可得知哪些檔案被修改,哪些檔案尚未被 Git 追蹤。
以 Project(本地端儲存庫)為例,輸入指令時顯示以下訊息,表示尚未做任何檔案新增或編輯:
1 |
|
加入暫存區
指令:$ git add .
工作目錄有新增或編輯的檔案時,可以輸入上述指令將檔案加入暫存區(索引),並等待提交成一次新的版本。
新增檔案 index.html 在 Project 資料夾中,並輸入指令 $ git status
查看狀態時顯示以下訊息:
1 |
|
訊息顯示偵測到尚未追蹤的檔案 index.html,此時可以輸入上述指令將檔案加入暫存區。
檔案加入暫存區後,輸入 $ git status
查看狀態時顯示以下訊息:
1 |
|
補充說明:
使用指令 $ git status
查詢狀態時,如果是工作目錄新增的檔案,狀態會是 Untracked files
,表示尚未加入暫存區追蹤;但如果是暫存區已存在,後續再進行修改的檔案,狀態會是 Changes not staged for commit
,並且檔案前面會標註 modified
,表示該檔案已被編輯,需要再次加入暫存區等待提交。
下列為檔案在不同狀態下所表示的意思:
1 |
|
提交更新(Commit)
指令:$ git commit -m "提交內容敘述"
將暫存區的檔案提交一次新的版本紀錄。
以下為成功提交暫存區的檔案 index.html 後顯示的訊息:
1 |
|
提交暫存區的檔案後,輸入 $ git status
查看狀態時顯示以下訊息,表示沒有更動需要提交,並且目前工作目錄乾淨,完全沒有檔案新增、修改或刪除。
1 |
|
查詢提交紀錄
指令:$ git log
列出過去幾筆的提交紀錄。
以下為提交紀錄的顯示內容範例:
1 |
|
顯示的筆數較多時,按下鍵盤 q 即可返回原內容。
忽略檔案
不希望某些檔案被 Git 追蹤時,可以建立一個 .gitignore 檔案,透過編輯器開啟檔案後,輸入希望被忽略的檔案名稱和檔案類型並儲存即可;需要注意的是 .gitignore 檔案本身不會被忽略。
被忽略檔案的輸入格式分別為下列幾種類型:
忽略單一檔案:輸入格式:
檔案名稱.檔案類型
忽略檔案類型:輸入格式:
*.檔案類型
忽略單一資料夾:輸入格式:
資料夾名稱/
還原(Reset)
開始介紹 $ git reset
相關指令之前,需要先理解 Reset 會使用到的三種參數模式,如下所示:
--mixed
(預設模式):暫存區的檔案會被丟回工作目錄,但是原本工作目錄的檔案不會被影響。--soft
:移除 commit 節點,但是暫存區與工作目錄的檔案皆不會被影響。--hard
:移除 commit 節點、工作目錄與暫存區所有檔案。
補充說明:
^
符號代表要往回還原的版本次數,HEAD^
代表往回一個版本,也可以使用 ~
加上數字來代替 ^
符號的數目,@
符號可以用來代表 HEAD
;以 HEAD^^
為例,可以改成 HEAD~2
,或 @~2
。
還原暫存區單一檔案回工作目錄
指令:$ git reset HEAD 檔案名稱
還原暫存區所有檔案回工作目錄
指令:$ git reset HEAD
還原單一檔案內容
指令:$ git checkout 檔案名稱.檔案類型
指定檔案內容還原回最後一次提交的狀態。
還原工作目錄與暫存區
指令:$ git reset --hard
當前工作目錄與暫存區,皆還原回最後一次提交時的狀態。
需要注意空的資料夾本身會被 git 忽略,因此不會被指令還原;但是資料夾內有存在檔案時,就會被 git 追蹤並還原。
移除最新的提交節點
指令:$ git reset HEAD^ --hard
除了移除最新的節點之外,當前暫存區的檔案也會被移除,但是當前工作目錄的檔案不受影響。
還原被移除的最新提交節點
指令:$ git reset ORIG_HEAD --hard
還原指令 $ git reset --hard HEAD^
移除的節點,並移除當前暫存區的檔案,但是當前工作目錄不受影響。
補充說明:
指令中的 ORIG_HEAD
是當使用者在執行一些較危險的指令(merge
、rebase
、reset
…)時,當前 HEAD 的檔案狀態會事先存放的地方,隨時可以還原。
除了上述方法,也可以使用以下指令來還原狀態:
1 |
|
需要注意被刪除的節點無法透過 $ git log
來查詢,查詢的方式可以使用指令 $ git reflog
來檢視歷史的狀態紀錄。
移除最新的提交節點並保留檔案狀態
指令:$ git reset HEAD^ --soft
可以理解成沒有執行最後一次的提交動作。
修改最新提交節點的描述
指令:$ git commit --amend -m "修改描述"
修改當前分支最新一次的提交描述。
追加檔案到最新的提交節點
指令:$ git commit --amend --no-edit
執行指令時如果未加上 --no-edit
參數,會跳出 Vim 編輯視窗。
分支
分支(branch)是開發者在團隊協作一個專案時,會需要使用到的 Git 架構內容;可以理解成將當前儲存庫的所有檔案複製一份,而這兩個版本可以獨立進行檔案新增、編輯與修改。這樣的好處是檔案的內容如果需要做更動,就可以先移動到另一個分支動作,同時也不用擔心影響到原本的檔案狀態。
以下列出常見分支名稱與主要用途:
- master(預設分支):用來合併 develop,合併時才會產生提交節點。
- develop(開發分支):用來合併 feature 分支,合併時才會產生提交節點。
- feature:用來開發功能、修改錯誤。
進入分支之前,需要先對 HEAD 指標有些概念,可以把它理解成當前分支上的所在位置;資料夾路徑可以看到目前 HEAD 的指向,如下圖所示:
1 |
|
檢視當前所有分支
指令:$ git branch
查詢目前本地端儲存庫的所有分支。
以 Project(本地端儲存庫)為例,輸入指令後顯示以下訊息,表示目前本地端有兩個分支,分別為 develop 與 master,而符號 *
表示當前 HEAD 正指向的分支。
1 |
|
移動 HEAD 到指定提交節點
指令:$ git checkout SHA-1前4碼
用來查看某一次的 commit 內容;而 SHA-1 值可透過 $ git log
查詢,如下所示:
1 |
|
接著輸入指令 $ git checkout ce9d
就能夠移動 HEAD 到這次 commit 節點,如果要回到原本位置,只需要輸入 $ git checkout 當前分支名稱
即可。
建立分支
指令:$ git branch 分支名稱
建立一個新的分支,但是 HEAD 的指向不變。
切換當前分支
指令:$ git checkout 分支名稱
移動 HEAD 到指定分支的最後一次提交節點。
合併分支 - 快轉模式(Fast-Forward)
指令:$ git merge 合併的分支名稱
快轉模式下,兩分支合併後路線重疊,並且不會產生額外的提交節點。
兩分支合併之前,如果最後提交節點都在同一個位置,合併時就會產生快轉模式(Fast - Forward),如下圖所示:
已知合併前的圖中,feature 分支比 master 分支多了兩次提交節點,但是 master 並沒有新增自己的節點,所以 master 分支的檔案在 feature 分支也都有,可以理解成 feature 分支只是 master 分支未來的版本而已,因此進行合併後,master 分支與 feature 分支會重疊,並且不會產生額外的合併節點,這種合併模式稱為 “快轉模式(Fast - Forward)”。
合併分支 - 關閉快轉模式
指令:$ git merge 合併的分支名稱 –no-ff
非快轉模式下,兩分支合併後會產生額外的提交節點。
下圖為加上參數 --no-ff
關閉快轉模式的例子:
圖中合併前的狀態前面的案例相同,因此在正常情況下合併兩分支就會產生快轉模式;但是也可以在合併時加上參數 --no-ff
來關閉快轉模式,如此一來,兩分支在合併後不但不會重疊,並且會額外產生新的提交節點。
補充說明:
兩分支在非快轉模式下進行合併時,可能會跳出以下訊息,表示需要輸入合併的原因;此時可以按下 i 進入輸入模式,接著將黃色文字的部分改成合併的簡單敘述(同 commit 訊息),輸入完畢後再按下 Esc 退出輸入模式,最後在底部輸入 :wq
即可完成合併並回到原來的畫面。
將當前分支合併到指定分支前
指令: $ git rebase 要合併的分支名稱
複製當前分支所有的提交節點,合併在指定的分支前面。
需要注意複製的提交節點會重新產生個別的 SHA-1,與原先的節點彼此並不相同,而原先的節點會隨著時間被 Git 機制回收。
補充說明:
使用 rebase
合併後,無法透過 $ git reset HEAD^
還原回合併前的狀態,而是會還原到前一個節點上;如果要還原回合併前的狀態,可以使用指令 $ git reset ORIG_HEAD --hard
。
下列圖片為兩分支在使用 rebase
合併時,可能產生的衝突:
合併時顯示上述訊息,表示檔案內容有衝突,此時可以開啟編輯器查看衝突的部分,以下圖為例:
確認完衝突的檔案內容後,只需要在終端機再次將檔案加入暫存區,接著輸入以下指令再次嘗試合併即可。
1 |
|
指定提交節點合併到當前分支前
指令: $ git cherry-pick SHA-1 SHA-1
複製指定的單一或數個提交節點,合併在當前分支前面。
以下圖為例,嘗試將 feature 分支的 add style 與 add js 兩個合併節點,合併在 master 分支前面:
可以從 sourcetree 介面中的右側看到每個節點的 SHA-1,在取得 add style 與 add js 兩個節點的值後,在 master 分支執行以下指令,即可複製被指定的兩個節點,並合併在當前分支前面。
1 |
|
如果希望被複製過來的節點不要直接進行合併,可以在指令後方加上參數 --no-commit
,如下所示:
1 |
|
此時被複製過來的節點會被拆除,並將節點的檔案加入暫存區,也可以透過 $ git status
查詢狀態,會發現暫存區目前有兩個檔案等待提交,如下所示:
1 |
|
確認檔案沒問題後,就可以進行提交,結果如下圖所示:
標籤(Tag)
開發專案過程中,會因為檔案不斷新增、刪除或修改而增加許多提交節點,雖然彼此都有獨自的版本描述,但是這樣很難去區分彼此之間的重要程度,如不同時間點的上線版本;因此為了有效區別,可以使用標籤相關指令。
補充說明:
標籤和分支都是指向某一個提交節點的指標,但是兩者的差別在於標籤只會指向固定的提交節點,而分支會隨著提交的增加而移動到最新的節點。
新增標籤
指令:$ git tag 標籤名稱
在當前位置新增一個標籤,可使用指令 $ git tag
來查詢標籤。
新增標示標籤
指令:$ git tag -am "標示內容" 標籤名稱
在當前位置新增一個標籤,並加入詳細的敘述,可以使用指令 $ git tag -n
來檢視標籤的詳細內容。
刪除標籤
指令:$ git tag -d 標籤名稱
可以將標籤想像成一張貼紙,撕掉並不會影響提交的檔案狀態。
移動到指定標籤位置
指令:$ git checkout 標籤名稱
移動 HEAD 的位置到指定標籤上查看檔案狀態,輸入 $ git checkout 分支名稱
即可回到原本內容。
暫存(Stash)
團隊開發專案的過程中,常常會開發到一半出現突發狀況要處理,其中一種作法是,先將目前的工作內容加入暫存區並提交,解決突發狀況後,再透過指令 $ git reset --soft HEAD^
刪除最後一次的提交節點,並還原提交前的所有狀態;另外一種做法則是透過 $ git stash
相關指令來暫存檔案狀態。
補充說明:
暫存(stash)和暫存區(Staging Area)兩者屬於不同的概念。
暫存當前的檔案狀態
指令:$ git stash
暫存當前工作目錄已被追蹤與暫存區(Staging Area)的檔案狀態,暫存後無法透過 $ git status
查詢檔案。
檢視暫存列表
指令:$ git stash list
透過指令 $ git stash
暫存的檔案可以使用上述指令來查詢,以下為查詢結果範例:
1 |
|
還原暫存的檔案狀態
指令:$ git stash pop
將暫存的檔案狀態還原到當前分支上,有搬運檔案的功能。
清除最新暫存
指令:$ git stash drop
刪除暫存列表最新的暫存紀錄,並無法還原。
清除全部暫存
指令:$ git stash clear
刪除暫存列表所有的暫存紀錄,並無法還原。
遠端儲存庫操作指令
本篇內容主要是在著重講述 Git 的基本操作,因此先不討論遠端儲存庫的建立方式與相關內容。
連結遠端儲存庫
指令:$ git remote add origin 遠端儲存庫網址
指令中的 origin
為遠端儲存庫的預設名稱;實務上通常會有多個儲存庫,如正式主機與測試主機;使用者可根據儲存庫用途來自訂名稱。
查詢遠端儲存庫
指令:$ git remote
查詢與本地端連結的遠端儲存庫的名稱;加入參數 -v
可以查詢詳細名稱與路徑。
複製遠端儲存庫
指令:$ git clone 遠端儲存庫網址
複製遠端資料到本地端資料夾,並建立工作目錄與本地端儲存庫(.git 資料夾),在指令後方加上 -b 遠端分支名稱
可以指定要複製的遠端分支。
補充說明:
上述指令通常會在本地端尚未存在遠端的資料的形況下執行;而後續本地端的資料更新都是透過 $ git pull
相關指令來操作。
推送本地端分支到遠端分支
指令:$ git push 遠端儲存庫名稱 遠端分支名稱
與本地端連結的遠端儲存庫如果有一個以上,在推送的時候要注意遠端儲存庫名稱,是否與要推送的遠端儲存庫相同,避免推送到錯誤的遠端。
補充說明:
第一次在推送時,如果在指令中加入參數 -u
,Git 就會記錄這次的推送行為,後續在推送本地端資料回遠端時,只需要輸入指令 $ git push
即可,但是也會遇到無法推送的情形,這部分會在 $ git pull
的部分說明。
1 |
|
變更遠端儲存庫名稱
指令:$ git remote rename 原儲存庫名稱 修改後名稱
預設的遠端儲存庫名稱為 origin
。
複製遠端儲存庫分支與本地端分支合併
指令:$ git pull 遠端儲存庫名稱 遠端分支名稱
團隊協作開發專案時,因為每個人的進度不同,會需要不定時更新遠端的資料回本地端;與 $ git clone
不同的是,$ git pull
是使用在本地端已經存在遠端的資料,但是需要更新檔案進度時。
推送本地端資料回遠端前,如果遠端資料已更新,本地端在推送時就會出現以下衝突訊息:
此時需要使用 $ git pull
先將遠端最新的資料更新(複製)到本地端,在複製遠端資料時會跳出以下訊息,表示需要將遠端資料與本地端進行合併。
從上述行為可得知,指令 $ git pull
做的事情是將遠端分支複製一份到本地端,再直接進行合併的動作。
複製遠端儲存庫分支與本地端分支等待合併
指令:$ git fetch 遠端儲存庫名稱 遠端分支名稱
與 $ git pull
不同的是,使用 $ git fetch
取得的遠端最新檔案會產生一個 FETCH_HEAD,表示遠端分支的最新狀態 遠端儲存庫名稱/遠端儲存庫分支
與 遠端儲存庫名稱/HEAD
,並額外產生提交節點在本地端當前分支前面,使用者檢查後再決定是否要與本地端分支合併,合併指令如下:
1 |
|
從上述行為可得知,$ git pull
做的動作相當於 $ git fetch
加上 $ git merge
。
參考資料
如何使用 –amend 追加檔案
Fast-Forward 快轉模式詳細介紹
Git Stash 詳細使用方式
Git Reset 使用模式
使用 Git Rebase 合併
Git Fetch 詳細介紹