專題 - 使用 git 進行版本控制 - 分支與合併
上次更新日期 2020/10/03
使用 git 一段時間後,你可能需要做某些測試,此時,你可能需要將你的專案做個分支來開發新的檔案或者是測試。 等到這個分支使用過一段時間,確定是可行的方案之後,就可以考慮將分支融合到原本的專案當中!完成這次的開發!
關於 git 檔案的追蹤與否: .gitignore 功能
- 關於 git 對於專案目錄底下的檔案分類:
基本上, git 對於該專案目錄底下的檔案追蹤,主要分為三個群組,大概是:
- 被追蹤:就是被 git add type1file 的檔案群,這些檔案在變更時, git 會提醒開發者,該檔案可能需要傳送紀錄才好。 這也是專案開發最重要的部份;
- 被忽略:很多檔案可能是開發過程中會產生的目標檔案 (object file),這些檔案不需要被追蹤,此時,可以透過 .gitignore 的檔案, 紀錄可被忽略的檔案群,這樣,許多不應該被 git 管理的檔名,就可以略過而不被查詢了。
- 不被追蹤:就是在專案目錄下,且不屬於其他兩群的檔案。基本上,這些檔案還是在『 git status 』時,會被 git 告知說, 是否需要被追蹤囉。
- 模擬網頁伺服器的環境中,如果有提供用戶上傳資料時,可能會有暫存檔,這些暫存檔假設放置 cache 這個目錄下,
因此,我們想要忽略 cache 這個目錄,那該如何處理呢?可以這樣做:
# cd /var/www/html # git status On branch master nothing to commit, working tree clean # git ls-files index.html phpinfo.php server.php # mkdir cache # chown apache:apache cache # ll drwxr-xr-x. 2 apache apache 6 9月 24 04:55 cache -rw-r--r--. 1 root root 89 9月 4 00:27 index.html -rw-r--r--. 1 root root 21 9月 4 00:23 phpinfo.php -rw-r--r--. 1 root root 126 9月 24 00:14 server.php # touch cache/upload_{a,b,c}_{1,2,3}.o # ll cache -rw-r--r--. 1 root root 0 9月 24 04:57 upload_a_1.o -rw-r--r--. 1 root root 0 9月 24 04:57 upload_a_2.o .... -rw-r--r--. 1 root root 0 9月 24 04:57 upload_c_2.o -rw-r--r--. 1 root root 0 9月 24 04:57 upload_c_3.o # git status On branch master Untracked files: (use "git add <file>..." to include in what will be committed) cache/ nothing added to commit but untracked files present (use "git add" to track)
這個時候你就可以發現到 git 有注意到 cache/ 目錄的產生,而且裡面有好多檔案了。現在,如果我想要完整的忽略該目錄,基本上可以這樣做:# vim .gitignore cache/ # git status On branch master Untracked files: (use "git add <file>..." to include in what will be committed) .gitignore nothing added to commit but untracked files present (use "git add" to track)
你可以輕鬆的發現到,只剩下 .gitignore 這個可被忽略的檔案生成而已,那個要被忽略的 cache/ 目錄,就整個被忽略了! 這樣就不用在乎該目錄囉!接下來,將 .gitignore 加入追蹤列表,並且上傳到資料庫即可。# git add .gitignore # git commit -m 'add ignore file .gitignore' [master 723ea7f] add ignore file .gitignore 1 file changed, 1 insertion(+) create mode 100644 .gitignore # git status On branch master nothing to commit, working tree clean # git ls-files .gitignore index.html phpinfo.php server.php
此時,你的專案目錄裡面依舊會存在 cache 目錄,但是沒有被追蹤了!而且,你的 git status 會回傳你 tree clean 的情境喔!真好! - 忽略的追蹤檔 .gitignore 檔案格式:
初次接觸 .gitignore 時,大部分的人都會直接將檔名寫入。如果是非特定檔名,或者是需要萬用字元的檔名 (wildcard) 時, 例如使用 * 來代表 0 到無窮多個任意字元時,有些規則還是得要稍微注意的好:
萬用字元 使用格式 接受的檔名列表示範 # 或空白行 # example 其實就是註解,會被略過 /(斜線) /index.html index.html index.html index.html
hw/index.html
newclass/index.htmlcache/ cache (通常代表目錄名稱,連同內部檔案喔!) *(星號) index.* index.html
index.php
index.txt*index.html index.html
hw/index.html
newclass/index.html**(兩個星號) cache/** cache/ 底下的所有檔案,連同子目錄 **/cache hw/cache
newclass/cache
cache? index?.html index1.html
index2.htmlindex??.html index11.html
indexbb.html[a-z] (集合) *.[ot] main.o
check.t*.[0-9] main5.o
check3.t - 實做練習:
- 假定除了 cache 之外,你的網頁目錄當中的 tmp 也是個暫存目錄。請建立該目錄, 並在 tmp 底下隨意增加大約 3~5 個以上的檔案看看。
- 檢查看看你的 git 狀態,有沒有偵測到該子目錄呢?
- 在你的 .gitignore 裡面加入 tmp 的目錄忽略,然後再次的觀察一下狀態,有發現什麼現象?
- 若想要知道目前的目錄與之前的 git 狀態差別有多少,可以使用『 git diff 』檢查一下喔!就能知道哪個檔案修改了哪些東西。
- 請上傳最新的資料,同時加入 'add tmp/ ignore' 的訊息!
開始使用分支
基本上,除了多人共同開發的網路環境之外,在本機上面的 git 系統運作,大部分都是單人開發的環境。 那既然是單人開發的環境,幹麻需要分支?不都是我自己能夠處理的?那如此一來,透過 git 原本的版本控制不就好了? 搞個分支是要搞死自己?
不過,我們得要想到,有時候總是需要進行測試的吧?這個測試可能是會成功也可能是會失敗吧?如果成功的話, 就將程式碼留下來,這沒問題!那如果是失敗呢?怎麼去除?另外,在測試的途中,可能還會發現某些有趣的程式碼, 於是,你可能也會想要測試分支當中的分支。
此外的此外,有時候你只是想要解決一個問題,這個問題解決完畢之後,你可能就會將這個問題產生的過程資料全部銷毀! 但是最終解決問題的解答則要寫回主程式中,這可就得真的要使用分支了!即使是個人開發的環境, 你也是需要了解分支的應用,可以讓你管理你的程式碼,更加有效率!
- 分支的命名規則:
- 主線分支稱為 master:
基本上,你的主程式碼也是一個分支,當然,目前我們也只有這個分支的意思。而目前這個分支是最重要的, 所以, git 預設稱呼目前這個主線分支為 master。 - 建立分支的主要指令大致如下:
# git branch 新分支名稱 # git show-branch
branch 是分支的意思,透過上述的指令,就可以建立分支與觀察分支。那麼,分支的名稱是否該有規則? 是的,就跟變數設定很類似喔!分支的名稱不可以隨便亂取! - 分支名稱的命名規則:
- 分支名稱的開頭不可以是減號 (-)
- 分支名稱可以包含斜線 (/) ,例如 bugs/mybug ,但是結尾不能是斜線 (容易被誤判為目錄)
- 每個接在斜線後的第一個字元,不可以是小數點,例如 bugs/.mybug 就是錯誤的。
- 不能使用連續的兩個小數點 (..)
- 分支名稱內不可以用空白字元、不可以用 git 的特殊符號 ( ~, ^, :, ?, *, [ )、不可以用 ASCII 的控制字元。
- 基本上,保持良好的命名習慣,單純使用英文、數字與底線,搭配斜線分類,應該就能夠應付大部分的情境! 也不容易對 git 的系統運作產生問題!
- 主線分支稱為 master:
- 開始建立分支與開始應用分支:
- 在目前的狀態下,建立名為 hw/unit2 的分支,並且觀察分支狀態:
# git branch hw/unit2 # git branch hw/unit2 * master
建立了兩個分支,名稱如上,而目前的系統環境,使用的是 master 分支,就是帶有星號 (*) 的那個分支系統。 那麼如果我想要知道每個分支從哪邊來的呢? - 查看每個分支的狀態:
# git show-branch ! [hw/unit2] add tmp/ ignore * [master] add tmp/ ignore -- +* [hw/unit2] add tmp/ ignore 12 3
上面的結果可以透過兩個減號 (--) 分開來看,先看上半部的部份:- 上半部是目前所有分支的列表,基本上排序是由最新到最舊,每一個分支佔用一行。
- 從上而下,每個分支的狀態都會佔用自己的一個位置,例如 [hw/unit2] 佔用第 1 個位置,[master] 佔用第 2 個位置。
- 有星號的 (*) 那個,代表目前使用的分支。
- 第一個位置上為 + 號,代表 [hw/unit2] 在 [hw/unit2] 分之內
- 第二個位置上為 * 號,代表 [hw/unit2] 在 [master] 分支內,且目前正在應用中。
- 變更分支的應用 - 最好需要保持在 clean 的狀態來切換較佳:
# git status On branch master nothing to commit, working tree clean # git branch hw/unit2 * master # git checkout hw/unit2 Switched to branch 'hw/unit2' # git branch * hw/unit2 master
現在,開始來處理 hw/unit2 這個分支的許多動作!這個動作預計將進行:- 增加 unit2 目錄,並且在其中增加 index.html 的檔案,內容寫 class02 即可
- 修改 index.html 檔案,增加一條到 unit2 的連結即可。
# mkdir unit2 # echo class02 > unit2/index.html # vim index.html <ul> <li><a href='unit2'>第二章作業</a></li> </ul> # git status On branch hw/unit2 Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: index.html Untracked files: (use "git add <file>..." to include in what will be committed) unit2/ no changes added to commit (use "git add" and/or "git commit -a") <==用這個處理看看 # git commit -a -m 'add homework unit2' [hw/unit2 b6d2522] add homework unit2 1 file changed, 3 insertions(+) # git status On branch hw/unit2 Untracked files: (use "git add <file>..." to include in what will be committed) unit2/ nothing added to commit but untracked files present (use "git add" to track) // 看起來,還是需要手動將目錄加入控制監視才行啊! # git add unit2/ # git commit -a -m 'add homework unit2' [hw/unit2 1b03199] add homework unit2 1 file changed, 1 insertion(+) create mode 100644 unit2/index.html # git status On branch hw/unit2 nothing to commit, working tree clean # git ls-files .gitignore index.html phpinfo.php server.php unit2/index.html # ll drwxr-xr-x. 2 apache apache 186 9月 24 04:57 cache -rw-r--r--. 1 root root 146 9月 28 00:20 index.html -rw-r--r--. 1 root root 21 9月 4 00:23 phpinfo.php -rw-r--r--. 1 root root 126 9月 24 00:14 server.php drwxr-xr-x. 2 root root 51 9月 24 05:32 tmp drwxr-xr-x. 2 root root 24 9月 28 00:20 unit2
- 切換回較早、較舊、與目前檔案狀態不同的分支,讓我們試圖回到 master 分支上面去看看:
// 觀察現有分支,並且切換到 master 上 # git branch * hw/unit2 master # git checkout master Switched to branch 'master' # git branch hw/unit2 * master # ll drwxr-xr-x. 2 apache apache 186 9月 24 04:57 cache -rw-r--r--. 1 root root 89 9月 28 00:41 index.html -rw-r--r--. 1 root root 21 9月 4 00:23 phpinfo.php -rw-r--r--. 1 root root 126 9月 24 00:14 server.php drwxr-xr-x. 2 root root 51 9月 24 05:32 tmp # cat index.html
不知道你會不會嚇一跳,因為 index.html 裡面新增的部份不見了,而新增加的 unit2 目錄也不見了! 怎麼會這樣呢?這是因為目前你的環境變這樣了:------ hw/unit2 ----> A / ----- master -----> B
我們剛剛做的動作在 A 點上面,但是你切換回 B 點的環境了!因此,所有在 B 與 A 之間的動作, 會全部被拿掉,而僅帶入 B 點的資料而已!所以,當然 index.html 以及 unit2/ 目錄就會被歸零復原! 也就是說,當你使用了切換分支的行為,你當下的目錄結構就會進行:- 預計使用的分支沒有,目前分支有的資料,將會被暫時移除
- 預計使用的分支有,目前分支沒有的資料,則會被加入到目前的目錄結果中。
- 在目前的狀態下,建立名為 hw/unit2 的分支,並且觀察分支狀態:
- 簡單的分支合併行為:
- 假設我們對於 hw/unit2 的開發已經完成,這個分支確實是正確運作的結果,因此,我們想要將這個分支開發的結果回歸到主線 (master) 上面,
這個時候我們可以這樣做:
// 先要確認目前是在 master 主線上,這樣才能夠合併其他分支喔! # git show-branch ! [hw/unit2] add homework unit2 * [master] add tmp/ ignore # 確實在主線上 -- + [hw/unit2] add homework unit2 # 最新的送交是在 add homework unit2 這個點上面 + [hw/unit2^] add homework unit2 +* [master] add tmp/ ignore // 開始進行合併的行為 # git merge hw/unit2 Updating a40d703..1b03199 Fast-forward index.html | 3 +++ unit2/index.html | 1 + 2 files changed, 4 insertions(+) create mode 100644 unit2/index.html # git show-branch ! [hw/unit2] add homework unit2 * [master] add homework unit2 -- +* [hw/unit2] add homework unit2 # git log // 就會看到將 hw/unit2 的送交 log 也通通加入回來了!
這時你就會發現,主線的資料跟 hw/unit2 是一模一樣的了!相當方便進行開發與彙整喔!
- 假設我們對於 hw/unit2 的開發已經完成,這個分支確實是正確運作的結果,因此,我們想要將這個分支開發的結果回歸到主線 (master) 上面,
這個時候我們可以這樣做:
- 實做練習:
- 建立名為 hw/unit5 的新的分支
- 切換到該新分支,並且依據剛剛的處理方案,建立名為 unit5 的目錄,建立名為 unit5/index.html 的檔案, 修改 index.html 的連結內容
- 確認 hw/unit5 分支的狀態是 clean 的!很重要喔!
- 確認一切無誤,將 hw/unit5 這個分支合併到 master 主線上面。
前一版次的分支應用
- 什麼情境產生了非新版資料的分支應用:
- 例如,目前是 2.0 版,但是有讀者說,他的 1.5 版次有繼續更新,所以你得要回去 1.5 版次的環境,然後根據讀者的說明, 重建與測試該環境的情境。
- 例如前面一小節的測試中,我們先寫了 unit2 與 unit5 這兩個作業,但是現在我們要回去 unit1 的作業環境, 以讓使用者比較有乾淨的測試環境來理解,而不是亂七八糟的存在。
- 從之前的舊版次增加分支的方式:
- 先找出尚未加入 hw/unit2 那個入口點,如下圖所示,找到 A 點的 log 旗標名稱:
------ hw/unit2 ------> B / \ ----- master -A----------------------C---> D
可以這樣做:# git log commit 1b0319971db9a8c2327a8283faf61498151dc0d6 (HEAD -> master, hw/unit2) Author: VBird Tsai <dmtsai@mail.ksu.edu.tw> Date: Mon Sep 28 00:18:09 2020 +0800 add homework unit2 .... commit a40d703f6c206f93ec409d93132a2ab4c1604c5f Author: VBird Tsai <dmtsai@mail.ksu.edu.tw> Date: Thu Sep 24 05:35:25 2020 +0800 add tmp/ ignore .... // 建立第一章 hw/unit1 的作業環境: # git branch hw/unit1 a40d7 # git branch hw/unit1 hw/unit2 * master # git show-branch ! [hw/unit1] add tmp/ ignore ! [hw/unit2] add homework unit2 * [master] add homework unit2 --- +* [hw/unit2] add homework unit2 +* [hw/unit2^] add homework unit2 ++* [hw/unit1] add tmp/ ignore
你會發現到,下半部的資料中,只有 hw/unit1 自己包含自己在內,其他兩個分支並沒有被包含在 hw/unit1 喔! 畢竟 hw/unit1 是回到之前的環境中,與新的 master, hw/unit2 比較,當然不可能包含呀!也就是, 舊的分支不太可能包含新的分支在內! - 切換到舊的環境去。事實上,你目前所在處有點像下圖的 E 點:
------ hw/unit2 ------> B / \ ----- master -A----------------------C---> D \ --- hw/unit1 ---> E
目前這個點應該是與 hw/unit2 完全無關!現在,讓我們來回到過去吧!# git checkout hw/unit1 Switched to branch 'hw/unit1' # ll drwxr-xr-x. 2 apache apache 186 9月 24 04:57 cache -rw-r--r--. 1 root root 89 9月 28 01:35 index.html -rw-r--r--. 1 root root 21 9月 4 00:23 phpinfo.php -rw-r--r--. 1 root root 126 9月 24 00:14 server.php drwxr-xr-x. 2 root root 51 9月 24 05:32 tmp
你會發現到,確實喔! unit2 也不見了! index.html 也回到原始狀態!好,讓我們來處理 unit1 的作業吧! - 在新的分支工作:
# git branch * hw/unit1 hw/unit2 master # mkdir unit1 # echo 'my class1 homework' > unit1/index.html # vim index.html <ul> <li><a href='unit1'>第一章作業</a></li> </ul> // 開始送交資料 # git add -A # git status On branch hw/unit1 Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: index.html new file: unit1/index.html # git commit -a -m 'add class1 homework' [hw/unit1 780235f] add class1 homework 2 files changed, 4 insertions(+) create mode 100644 unit1/index.html
- 先找出尚未加入 hw/unit2 那個入口點,如下圖所示,找到 A 點的 log 旗標名稱:
- 合併從舊版次建立的分支行為,可能導致的合併錯誤整理:
- 我們在 hw/unit1 當中有修改了 index.html 喔,但是這個檔案似乎在 hw/unit2 面有被合併了!
因此,這個檔案似乎有點衝突喔!以下圖來看, D 點與 E 點的 index.html 可能有點衝突的問題!
我們現在想做的,就是將 E 融合到 D 上面!
------ hw/unit2 ------> B / \ ----- master -A----------------------C--------> D \ / --- hw/unit1 ---> E---
- 舊版次合併的方式:其實跟一般合併相同而已:
// 先回到 master 主線分支 # git checkout master Switched to branch 'master' # git branch hw/unit1 hw/unit2 * master // 開始合併 hw/unit1 喔! # git merge hw/unit1 Auto-merging index.html CONFLICT (content): Merge conflict in index.html Automatic merge failed; fix conflicts and then commit the result. # git status On branch master You have unmerged paths. (fix conflicts and run "git commit") (use "git merge --abort" to abort the merge) Changes to be committed: new file: unit1/index.html Unmerged paths: (use "git add <file>..." to mark resolution) both modified: index.html
意思是說,大致上都合併成功了,但是 index.html 的合併失敗!因為有衝突啊!如果你查閱一下該檔案,就可以發現問題:# cat index.html <ul> <<<<<<< HEAD <li><a href='unit2'>第二章作業</a></li> ======= <li><a href='unit1'>第一章作業</a></li> >>>>>>> hw/unit1
- 放棄這次的合併:如果出於某些原因,你必須要回頭去查一查哪邊出問題,所以想要放棄這次的合併時,
可以這樣做:
# git merge --abort # cat index.html
這樣,系統就可以放棄合併了! - 將衝突解決,確認合併工作:這次,解決合併問題吧!
# git merge hw/unit1 Auto-merging index.html CONFLICT (content): Merge conflict in index.html Automatic merge failed; fix conflicts and then commit the result. # vim index.html <ul> <li><a href='unit2'>第二章作業</a></li> <li><a href='unit1'>第一章作業</a></li> </ul> // 改好之後,就在次的上傳合併資料吧! # git add index.html # git status On branch master All conflicts fixed but you are still merging. (use "git commit" to conclude merge) Changes to be committed: modified: index.html new file: unit1/index.html # git commit -a -m 'add homework class1 to master' [master 9b3ee0f] add homework class1 to master # git show-branch ! [hw/unit1] add class1 homework ! [hw/unit2] add homework unit2 * [master] add homework class1 to master --- - [master] add homework class1 to master <==合併送出的減號 (-) 出現了! + * [hw/unit1] add class1 homework +* [hw/unit2] add homework unit2 +* [hw/unit2^] add homework unit2 ++* [hw/unit1^] add tmp/ ignore
- 我們在 hw/unit1 當中有修改了 index.html 喔,但是這個檔案似乎在 hw/unit2 面有被合併了!
因此,這個檔案似乎有點衝突喔!以下圖來看, D 點與 E 點的 index.html 可能有點衝突的問題!
我們現在想做的,就是將 E 融合到 D 上面!
- 實做練習:
- 先確認目前使用的分支為 master 主線分支,而且確認 hw/unit5 那個習題已經完成!
- 建立名為 hw/unit3 的新的分支,且分支位置請選擇 hw/unit2 合併到 master 的那個時間點,亦即送交時間點必須要在 hw/unit5 合併之前的某個時段才行!
- 切換到該新分支,並且依據剛剛的處理方案,建立名為 unit3 的目錄,建立名為 unit3/index.html 的檔案, 修改 index.html 的連結內容
- 確認 hw/unit3 分支的狀態是 clean 的!很重要喔!
- 確認一切無誤,將 hw/unit3 這個分支合併到 master 主線上面,並且自行解決無法 merge 的檔案衝突問題!。
分支的刪除與標籤的製作
- 為什麼需要刪除分支:
有時候我們只是單純的要測試某個時間點產生的分支狀態,測試完畢之後,該分支的資料並不需要儲存, 所以,該分支的狀態就可以被捨棄的意思。另外,某些時刻我們的程式改寫好像有問題,可以用其他方法解決, 因此,該分支也能夠撤除。當然,已經確認沒問題且合併到主線分支上了,那麼該分支似乎也沒必要持續存在啊!
- 分支的新增:
# git log ..... commit 9b3ee0fb960dcabbe77f1f45868e04763b1c45e7 Merge: 1b03199 780235f Author: VBird Tsai <dmtsai@mail.ksu.edu.tw> Date: Mon Sep 28 02:02:21 2020 +0800 add homework class1 to master ..... # git branch hw/unit4 9b3ee # git branch hw/unit1 hw/unit2 hw/unit4 * master # git checkout hw/unit4 Switched to branch 'hw/unit4' # mkdir unit4 # echo "hehe" > unit4/index.html # git add -A # git commit -a -m 'add unit 4' [hw/unit4 e4ea47c] add unit 4 1 file changed, 1 insertion(+) create mode 100644 unit4/index.html
- 分支的變更與刪除:
# git checkout master Switched to branch 'master' # git branch hw/unit1 hw/unit2 hw/unit4 * master # git show-branch ! [hw/unit1] add class1 homework ! [hw/unit2] add homework unit2 ! [hw/unit4] add unit 4 * [master] add homework class1 to master ---- + [hw/unit4] add unit 4 -- [master] add homework class1 to master + +* [hw/unit1] add class1 homework ++* [hw/unit2] add homework unit2 ++* [hw/unit2^] add homework unit2 +++* [hw/unit1^] add tmp/ ignore # git branch -d hw/unit4 error: The branch 'hw/unit4' is not fully merged. If you are sure you want to delete it, run 'git branch -D hw/unit4'. # git branch -D hw/unit4 Deleted branch hw/unit4 (was e4ea47c). # git branch hw/unit1 hw/unit2 * master
- 標籤的製作:
- 為什麼要製作標籤 (Tag) 呢?通常原因是因為某個版本固定了,不再更動了,未來的變動則是掛上其他釋出版本。 例如 V1.0 釋出之後,可以將這個版本固定成為一個『標籤 (Tag) 』讓它不動這樣。說穿了,其實就是額外給個名稱, 讓操作使用這個專案的人,更清楚知道版本別這樣。
- 標籤的製作通常就是找一個送交的點,這個送交的點當然需要有點意義比較好。舉例來說,
我們將 hw/unit2 合併的那個點,可以視為第二單元已經完成的一個重要里程碑,因此,或許將它當成 v0.2 這樣的版本別!
來處理也可以的!實際作法有點像這樣:
# git log ..... commit 1b0319971db9a8c2327a8283faf61498151dc0d6 (hw/unit2) Author: VBird Tsai <dmtsai@mail.ksu.edu.tw> Date: Mon Sep 28 00:18:09 2020 +0800 add homework unit2 ..... # git tag -m "Tag version v 0.2" V0.2 1b0319 # git tag V0.2 # git log ..... commit 1b0319971db9a8c2327a8283faf61498151dc0d6 (tag: V0.2, hw/unit2) Author: VBird Tsai
很簡單的做了個標籤,未來可以輕鬆的找到我們的入口點,而不用持續分析不同的分支或送交點。請注意喔, 標籤可以用來取代分支的名稱喔!也就是說,未來如果你想要切換到 V0.2 版本的話,可以這樣做:Date: Mon Sep 28 00:18:09 2020 +0800 add homework unit2 ..... # git show V0.2 tag V0.2 Tagger: VBird Tsai <dmtsai@mail.ksu.edu.tw> Date: Mon Sep 28 06:24:40 2020 +0800 Tag version v 0.2 commit 1b0319971db9a8c2327a8283faf61498151dc0d6 (tag: V0.2, hw/unit2) Author: VBird Tsai <dmtsai@mail.ksu.edu.tw> Date: Mon Sep 28 00:18:09 2020 +0800 add homework unit2 diff --git a/unit2/index.html b/unit2/index.html new file mode 100644 index 0000000..d29f2cf --- /dev/null +++ b/unit2/index.html @@ -0,0 +1 @@ +class02 # git checkout V0.2
- 分析不同 commit 之間的檔案差異:
- 如果你想要知道兩次 commit 之間的檔案間的差異,除了前一章的 git cat-file -p flag 功能之外,其實也能夠透過簡易的 git diff 來處理!
基本上, git diff 可以列出該目錄底下與 clean 的狀態之間的檔案差異:
# cd /var/www/html # vim server.php echo 'Its OK'; # git diff diff --git a/server.php b/server.php index e29921d..510553b 100644 --- a/server.php +++ b/server.php @@ -2,5 +2,5 @@ diff --git a/server.php b/server.php index e29921d..510553b 100644 --- a/server.php +++ b/server.php @@ -2,5 +2,5 @@ foreach ( $_SERVER as $myindex => $myvalue ) { echo "index is " . $myindex . ", value is " . $myvalue . "\n"; } - + echo 'Its OK'; ?>
- 那如果你想要處理的是兩次 commit 之間的差異呢?依舊使用 git diff 進行喔!
# git log commit 9b3ee0fb960dcabbe77f1f45868e04763b1c45e7 (HEAD -> master) Merge: 1b03199 780235f Author: VBird Tsai <dmtsai@mail.ksu.edu.tw> Date: Mon Sep 28 02:02:21 2020 +0800 add homework class1 to master commit 780235faf99eb3eff46d5b8b59f567f6eb5c80ea (hw/unit1) Author: VBird Tsai <dmtsai@mail.ksu.edu.tw> Date: Mon Sep 28 01:41:49 2020 +0800 add class1 homework ...... commit a40d703f6c206f93ec409d93132a2ab4c1604c5f Author: VBird Tsai <dmtsai@mail.ksu.edu.tw> Date: Thu Sep 24 05:35:25 2020 +0800 add tmp/ ignore .... # git diff 78023 4a1c7e diff --git a/.gitignore b/.gitignore deleted file mode 100644 index a3ad08c..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -cache/ -tmp/ diff --git a/index.html b/index.html index c5bfaf2..0b51bc2 100644 --- a/index.html +++ b/index.html @@ -4,8 +4,5 @@ </head> <body> myname is XXX xxx -<ul> - <li><a href='unit1'>第一章作業</a></li> -</ul> </body> </html> diff --git a/unit1/index.html b/unit1/index.html deleted file mode 100644 index 59545fe..0000000 --- a/unit1/index.html +++ /dev/null @@ -1 +0,0 @@ -my class1 homework
也就是說,透過找到兩次 commit 的 flag 之後,加入到 git diff 後面即可分析囉! - 已經到最新的 up to date 功能:因為 git 會根據分支的結合方式,主動的判斷到底這個分支有沒有加入到你的分支中了。
因此,如果你的分支都沒有重新增加新資料,那麼,當你要重複合併分支時,git 就會主動告知,已經合併成功了!
而且是最新的合併啊!
# git show-branch ! [hw/unit1] add class1 homework ! [hw/unit2] add homework unit2 * [master] add homework class1 to master --- - [master] add homework class1 to master + * [hw/unit1] add class1 homework +* [hw/unit2] add homework unit2 +* [hw/unit2^] add homework unit2 ++* [hw/unit1^] add tmp/ ignore # git merge hw/unit2 Already up to date.
- 如果你想要知道兩次 commit 之間的檔案間的差異,除了前一章的 git cat-file -p flag 功能之外,其實也能夠透過簡易的 git diff 來處理!
基本上, git diff 可以列出該目錄底下與 clean 的狀態之間的檔案差異:
- 實做練習:
- 先確認目前使用的分支為 master 主線分支,而且確認 hw/unit3 那個習題已經完成!
- 確認 unit3 已經合併到 master 主線分支上。
- 將沒有用途的 hw/unit3 分支刪除
- 將 hw/unit3 合併的那一個送交點,設定標籤為 V0.3 版本。
- 將目前的環境回歸到 V0.3 的版本,進行簡單的目錄檔名檢查
- 回到原本的最新主線環境上。
參考資料
- O'REILLY、『版本控制使用 Git - 第二版』、碁峰出版社
- 專門介紹 .gitignore 應用:https://linuxize.com/post/gitignore-ignoring-files-in-git/
- 2020/09/27:經過假日的奮戰,終於將分支系統以及例題做了個比較好理解的簡單範例!
- 2020/10/03:僅增加了 git diff 的說明部份!