### GDSC NYUST x 資訊創客社 <br> ### 軟體開發工具入門讀書會 #### Git課程 <br> #### 2023/10/23 (Mon) 19:00 - 21:00 #### 講師:楊鈞元 Charles #### 本次課程影片: <img src="" height="200px"> --- ## 前言 ---- ### 軟體開發工具入門讀書會 ### VS Code & Node.js 課程 <br> 課程影片:[⚒️YouTube後製中]() 簡報連結:[🔗HackMD](https://hackmd.io/@GDSC-NYUST/SkiZJXPZ6/%2FkpG3SBCFQU6OPl-gK-R0eQ) ---- ### GDSC社課 ### Topic 1 - Class 3 Git & GitHub <br> 課程影片:[⚒️YouTube後製中]() 簡報連結:[🔗HackMD](https://hackmd.io/@GDSC-NYUST/rJKqKU1gp/%2FJzrJyqfBQhuR9t1Q7OX73w) --- ## 環境說明 ---- 以 Linux ( WSL ) 及 VS Code 進行 Git 管理 <br> 如何安裝WSL:[🔗Linux課程](https://youtu.be/8awPH5tUko8) ---- Ubuntu 預設即有Git Debian 可能會尚未安裝 ![](https://hackmd.io/_uploads/SkL25rQGT.png) ---- Debian / Ubuntu 系統安裝方式 ```= sudo apt update sudo apt install git ``` ![](https://hackmd.io/_uploads/Hybehrmfa.png) <br> 確認是否安裝成功 ```= git --version ``` --- ## 安裝VS Code Extension ---- - [Git Graph](https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph) ![](https://hackmd.io/_uploads/Syu2pBmMp.png) - [git-commit-plugin](https://marketplace.visualstudio.com/items?itemName=redjue.git-commit-plugin) ![](https://hackmd.io/_uploads/rkOkRrmza.png) ---- 修改自定義commit模板 ```= cd ~/.vscode-server/extensions/redjue.git-commit-plugin-1.2.1/out/config sudo rm -f commit-type.js && sudo wget https://github.com/Charles5277/git-commit-plugin/raw/main/__fix_config/commit-type.js --no-check-certificate sudo rm -f commit-detail.js && sudo wget https://github.com/Charles5277/git-commit-plugin/raw/main/__fix_config/commit-detail.js --no-check-certificate ``` --- ## Git Branch ---- 從2022/10開始 Github的預設分支主線由master改為main Git預設仍為master ( 未建立Branch直接進行Commit ) ![](https://hackmd.io/_uploads/r1Y-gI7fp.png) ---- ### 查看現有的分支 ```= git git branch -a ``` ---- 在git init後直接查看,不會有分支 ![](https://hackmd.io/_uploads/BJh3zUXGa.png) ---- ![](https://hackmd.io/_uploads/HJVZmI7MT.png) ---- ### 創建分支 使用 **`git branch <新分支名稱>`** 創建分支 這個新分支會以當前HEAD指到的位置作為起點 ```= git git branch dev git switch dev ``` <br> 或使用 **`git switch -c <新分支名稱>`** 可以直接在創建後同時將HEAD指過去 ```= git git switch -c main ``` <br> ``` *新增後尚未commit,也不會在git branch -a跟git graph中看到 ``` ---- #### 使用 Git Graph 創建分支 <br> 對指定commit右鍵新增分支 ||| |-|-| ![](https://hackmd.io/_uploads/ryZJctQM6.png) ---- #### 使用 Git Graph 創建分支 <br> 取名字 & 是否要順便移動過去 ||| |-|-| ![](https://hackmd.io/_uploads/ryFLcYXfa.png) ---- ### 更改分支名稱 **`git branch -m <舊分支名稱> <新分支名稱>`** ```= git git branch -m dev test ``` ---- #### 使用 Git Graph 更改分支名稱 ||| |-|-| ![](https://hackmd.io/_uploads/SyR5qtmzT.png) ![](https://hackmd.io/_uploads/r1GhcY7Ma.png) ---- ![](https://hackmd.io/_uploads/BkS-U8XGT.png) ![](https://hackmd.io/_uploads/rJdL8IXzT.png) ---- ### 刪除分支 ```= git // 一般刪除,若有未合併的節點會停下詢問,避免節點遺失 git branch -d <分支名稱> ``` ```= git // 強制刪除,無視節點遺失 // 但HEAD當前指的Branch用此方法也刪除不了 // 需要先移動到其他分支 git branch -D <分支名稱> ``` ---- #### 使用 Git Graph 刪除分支 ![](https://hackmd.io/_uploads/HkxLKK7zT.png) 詢問是否要強制刪除 ![](https://hackmd.io/_uploads/rkiuKF7fp.png) ---- ### 節點遺失 ( unreachable commits ) 若因為強制刪除導致節點遺失 我們稱這些節點為unreachable commits 即無法抵達的commits 後續會介紹如何救回這種節點 --- ## Git Switch ---- ### HEAD介紹 ---- Commit節點像是大富翁格子 每個Branch像是不同的角色棋子 但Branch會紀錄自己擁有的每一格紀錄 HEAD就是手指 | HEAD指dev | HEAD指main | HEAD指節點上| | --- | --- | --- | |![](https://hackmd.io/_uploads/By_9v8Xfp.png)|![](https://hackmd.io/_uploads/BkxawImM6.png)|![](https://hackmd.io/_uploads/BJPiuI7Ga.png)| |![](https://hackmd.io/_uploads/HJsswUXMp.png)|![](https://hackmd.io/_uploads/S1B0vI7Ga.png)|![](https://hackmd.io/_uploads/SkNeKImG6.png) ---- ### 移動HEAD ---- 使用 **`git switch <分支名稱>`** ```= git git switch dev git switch main ``` 使用 **`git switch -d <節點hash值>`** ```= git git switch -d 0b5d9580c43c05ac7513237aaaaf0abe5d24029c ``` ---- #### 如何取得節點的hash值 ```= git git log // 或者 git reflog ``` 透過以上兩個指令判斷 (後面會解釋) ---- #### 如何取得節點的hash值 直接透過Git Graph,最右側commit欄即為hash ![](https://hackmd.io/_uploads/r1LfnY7zp.png) ``` 大部分git指令提供這種長度的hash縮寫即可 ``` ---- #### 如何取得節點的hash值 <br> 針對某個commit右鍵,直接複製完整hash ![](https://hackmd.io/_uploads/SkXF3tXGa.png) ---- 使用 Git Graph ![](https://hackmd.io/_uploads/B1RsY87fp.png) ``` checkout有switch跟restore的功能 有些舊教學或套件會習慣使用checkout 只要看得懂,會使用即可 為了避免混淆,我們以switch跟restore分開示範 ``` ---- 使用 VS Code ||| |-|-| |![](https://hackmd.io/_uploads/S1D7oIQfT.png)|![](https://hackmd.io/_uploads/SknA5U7Gp.png)| ![](https://hackmd.io/_uploads/BkfY5LQfp.png) ---- #### 補充展示 [🔗HEAD指向commit跟branch的差別](https://hackmd.io/@GDSC-NYUST/rJKqKU1gp/%2FJzrJyqfBQhuR9t1Q7OX73w#HEAD%E6%8C%87%E5%90%91commit%E8%B7%9Fbranch%E7%9A%84%E5%B7%AE%E5%88%A5) --- ### Git Reflog ---- #### Reflog概念說明 Reflog紀錄所有變更(包含分支和 HEAD)的歷史 最常用於恢復意外刪除的分支或提交 或確認 Git 操作歷史是否如期 ---- #### git log與git reflog ![](https://hackmd.io/_uploads/SkIuCI7G6.png) ``` 最上面是最新的操作紀錄 越往下越舊,可透過方向鍵上下移動 按Q可以離開檢視 ``` ---- #### git graph查看詳情 ![](https://hackmd.io/_uploads/Bk1xyDmza.png) ---- #### 情境題 ![](https://hackmd.io/_uploads/S1iLkvXfa.png) ```= git git switch main git branch -D dev ``` ![](https://hackmd.io/_uploads/H1XI4D7z6.png) ![](https://hackmd.io/_uploads/rkGdVDmGa.png) ---- ```= git git reflog ``` ![](https://hackmd.io/_uploads/Bk2VBv7fa.png) 剛才先switch到main,才進行刪除 因此我們可以回到他之前的節點 ```= git git switch -d 6a89645 ``` ![](https://hackmd.io/_uploads/rkS_wwmzp.png) ![](https://hackmd.io/_uploads/B1sPDwmz6.png) ---- 再建立Branch指向這個commit ![](https://hackmd.io/_uploads/SJtcPvQGa.png) --- ### Git Merge ---- #### 指令展示 <br> [🔗Git Merge筆記](https://hackmd.io/JzrJyqfBQhuR9t1Q7OX73w#git-merge) [🔗線上練習Git Merge](https://learngitbranching.js.org/?locale=zh_TW) ---- #### 透過Git Graph ![](https://hackmd.io/_uploads/Bk-THFmMT.png) ---- #### 合併衝突 ![](https://hackmd.io/_uploads/SyoExtmz6.png) ---- 顯示衝突 ||| |-|-| |![](https://hackmd.io/_uploads/BJv8lFmGT.png)|![](https://hackmd.io/_uploads/HkZD-tXGp.png)| ---- 比較變更 ||| |-|-| ![](https://hackmd.io/_uploads/rkg_ltmM6.png) ``` *無法直接在此處修改 即將到來的變更: 如果指定的分支內容直接覆寫當前分支,這個檔案會受到怎樣的影響 ``` ---- 使用內嵌顯示 ||| |-|-| |![](https://hackmd.io/_uploads/S1bYlFmMa.png)|![](https://hackmd.io/_uploads/BJ6tetXz6.png)| ``` *無法直接在此處修改 ``` ---- 使用 **在合併編輯器中編輯** ||| |-|-| ![](https://hackmd.io/_uploads/S1F5-t7M6.png) ``` 傳入:唯讀,merge進來的分支,相較於共同parent帶來的變更 目前:唯讀,當前分支,相較於共同parent帶來的變更 結果:可編輯,預設為共同parent的狀態,會即時顯示預覽變更 ``` ---- 手動新增內容 ||| |-|-| |![](https://hackmd.io/_uploads/HJh9zKQza.png)|![](https://hackmd.io/_uploads/Sy5-7KXfT.png) | ---- 重設為基底 ||| |-|-| ![](https://hackmd.io/_uploads/HyPsXF7Ga.png) ---- 重設為基底 ||| |-|-| ![](https://hackmd.io/_uploads/rygBmtXMa.png) ``` 點擊重設為基底,會清空手動變更,讓你重新處理 *按了又想反悔,可以用Ctrl + Z ``` ---- 切換衝突點 ||| |-|-| ![](https://hackmd.io/_uploads/BybxVKmfT.png) ``` *利用上、下箭頭移動到其他衝突點 ``` ---- 完成衝突處理 ||| |-|-| ![](https://hackmd.io/_uploads/r1lNNFQG6.png) ``` 處理所有衝突,直到顯示變成0個剩餘衝突 ``` ---- 完成衝突處理 ||| |-|-| ![](https://hackmd.io/_uploads/BJGoEKQMp.png) ``` 點擊右下角完成合併 ``` ---- 中途想停止合併 ~~有內鬼,終止交易!~~ ```= git git merge --abort ``` --- ## Git Cherry-Pick ---- ![](https://hackmd.io/_uploads/B1INsYXzT.png) 使用 **`git cherry-pick <hash>`** ```= git git cherry-pick 5940b3432b84f25956aea26c41781443dfcd0731 ``` ``` 可以理解為跟merge一樣,但只合併一個指定的commit 一樣可能遇到衝突,一樣可以用 git cherry-pick --abort 中止操作 ``` ---- #### 搭配 Git Graph 針對commit直接右鍵選擇 ![](https://hackmd.io/_uploads/HyQEaYXMa.png) ![](https://hackmd.io/_uploads/By8upFQMp.png) ``` 由於時間有限,此處就不詳細展開Record Origin 以及No Commit的意義,大家可以自行嘗試,遇到問題在Discord提出 ``` ---- 更多補充 ``` git cherry-pick <start-hash>..<end-hash> > 將start到end的commit都擷取 git cherry-pick <hash> -e <target-branch> > 將指定commit單獨複製到指定分支上 (而非當前分支) git cherry-pick --no-commit <commit-hash> > 將指定的commit變更套用到當前stage區,而非直接套用提交 ``` <br> 延伸閱讀 [🔗Git Cherry Pick 的後遺症](https://blog.darkthread.net/blog/git-cherry-pick-cons/) --- ## Git Restore ---- ### 捨棄檔案變更 使用 **`git restore <file_name>`** ``` 將檔案的變更捨棄(只限定未放到stage區的workdir變更) 預設即為-W (worktree) 因此 git restore -W <file_name>的效果是一樣的 ``` 白話文👇 ![](https://hackmd.io/_uploads/ryWvbcmfT.png) ---- ### 取消 git add 使用 **`git restore -S <file_name>`** ``` 將檔案從stage區移回workdir(但內容變更不改變) 相當於取消git add ``` 白話文👇 ||| |-|-| |![](https://hackmd.io/_uploads/Skc3W5QMT.png)|![](https://hackmd.io/_uploads/SkcRWcXG6.png) | ---- ### 捨棄單一檔案的變更 使用 **`git restore <檔名>`** 白話文👇 ||| |-|-| ![](https://hackmd.io/_uploads/rJBoX57fT.png) ---- ### 捨棄所有檔案的變更 使用 **`git restore .`** 白話文👇 ||| |-|-| ![](https://hackmd.io/_uploads/Byj949XMa.png) ``` 指令要達到"捨棄所有檔案",包含未追蹤的檔案較為複雜,也較危險 此處就不展示,若使用VS Code想選擇同等的 "捨棄所有檔案" 功能 請確保所有變更都真的不要了 ``` ---- ### 把暫存區的變更殺掉 使用 **`git restore -W -S <file_name>`** ``` 一次完成從stage區直接捨棄變更 ``` ``` 由於太危險,VS Code的圖形介面沒有直接提供這個按鈕 需要先取消暫存變更 (Unstage Changes) 才能將檔案移除 ``` ---- #### 從其他commit拿檔案 比cherry-pick更狠 使用 **`git restore -s <hash/branch> <file_name>`** ``` 抓某個commit版本的指定檔案到目前的workdir ``` <br> ``` 同cherry-pick的問題,一樣需要謹慎使用,不要為了方便破壞專案易維護性 ``` --- ## Git Reset ---- ### 取消最近一次的commit 使用 **`git reset HEAD~`** 或 使用 **`git reset HEAD^`** ---- ### 取消當前branch的多筆commit 使用 **`git reset HEAD~數字`** 或 使用 **`git reset HEAD~..~`** 例如想要取消3筆 ``` git reset HEAD~~~ 或 git reset HEAD~3 ``` ---- ### reset後捨棄變更 一般reset後 原本最新的變更會退回到worktree的workdir 若確定退回後不需要這些變更紀錄 使用 **`git reset HEAD~ --hard`** ---- ### 當前branch直接投奔到其他位置 當我們要讓當前branch強行變更到指定位置 可以使用 **`git reset <hash>`** 或 使用 **`git reset <branch_name>`** 將當前branch直接變更為指定commit的狀態 同樣可以選用 `--hard` 將原本位置的檔案變更捨棄 ---- #### 搭配 Git Graph ![](https://hackmd.io/_uploads/BJwVcqmM6.png) ``` 直接對想要的位置右鍵,使用 Reset current branch to this Commit 即可 ``` ---- #### 搭配 Git Graph ![](https://hackmd.io/_uploads/Hyw85q7Gp.png) ``` Soft:提交過的commit放到暫存區、當前worktree保留, Mixed:提交過的commit放到工作目錄、當前stage清除、workdir保留 Hard:提交過的跟當前變更都不要了,直接變成目標的狀態 ``` ``` 指令預設採Mixed模式,可以改指定`--hard`或`--soft` ``` ---- #### 參考閱讀: <br> [🔗剛才的 Commit 後悔了,想要拆掉重做…](https://gitbook.tw/chapters/using-git/reset-commit) ---- #### 補充 <br> git reset除了重置到指定狀態以外 還有很多活用的技巧 由於篇幅關係 此處簡單介紹回退commit及模式差別 實務用法可以在課後作業進行練習與思考 <br> --- ### Git Rebase ---- ### rebase的意義 <br> rebase中文翻譯成重訂基底,主要有2個功能 1. 濃縮commit 2. 將目前分支整根接到其他分支上 ---- ### 濃縮commit 當我們在同一條branch上commit太多次 想把一部分的commit合併成一個時 可以使用 **`git rebase -i HEAD~數字`** ``` 同樣可以使用 git rebase --abort 取消操作 ``` ---- ### 濃縮commit |||| |-|-|-| |![](https://hackmd.io/_uploads/r1qovjXfp.png)|![](https://hackmd.io/_uploads/SyakDjXGT.png)| ``` 等同git rebase -i HEAD~3 ``` ``` 選擇的那個commit不包含在可編輯區 ``` ---- ### 濃縮commit ![](https://hackmd.io/_uploads/Sk21uiQGT.png) ![](https://hackmd.io/_uploads/SkRVPsQfp.png)| ---- #### rebase 參數 ![](https://hackmd.io/_uploads/HydRdjQMT.png) ---- #### rebase 參數 簡單解釋4個比較常用的 ``` pick:保留Commit drop:刪除Commit,會捨棄這個Commit所紀錄的變更 reword:保留Commit,並修改這個Commit的訊息,但不影響裡面包含的檔案 squash:將這個Commit合併到前一個,用於濃縮多個小的連續Commit合併成1個 ``` ---- #### 進行濃縮 ![](https://hackmd.io/_uploads/rJH-Co7f6.png) ``` 修改後存檔 (Ctrl + S),再關閉分頁 ``` ``` 注意! 在互動模式的紀錄由上而下是從最舊到最新 跟 Git Graph 所呈現的結果是相反的。 ``` ---- #### 進行濃縮 ![](https://hackmd.io/_uploads/SyzuRimG6.png) ``` 我利用commit的模板工具,產生了我想要修改的訊息內容 但你會發現,此時無法直接按提交鈕 你必須將內容複製到文件,並取代原本的訊息 不要的內容都註解或刪除 ``` ---- #### 進行濃縮 ![](https://hackmd.io/_uploads/BJFEaiXGa.png) ``` 像這樣,完成後一樣存檔,關閉分頁 ``` ---- #### 完成濃縮 ![](https://hackmd.io/_uploads/HyETRsXfT.png) ``` 若執行完成沒有立刻更新,可以手動按右上角的refresh鈕 ``` ---- ### 移植當前分支到其他分支 ||| |-|-| |![](https://hackmd.io/_uploads/rygTGiXfa.png)|![](https://hackmd.io/_uploads/H1i3Hsmfp.png)| ``` 等同 git rebase branch ``` ---- ### 移植當前分支到其他分支 |||| |-|-|-| |![](https://hackmd.io/_uploads/B1OR4s7fp.png)|![](https://hackmd.io/_uploads/rJD1QsXzp.png)|![](https://hackmd.io/_uploads/Sk_fXsQG6.png)| ``` 搭配interactive也能在rebase階段如同濃縮的用法 在移植的過程中濃縮,或更改commit訊息 ``` ---- #### 補充 <br> git rebase 又更加強大而複雜了 同樣由於篇幅關係 需要各位在課後作業多加練習 遇到問題請盡量提出! <br> --- ## 延伸閱讀 ---- ### Git Revert ---- 將某個版本否決 [🔗Git Revert筆記](https://hackmd.io/JzrJyqfBQhuR9t1Q7OX73w?view#git-revert) ---- ### Git Stash ---- 將當前Worktree打包暫存 [🔗Git Stash筆記](https://hackmd.io/JzrJyqfBQhuR9t1Q7OX73w?view#git-stash) --- ## 學習資源 [🔗Charles HackMD - Git筆記 (GDSC複本)](https://hackmd.io/JzrJyqfBQhuR9t1Q7OX73w?both#git-command) [🔗W3Hexschool - Git & GitHub 教學手冊](https://w3c.hexschool.com/git/cfdbd310) [🔗為你自己學 Git - 情境狀況實戰](https://gitbook.tw/) [🔗Learn Git Branching - 線上Branch操作練習](https://learngitbranching.js.org/?locale=zh_TW) --- ## Q & A 時間 ---- ## 下一次課程 ### 10/25 (Wed) GitHub課程 金鑰交換, 遠端備份, Issue, Pull Request GitHub Actions, GitHub Project... --- ## 回家作業 <br> ⚒️製作中 請Follow Discord 或影片下方說明欄
{"slideOptions":"{\"transition\":\"concave\",\"allottedMinutes\":100}","title":"Git 課程","contributors":"[{\"id\":\"f8142aa2-66aa-4867-821d-2f1ffff7a7ba\",\"add\":21252,\"del\":8626}]","description":"課程影片:⚒️YouTube後製中簡報連結:🔗HackMD"}
    449 views
   Owned this note