①②②Git 版本控制入門(4)

Beginning Git: Ep. 9 ~ 10— Branching,Merging

Min
14 min readJan 10, 2024

接續上一篇:

線上課程資源:

以下跟著課程實做用 zsh 練習 git。

Ep. 9 Branching

What is Commit?

在講 branch 之前,先討論一下究竟什麼是 commit?

Commit 除了紀錄專案當下長的樣子,裡面有什麼內容之外, 還會包含一些 metadata,像是作者、日期、email 等等。重要的是,Commit 還包含對其 parent 的引用。這些種種全包裹在 Git repository 中,使用 SHA-1(Secure Hash Algorithm 1) 的形式保存。

因為每個 commit 都是獨一無二的,使用 hash 可以很簡單的識別每一個 commit。

This is a Branch

Branch 是關聯著特定 commit 的標籤,非常靈活高效。Branch 是包含著 SHA-1 的檔案。當創建越多的 commit,此標籤跟著往前,當在 branch 上創建新 commit 時更新。

預設當我們創建一個 Git repository 時,Git 創建一個 branch 給我們,命名為 master branch。

接著將練習創建一個 Branch,並將任何今建立的東西放在之上,而不是原先的 Branch。接著學習如何刪除 Branch。

使用 branch tool 創建一個新的 branch:

git branch myBranch

創建出來的 myBranch 被建立在 .git/refs/heads/ 中,使用 cat 查詢他的 SHA-1 hash:

cat .git/refs/heads/myBranch

使用 git log --oneline -1 查詢最近一次 commit 的紀錄:

git log --oneline -1

可以看到跟剛剛的 branch 一樣是 3c4df66 開頭,代表是相同的 hash:

使用 git branch 查看所有的 branch:

git branch
目前只有 master 跟 myBranch,而目前在 master 上

git checkout 切換分支並更新工作目錄:

git checkout myBranch
顯示目前不在 master 而在 myBranch 上

再次 git branch ,發現星號變色的 branch 已從 master 換到 myBranch:

git status 確認目前在 myBranch 分支上,並且沒有東西需要 commit:

想要切換回 master ,一樣使用 git checkout

git checkout master
回到 master

如果想要刪除 branch,使用 git branch -d 分支名稱

git branch -d myBranch

git branch 檢查,只剩 master:

ls .git/refs/heads 看 Heads 資料夾的內容,只剩下 master:

目前使用的 local repo,是從 fork 來的 remote 的 repo clone 下來的。

local repo 知道自己是 remote repo 的分支。如果想開始在 remote 分支工作,必須先 checkout 一個新的 local branch,用來追蹤 remote branch。

當在 local branch 創造 commit 時, Git 知道需要將他們 push 到特定的 remote branch 中。相同地,如果在 remote branch 創建新 commit,它也知道應該將這些新 commit 附加到哪一個 local branch 上。

看看目前所有的 branch,包含 remote branch:

git branch --all

發現我比講者 Sam 少了一個 remote:

自己先在 local 增加一個分支 clickbait,再使用 git push -u origin clickbait 將之 push 到 remote 中,並將 local 的 分支刪除:

OK 了繼續看影片…

創建一個可以追蹤 remote branch 的新 local branch:

git checkout --track origin/clickbait

查看包含 remote branch 的所有 branch,並顯示詳細 commit 資訊:

git branch --all -v

看到目前在 local 的 clickbait 上,並且跟 remote 的 clickbait 有一樣的 hash:

用 git status 可看到目前在 clickbait 上,且這分支是從最新的 origin/clickbait 建立的。

使用 git log --oneline --graph 顯示 ASCII 格式的 commit 資訊:

git checkout clickbait Git 會自動生成一個追蹤 remote clickbait 的 local clickbait:

如果刪除一個 branch 會因此失去一個 Commit,Git 不會讓我們刪除這個 branch。失去 Commit 代表我們不再有可以存取那個 commit 的 reference,也就是一個代表那個 commit 的 branch 。

所以這次的挑戰就是刪除一個其實會將 commit 一起刪掉的 branch。四個步驟:

  1. checkout master
  2. 新建一個 branch,命名為 myBranch,check it out
  3. 更改 readme file 並 commit 它
  4. 回到 master 並刪除 myBranch

今日挑戰

git checkout master

git checkout -b myBranch 創建一個新的 myBranch 並立即切換到該分支:

git checkout -b myBranch

使用 vim README.md 在 README 中添加新的一行:

git add README.mdgit commit -m “Added one line”

中間依照指示去更新了資訊

git checkout master 切換回 master:

git log — all — oneline — graph — decorate 看見最上方在 myBranch 多了一個 Commit:

使用 git branch -d myBranch 嘗試刪除 myBranch:

失敗,因為 Git 認為我們會失去剛剛產生的 commit。但我們真的想刪除,因此將 d 改為大寫 D,git branch -D myBranch

git branch -D 分支名稱

成功刪除:

再用 git log — all — oneline — graph — decorate 檢查一次,最上面一行的確被刪掉了:

Ep. 9 重點 git 指令

git branch 名稱     創建新的 branch
git log --oneline -數字 查詢最近幾次 commit 的紀錄
git branch 查看所有的 branch
git checkout 切換分支並更新工作目錄
git branch -d 分支名稱 刪除 branch
git branch --all 查看包含 remote branch 的所有 branch
git checkout --track (remote branch 的位置) 創建一個可以追蹤 remote branch 的新 local branch
git branch --all -v 查看包含 remote branch 的所有 branch,並顯示詳細 commit 資訊
git checkout -b 名稱 創建新的 branch 並立即切換到該分支
git branch -D 分支名稱 強制刪除 branch

Ep. 10 Merging

將兩個 branch 結合在一起,稱為 Merge。Merge是將一個 branch 的更改加入到另一個 branch(通常是 master)的過程。

Three Way Merge

當 Git 在處理 Merge 時,只會看三個 commit,從主分支開始分出分支的 commit,主分支的最後一個 commit,與分支的最後一個 commit,去創建一個 merge commit。

Merge Conflict

當兩個人用不同的方式編輯了同一行程式,Git 不知道怎麼處理時,稱為 merge conflict。這支影片不會處理這個。先從 merge 分支開始。

git checkout clickbait 切換到 clickbait

git log 看一下想要 merge 的 commit:

git checkout master 回到 master:

git merge clickbait merge 分支 clickbait 與當前分支 Master :

git merge 分支名稱

此時進入到一個 vim 模式,輸入跟 merge commit 相關的訊息

git log --oneline --graph --decorate 看到分支在最上層合併了!

使用 cat articles/clickbait_ideas.md 顯示 md 檔案的內容:

因為合併好了,所以 branch 可以刪掉了。使用 git branch -d clickbait 刪除分支。

Fast Forward Merge

當從 master 產生 Branch 1 之後, master 在此期間都沒有新的 commit,因此直接把兩個分支 merge 在 Branch 1 最新的 commit 上,稱為 fast forward merge。

這個做法像是直接把標籤移動到 Branch 1,但不會留下 merge commit。

實做:

在 master 之下新建立一個 branch,先確定自己位於 master,使用 git checkout -b 新建一個分支 readme_improvements 並移動過去:

vim README.md 打開 README.md 檔案,添加第三行文字:

git add README.mdgit commit -m”Adding request for action to the readme” commit 剛剛的更動。

使用 git checkout master 回到 master:

git log — oneline — graph — decorate — all 看到 Adding 這一句話直接坐在剛剛 merge clickbait 之上:

merge 大家 git merge readme_improvements

看到第二行標示 Fast-forward

再次 git log --oneline --graph --decorate --all ,發現只是把第二行的 master 搬上來到第一行 readme 變動的地方而已,並沒有創建一個新的 merge commit。這就是 fast forward merge。

今日挑戰

使用原本可以 fast forward merge,但我們不 fast forward merge ,而是創建一個 Merge commit。步驟:

  1. 回到 readme_improvements 分支
  2. 在 readme file 中的結尾加上一個簽名
  3. commit 改變
  4. merge 到 master 中,但不要 fast forward merge。看看 log。刪掉分支。

git checkout readme_improvements 回到分支 readme_improvements,vim README.md 編輯內容:

git add README.mdgit commit -m “Adding a signature” commit 剛剛的變化。

git checkout master 回到 master:

git merge --no-ff readme_improvements,要求不使用 fast forward merge 完成合併:

git merge --no-ff readme_improvements

直接跳到文字編輯內,寫下 commit 訊息:

儲存後退出

git log — oneline — graph — decorate 這樣的 merge commit 就能被紀錄:

Ep. 10 重點 git 指令

git merge 分支名稱     將分支與當前分支 merge
git merge --no-ff 分支名稱 將分支與當前分支 merge,不使用 fast forward merge

謝謝收看,下一章往 syncing local repository with a remote 前進:

--

--