# Git ###### tags: `summer course` contributed by <[YW0330](https://github.com/YW0330)> ## 你為什麼要學 Git ? * [**104 人力銀行** "git" 搜尋結果](https://www.104.com.tw/jobs/search/?ro=0&keyword=git&expansionType=area%2Cspec%2Ccom%2Cjob%2Cwf%2Cwktm&order=1&asc=0&page=1&mode=s&jobsource=2018indexpoc&langFlag=0&langStatus=0&recommendJob=1&hotJob=1) ## 版本控制簡介 - 版本控制 Version Control System (VCS) - 紀錄修改歷程 - 應用-主要是文字類檔案 - 程式 (C/C++, java, python) - 論文 (LaTex) - VCS 分類 - 中央式 ![](https://git-scm.com/book/en/v2/images/centralized.png) - 分散式 ![](https://git-scm.com/book/en/v2/images/distributed.png) ## Git SCM - [官方網站](https://git-scm.com/) - [下載](https://git-scm.com/downloads) :::info :notes: Windows: `64-bit Git for Windows Setup.` ::: - **S**ource **C**ode **M**anagement - Linux kernal 開發者 Linus Torvalds 創建 - C 語言編寫 - 分散式 ## Git 操作 - 學習資源 {%youtube FKXRiAiQFiY %} - [Pro Git](https://git-scm.com/book/en/v2) - [為你自己學 Git](https://gitbook.tw/) - [連猴子都能懂的 Git 入門指南](https://backlog.com/git-tutorial/tw/) ### 使用者設定 - 查看設定指令 `$ git config --list` - 設定使用者名稱 `$ git config --global user.name "John Doe"` - 設定email `$ git config --global user.email johndoe@example.com` ### 基礎概念 - Repository (倉儲): 儲存修改紀錄的資料庫 - Local Repository: 在個人電腦上 - Git directory: `.git` 資料夾,儲存 Local repository 的所有資料,包含修改紀錄 - Working tree: 當前的工作目錄,即正在編輯的檔案 - Staging area (預存區): 紀錄需要儲存進 local repository 的檔案變更,沒有在 staging area 的檔案不會進入 repository - Remote Repository: 在遠端伺服器 (server) - Working tree 的檔案狀態 ![](https://git-scm.com/book/en/v2/images/lifecycle.png) - Tracked: 有進行版控的檔案 - commited/unmodified: 已提交 (commit) 修改的檔案 - modified: 從上次提交後有做過修改 - staged: 等待提交 - Untracked: 沒有進行版控的檔案 ### 基本操作 1. 開啟 Git Bash - 右鍵菜單點選 `Git Bash Here` :::info :notebook: Windows 系統也可以用 `cmd`,linux系統直接使用 `Terminal`。 ::: 2. 複製 GitHub 上的倉儲 ```shell $ git clone <url> ``` :::info :notes: <url> 可由 GitHub 網頁上獲得 ![](https://i.imgur.com/ZcyMqYK.png) 一個專案只需要一次 `clone`。 ::: - 變更複製的倉儲名稱 ```shell $ git clone <url> <desired repository name> ``` :::warning :warning: 在 windows 中使用 `$ git clone` 時,注意不要使用 `Ctrl+V` 來貼上文字,使用 `Ctrl+V` 貼上文字然後再右鍵按 `paste` 會造成以下 bug ``` Git fatal: protocol 'https' is not supported ``` 解決方式: [stackoverflow-Git fatal](https://stackoverflow.com/questions/53988638/git-fatal-protocol-https-is-not-supported) ::: - 下載整個倉儲 - 上面圖片點選 `Download ZIP` - 下載特定 GitHub 檔案或資料夾 - [DownGit](https://minhaskamal.github.io/DownGit/#/home) 3. 新建 git 倉儲 - 在需要進行版控的目錄下 ```shell $ git init ``` 完成後會看到該目錄下多了一個 `.git` 隱藏資料夾。 4. 將檔案加入 Git 管理中 - 新增當下目錄中的單一檔案 ```shell $ git add <filename> ``` - 新增當下目錄中的全部檔案 ```shell $ git add . ``` 5. 查看檔案狀態 ```shell $ git status ``` 6. 提交 ```shell $ git commit ``` :::success :notebook: 可改用 `$ git commit -a` 這道命令,讓 Git 自動追蹤變更的檔案並提交。 ::: - Commit Message - 第一列: 標題摘要 :notes: 只需要紀錄標題可以使用下列命令。 ```shell $ git commit -m "<commit title>" ``` - 第二列: 空白 - 第三列: 內文,如功能詳情與修改理由等 - [如何寫好 Git Commit Message](https://blog.louie.lu/2017/03/21/%E5%A6%82%E4%BD%95%E5%AF%AB%E4%B8%80%E5%80%8B-git-commit-message/) ### 其他常用操作 - 重新提交 ```shell $ git commit --amend ``` :notes: `git commit --amend` 僅限於重新提交最新的 commit message,若要修改之前的 commit message,必須使用 `git rebase -i HEAD~~<倒數第幾個提交的 commit>`。 範例: [fewletter/fibdrv](https://github.com/fewletter/fibdrv/commits/master) commit ![](https://hackmd.io/_uploads/BJX5obwL3.png) ```shell $ git rebase -i HEAD~10 ``` ![](https://hackmd.io/_uploads/SJhXobwL3.png) 選取要修改的檔案修改前贅詞 `pick` 為 `r` 或 `reword`,儲存檔案在 `git-rebase-todo`,接著離開 ![](https://hackmd.io/_uploads/rkl6j-wU2.png) 會看到 ![](https://hackmd.io/_uploads/By3LnbwLn.png) 然後將想改的 commit message 加到上面,儲存檔案在 `COMMIT_EDITMESG`,接著離開 ![](https://hackmd.io/_uploads/rJS6nbwI2.png) ```shell $ git push -f ``` f 代表 force 的意思,他會覆蓋掉整個 branch 的 commit message ![](https://hackmd.io/_uploads/S1agRbDUn.png) 從下圖可以看到 `Fix big number in driver` 已經改成 `Fix big number size and time in driver` ![](https://hackmd.io/_uploads/ByltRbvIh.png) - 查看歷程記錄 ```shell $ git log ``` - 僅顯示標題 ```shell $ git log --oneline ``` - 查看尚未預存的修改 ```shell $ git diff ``` - 將 staged 檔案移出預存區 ```shell $ git reset <filename> ``` - 復原被修改的檔案 ```shell $ git checkout -- <filename> ``` :::danger :warning: 對未提交 commit 的檔案進行復原或刪除,有可能導致檔案遺失。 ::: ## VS Code 中操作 Git 1. 安裝 `GitLens`, `Git History` 擴充插件 ![](https://i.imgur.com/ChOdibV.png) ![](https://i.imgur.com/3aZsEGW.png) 2. 新建 git repository 點選 `初始化`。 ![](https://i.imgur.com/q0sVowC.png) 3. 可用檔名上的 `+`, `-` 號變更檔案狀態 - Changes (變更): 未加入 staged area - Staged Changes (暫存的變更): 已加入 staged area - 檔案右邊名稱最右邊字母表示狀態 - A: added - U: untracked - M: modified - D: deleted ![](https://i.imgur.com/ge4wdMi.png) 4. 在文字框中輸入 commit message,`Ctrl`+`Enter` 可以提交 commit ## GitHub - [官方網站](https://github.com/) ### 基本操作 1. 在本地端加入 remote repository ```shell $ git remote add <remote username> <url> ``` - 常見的 `<remote username>`: `origin`,clone 的預設名稱 2. 上傳 local repository 到 remote repository ```shell $ git push <remote username> <local branch> ``` - 常見的 `<local branch>`: `master`, `main` - 在第一次上傳後,往後可以直接執行 `$ git push` 3. 下載 remote repository 到 local repository ```shell $ git pull <remote username> <local branch> ``` - 往後可以直接執行 `$ git push` ### 參與公開專案 1. 參與一個**沒有權限**的專案,可利用 `fork` 複製一份專案副本到你的 GitHub 帳號。 ![](https://i.imgur.com/cm39zlm.png) 2. 對合作專案提交 pull request 當你參與了一個專案 (已經進行 `fork` 後),並且想要修改原本的合作專案,可以提交 pull request,但是提交前要先注意 `fork` 時候的版本跟原本專案的版本是否相同。 - **`fork` 版本跟原本專案的版本相同** 直接提交 pull request ![](https://hackmd.io/_uploads/rko01Av_h.png) 出現下面的畫面,撰寫標題和描述然後點選 `Create pull request` 即可。 :::warning 請注意此處標題須符合 commit message 的規範,因為原專案作者會使用你的標題去創造 commit。 ::: ![](https://hackmd.io/_uploads/ryi9lRwOn.png) - **`fork` 版本跟原本專案的版本不相同** ![](https://hackmd.io/_uploads/BJuEzAP_3.png) :question: 在提交 pull request 時,會發現一次提交所有 commit,但問題是如果你只想提交某個 commit 時怎麼辦? ![](https://hackmd.io/_uploads/B1UuzCPOh.png) 1. 首先先增加遠端儲存庫 ```shell $ git remote add upstream <原本專案網址> ``` :::info git 本身即支援多個倉儲,而自己本身的默認倉儲的名稱為 origin。 ::: 2. 同步遠端倉儲至本地端 ```shell $ git fetch upstream ``` 3. 創造分支於上游倉儲 ```shell $ git checkout -b <分支名稱> upstream/master ``` :::warning 請注意此處也會在原本專案中創造分支,代表原本專案作者也看的到分支。 ::: 4. 切回原本分支 ```shell $ git checkout master ``` 5. 瀏覽並挑選要提交的 commit,請記住要提交的 commit 的 ID。 ```shell $ git log ``` :::info 切回原本分支和瀏覽並挑選要提交的 commit 可以用看 github 中 commit 取代。 ::: 6. 切回自己創造的分支,接著挑選自己剛才記住 commit ID ```shell $ git checkout <分支名稱> $ git cherry-pick <commit ID> ``` 7. 直接推回自己的專案 ```shell $ git push origin <分支名稱> ``` 選取要的分支然後提交 pull request。 ![](https://hackmd.io/_uploads/Hy4cF0v_3.png) 等到專案作者接受就可以刪掉分支。 參考資訊: [如何只提交/應用指定 commit](https://anclark.github.io/2021/02/12/Git/Git_Sync_Commits/) ## 其他 ### 忽略不需要的檔案 - 新增 `.gitignore` 檔案 - 範例 ``` # 不要追蹤檔名為 .a 結尾的檔案 *.a # 但是要追蹤 lib.a,即使上面已指定忽略所有的 .a 檔案 !lib.a # 只忽略根目錄下的 TODO 檔案,不包含子目錄下的 TODO /TODO # 忽略 build/ 目錄下所有檔案 build/ # 忽略 doc/notes.txt,但不包含 doc/server/arch.txt doc/*.txt # 忽略所有在 doc/ 目錄底下的 .pdf 檔案 doc/**/*.pdf ``` - [Visual Studio Code - 右鍵開啟檔案或資料夾](https://blog.johnwu.cc/article/right-click-open-visual-studio-code.html) - [Git 發布 Release 版本](https://ithelp.ithome.com.tw/articles/10254919)