--- title: Git 學習筆記 tags: Note, git --- # Git 學習筆記 記錄一些Git 指令,太常用GUI操作有夠容易忘記指令的.. :::spoiler **Learning Resource** - [從 0 到 1 的 GitHub Pages 教學手冊](https://hackmd.io/@Albertnotes/B1_iKcAwI) - [Git & GitHub 教學手冊 - 六角學院](https://w3c.hexschool.com/git/cfdbd310) - [為你自己學 Git - 作者高見龍](https://gitbook.tw/) - [連猴子都能懂的 Git 入門指南](https://backlog.com/git-tutorial/tw/) - [Git 官方中文教學](https://git-scm.com/book/zh-tw/v2) - [30 天精通 Git 版本控管 - 作者黃保翕 ( Will 保哥 )](https://github.com/doggy8088/Learn-Git-in-30-days/blob/master/zh-tw/README.md) ::: ## Git 常用指令 src: https://codertw.com/程式語言/639003/ 1. `git remote -v` 查看origin指向URL 1. `git status` :查看目前工作目錄有無未被追蹤或已被修改的檔案 2. `git add [檔名or目錄名]` :新增追蹤的檔案,將檔案暫存 3. `git commit` :將 `git add` 加進去的檔案記錄在快照內。可使用 `-m` 參數添加此次commit的註記 * `git commit -am.` 4. `git push` :將commit完的分支推送到遠端倉庫上 5. 危險操作(ex. `merge`, `rebase`, `reset`等)之後回到上一步[(src)](https://hackmd.io/E9Q4BbyvTbWHVTk0ElaXng?view#%E4%BF%AE%E6%94%B9commit%E7%B4%80%E9%8C%84) ``` git reset ORIG_HEAD --hard ``` > [2021.10.15] > 由於Github前陣子取消了https上傳的方式,只好改來設定SSH金鑰[(SSH Key設定)](/qd9jrBOfQiSCFDIc6trkGg) ## 合併其他分支到main分支 src: https://gitbook.tw/chapters/branch/merge-branch.html 1. commit 目前所有更改的檔案 2. 切回 `main` 分支 ``` git checkout main ``` 3. 合併分支 ``` git merge [your-branch-name] ``` ## 切換遠端資料庫 1. 在github上建立完新repo之後 2. 初始化git ``` git init --initial-branch=main ``` 3. 切換到新的repo url ``` git remote set-url origin [new-remote-repo-url] ``` 4. 建立分支 ``` git branch -M main ``` 5. 上傳本地資料夾檔案到repo ``` git push -u origin main ``` </br> 也可以透過刪除的方式: 1. 查看所有遠端目錄 `git remote -v` 2. 刪除遠端 `git remote rm [remote-repo-name]` 3. 新增遠端 `git remote add origin [remote-repo-url]` ## 刪除遠端分支 1. 將 local branch 改名 ``` git branch -m {old_branch_name} {new_branch_name} ``` 2. 將新 branch push 至 server 並從 server 上刪除 branch ``` git push origin {new_branch_name} :{old_branch_name} ``` ## 本地分支與遠端分隻的操作 > src: [git Local 端與 Remote 端的分支操作](https://sean22492249.medium.com/git-local-%E7%AB%AF%E8%88%87-remote-%E7%AB%AF%E7%9A%84%E5%88%86%E6%94%AF%E6%93%8D%E4%BD%9C-3dc360be3b5b) * 連結local branch到 remote ```bash git branch --set-upstream-to=origin/uat uat ``` * 如果remote有一個新的分支還沒追蹤,local也沒有建立這個分支,可以直接輸入 ``` git checkout -track origin/uat ``` 直接將remote branch拉到本地,並建立連結。 ## 回到上一版或指定版本 回到上一版 ``` git reset --hard HEAD~ ``` 參數 ``` git reset --參數 節點ID ``` - `hard`: 強制回朔,不保留修改,刪除暫存 - `soft`: 回朔,且保留修改,不刪除暫存 - `mixed`: 強制回朔,保留修改,但刪除暫存 ## 修改 commit 方法 有三種方式: `reset`, `rebase`, `revert` | 指令 | 改變歷史紀錄 | 說明 | | -------- |:--------:| -------- | | Reset | 是 | 把目前的狀態設定成某個指定的 Commit 的狀態,通常適用於尚未推出去的 Commit。 | |Rebase |是 |不管是新增、修改、刪除 Commit 都相當方便,用來整理、編輯還沒有推出去的 Commit 相當方便,但通常也只適用於尚未推出去的 Commit。| |Revert|否|==新增一個 Commit== 來反轉(或說取消)另一個 Commit 的內容,==原本的 Commit 依舊還是會保留在歷史紀錄中==。雖然會因此而增加 Commit 數,但通常比較適用於已經推出去的 Commit,或是不允許使用 Reset 或 Rebase 之修改歷史紀錄的指令的場合。| ## Git clone 失敗 解決方法:https://www.cnblogs.com/anliux/p/11668058.html # 在Intellij IDEA中使用Git ## Git的基本工作流程 ![](https://i.imgur.com/hDgDaAm.png) - `git clone`: 將遠端的`master` 分支複製到本地的repository - `git checkout`: 切換到分支 - `git add`: 將文件加入git版控(stage) - `git commit`: 將版控中有改變的code提交到本地的repository - `git push`: 將本地repository的code提交到遠端repository 在IDEA中,會看到檔案變標著不同顏色:紅色、綠色、藍色,分別代表以下意思: - 紅色:未加入版控的檔案 - 綠色:新加入版控的檔案,還未提交到remote repository - 藍色:修改過的檔案,即 remote repository已有此檔案,我們對這檔案做了修改但還未提交。 一般再提交程式碼前最好先更新遠端repository的程式碼到本地,這樣可以減少不必要的衝突 - `fetch`: 取得遠端repository的最新歷史紀錄 - `merge`: 將遠端repository合併到目前所在的分支 - `pull` = `fetch` + `merge` 將遠端repository更新到本地的步驟如下:[src](http://italwaysrainonme.blogspot.com/2012/12/gitmerge_20.html) ### 更新 ## Git 分支 根據 **[Git Flow](https://ithelp.ithome.com.tw/articles/10227605)** 建議的git branch命名及使用方式如下: - Master 分支 主要是用來放穩定、隨時可上線的版本。這個分支的來源只能從別的分支合併過來,開發者不會直接 Commit 到這個分支。因為是穩定版本,所以通常也會在這個分支上的 Commit 上打上版本號標籤。 - Develop 分支 這個分支主要是所有開發的基礎分支,當要新增功能的時候,所有的 Feature 分支都是從這個分支切出去的。而 Feature 分支的功能完成後,也都會合併回來這個分支。 - Hotfix 分支 當線上產品發生緊急問題的時候,會從 Master 分支開一個 Hotfix 分支出來進行修復,Hotfix 分支修復完成之後,會合併回 Master 分支,也同時會合併一份到 Develop 分支。 為什麼要合併回 Develop 分支?如果不這麼做,等到時候 Develop 分支完成並且合併回 Master 分支的時候,那個問題就又再次出現了。 那為什麼一開始不從 Develop 分支切出來修?因為 Develop 分支的功能可能尚在開發中,這時候硬是要從這裡切出去修再合併回 Master 分支,只會造成更大的災難。 - Release 分支 當認為 Develop 分支夠成熟了,就可以把 Develop 分支合併到 Release 分支,在這邊進行算是上線前的最後測試。測試完成後,Release 分支將會同時合併到 Master 以及 Develop 這兩個分支上。Master 分支是上線版本,而合併回 Develop 分支的目的,是因為可能在 Release 分支上還會測到並修正一些問題,所以需要跟 Develop 分支同步,免得之後的版本又再度出現同樣的問題。 - Feature 分支 當要開始新增功能的時候,就是使用 Feature 分支的時候了。Feature 分支都是從 Develop 分支來的,完成之後會再併回 Develop 分支。 ![](https://i.imgur.com/v0RXA8R.png) 由於 Git Flow 流程較為複雜,後來推出的 **[GitLab Flow](https://ithelp.ithome.com.tw/articles/10228195)**,將流程簡化。 只分兩種主要分支: `master`, `production`。 - **Master**: 所有開發需求都從 `master` 分出來 - **Production**: 針對發佈的版本建立` ![](https://i.imgur.com/niC1Yjh.png) ## Git 標籤 - tag: 就是貼紙的概念,為指向某一commit的指標 - 用處:通常用來標記軟體版號,例如軟體版號 `1.0.0` 或是 `beta-release` 之類的 - 分成兩種:輕量標籤(lightweight tag)、附註標籤(annotated tag) - 輕量標籤:沒有附註,僅是一個指向某個 Commit 的指標,沒有含有其它的資訊 - 附註標籤:包含更多關於這張標籤的資訊,例如是誰在什麼時候貼這張標籤,以及為什麼要貼這張標籤 - 刪除標籤:不會造成commit或檔案不見 不管是哪種標籤,都跟branch一樣以檔案方式存在 `.git/refs/tags` 目錄下。 檔案的內容也跟分支一樣,是一個 40 個字元的 SHA-1 值,指向某個地方。但差別是,輕量標籤指向的是某一個 Commit,但附註標籤是指向某個 Tag 物件,而這個 Tag 物件才再指向那個 Commit。 `annotated tag` -> `lightweight tag` -> `commit` :::info **標籤、分支的差別** 「分支會隨著commit移動,標籤不會」 ::: ## Git commit 規範 Commit訊息規範的重要性,可參考:[Git Commit Message 這樣寫會更好,替專案引入規範與範例](https://wadehuanglearning.blogspot.com/2019/05/commit-commit-commit-why-what-commit.html) ### type 只允許使用以下類別: - feat: 新增/修改功能 (feature)。 - fix: 修補 bug (bug fix)。 - docs: 文件 (documentation)。 - style: 格式 (不影響程式碼運行的變動 white-space, formatting, missing semi colons, etc)。 - refactor: 重構 (既不是新增功能,也不是修補 bug 的程式碼變動)。 - perf: 改善效能 (A code change that improves performance)。 - test: 增加測試 (when adding missing tests)。 - chore: 建構程序或輔助工具的變動 (maintain)。 - revert: 撤銷回覆先前的 commit 例如:revert: type(scope): subject (回覆版本:xxxx)。 Type 是用來告訴進行 Code Review 的人應該以什麼態度來檢視 Commit 內容。 例如: 看到 Type 為 fix,進行 Code Review 的人就可以用「觀察 Commit 如何解決錯誤」的角度來閱讀程式碼。 若是 refactor,則可以放輕鬆閱讀程式碼如何被重構,因為重構的本質是不會影響既有的功能。 利用不同的 Type 來決定進行 Code Review 檢視的角度,可以提升 Code Review 的速度。因此開發團隊應該要對這些 Type 的使用時機有一致的認同。 ### commit格式 Header: `<type>(<scope>): <subject>` - type: 代表 commit 的類別:feat, fix, docs, style, refactor, test, chore,必要欄位。 - scope 代表 commit 影響的範圍,例如資料庫、控制層、模板層等等,視專案不同而不同,為可選欄位。 - subject 代表此 commit 的簡短描述,不要超過 50 個字元,結尾不要加句號,為必要欄位。 Body: 72-character wrapped. This should answer: * Body 部份是對本次 Commit 的詳細描述,可以分成多行,每一行不要超過 72 個字元。 * 說明程式碼變動的項目與原因,還有與先前行為的對比。 Footer: - 填寫任務編號(如果有的話). - BREAKING CHANGE(可忽略),記錄不兼容的變動, 以 BREAKING CHANGE: 開頭,後面是對變動的描述、以及變動原因和遷移方法。 範例: - 橘色部分份為 "必填" - 藍色部分份為 "選填" ![](https://i.imgur.com/LMs6rdi.png =70%x) ### 使用Plugin寫符合規範的commit 有許多幫助或檢查commit有沒有符合規範的套件,terminal或IDE內的都有,可視自己常用的開發工具或流程而定: - IDE: 推薦安裝 Conventional Commits,在VScode 或Intellij IDEA都有此套件 - terminal: https://github.com/Everduin94/better-commits