Git 入門 (三):分支 (branch)、下載遠端儲存庫 (clone)
為什麼要用分支?
多人協作時,不可能都在 master分支 上更動程式碼,通常會另外開分支來做測試或開發,藉此不影響正式主機分支。
branch 非常不佔空間。它們只是一個指向某個 commit 的 reference,就這麼簡單。使用 branch 其實就是在說:「我想要包含這一次的 commit 以及它的所有 parent 的 commit。」
分支常用指令:branch、checkout、reset
開發情境:我有一個正式主機 master 分支,有一個開發分支 develop。
- 新增分支:
git branch 分支名稱
- 查看有哪些分支:
git branch
- 切換分支 (將 HEAD 指向分支):
git checkout 分支名稱
- 回頭觀看版本內容 (將 HEAD 指向 commit 版本):
git checkout commit編號
- 返回最新的版本:
git checkout master(分支名稱)
- 還原上個版本:
git reset HEAD^
- 將特定 commit 貼上新分支:
git branch 新分支名稱 commit編號
- 將特定 commit 貼上舊分支 (移動分支標籤):
git branch -f 舊分支名稱 commit編號
checkout 與 reset 的差異
git checkout
將 HEAD 移動到特定位置,但是不對檔案做更動。也不移動分支標籤。
git reset
將 HEAD 移動到特定位置,但是依照 --soft
--mixed
--hard
指令,對檔案做更動:退回索引區、退回工作區、檔案都放棄。如果 HEAD 和分支黏在一起的時候,分支標籤會跟著 HEAD 一起移動。
checkout HEAD^
如下圖 HEAD 原本在 815b5bc(new branch) 這個 commit,當我下了 git checkout HEAD^
,HEAD 會移動到 4e77317(add h1),並出現如下文字:
Previous HEAD position was 815b5bc new branch
HEAD is now at 4e77317 add h1
reset HEAD^ --hard
如果 HEAD 原本在 815b5bc(new branch) 這個 commit,當我下了 git reset HEAD^ --hard
,HEAD 會移動到 4e77317(add h1),並出現如下文字:
HEAD is now at 4e77317 add h1
圖雖然看起來一樣,但是 git 背後做的動作並不一樣。因為 reset 是危險動作,git 會把 HEAD 的狀態存放在 ORIG_HEAD 的檔案夾,讓你隨時可以跳回危險動作之前的狀態。
reset HEAD^ (- -mixed)
如果 HEAD 原本在 815b5bc(new branch) 這個 commit,當我下了 git reset HEAD^
,HEAD 會移動到 4e77317(add h1),並出現如下文字:
Unstaged changes after reset:
M index.html
圖中可以看到多了一個 uncommitted changes 的線,它是 815b5bc(new branch) 的工作區 (Working area) 版本。
modified index.html, index2.html and index3.html 還沒加入索引區。
reset HEAD^ --soft
如果 HEAD 原本在 815b5bc(new branch) 這個 commit,當我下了 git reset HEAD^ --soft
,HEAD 會移動到 4e77317(add h1),沒有出現文字說明。
圖中可以看到多了一個 uncommitted changes 的線,它是 815b5bc(new branch) 的索引區 (Staging area) 版本。
合併分支、快轉機制
通常會以舊的 commit 為基底 (git checkout 分支名稱)
,去合併新的編輯過的 commit。(merge 新branch 到 master)
先輸入 git checkout master
,再輸入 git merge dev
。
- 合併分支 (快轉):
git merge 分支名稱
- 取消快轉:
git merge 分支名稱 --no-ff
- 觀看線圖:
git log --oneline --graph
- 還原合併前狀態:
git reset ORIG_HEAD --hard
- 刪除已經合併的分支:
git branch -d 分支名稱
- 強制刪除未合併的分支:
git branch -D 分支名稱
還原到危險動作前的狀態
當你在做一些比較「危險」的操作 (例如像:merge、rebase 或 reset 之類的),Git 就會把 HEAD 的狀態存放在 ORIG_HEAD 的檔案夾,讓你隨時可以跳回危險動作之前的狀態。
- 還原 reset 前狀態:
git reset ORIG_HEAD --hard
、git reset commit編號 --hard
雖然 git reflog 指令也可以查到相關資訊,但 reflog 的資料比較雜一點,這個 ORIG_HEAD 會更方便的讓你找到最近的一次危險動作之前的 SHA-1 值。
ORIG_HEAD 是什麼東西?
【狀況題】不小心使用 hard 模式 Reset 了某個 Commit,救得回來嗎?
下載遠端儲存庫 (clone)
- 下載遠端儲存庫:
git clone 儲存庫網址
clone 和 gitHub 上的 Download ZIP 是完全不同的東西,一開始不知道的時候,踩了一個大坑。
clone 會將檔案和遠端的儲存庫一並取下來。而 Download ZIP 只會將檔案取下來。
所以這時你想要 push 上遠端的儲存庫時,必須先在本地端初始化一個儲存庫,然後執行 commit,然而你的本地端儲存庫和遠端儲存庫裡面的 commit 歷史不同,因此會造成衝突,無法 push 上去。
參考資料:
六角學院 -「Git 分支 (branch)」線上講義
六角學院 -「Git 分支中階教學」線上講義
Git 入門 系列文
Git 入門 (一):介紹和基本指令
Git 入門 (二):遠端操作 (使用 GitHub 的伺服器)、檔案狀態與還原
Git 入門 (三):分支 (branch)、下載遠端儲存庫 (clone) ← 你在這~
Git 入門 (四):取得遠端新檔案並合併 (fetch + merge = pull)、衝突 (conflict)