# Git 基礎教學 contributed by <[steven1lung](https://github.com/steven1lung)> and <[Niomoo](https://github.com/Niomoo)> Git 是所有開發者、工程師必定要學會如何使用的工具,今天就打算講解一下我們為什麼會需要版本控制工具,以及要如何去初步使用它。 ![](https://i.imgur.com/PGzKhpN.jpg =500x) 課程投影片請[點我](https://docs.google.com/presentation/d/1k-8tpV2Y56pjV5ukGwuOT38JDNpj2Eng/edit?usp=sharing&ouid=108571221444213940337&rtpof=true&sd=true)。 ## 介紹 Git 是由 Linux Kernel 的開發者 Linus Torvalds 在開發 kernel 時,因為需要一個版本控制工具而發明的。 現在的 Git 已經是在全世界被許多人在使用了,可以說 Linus Torvalds 開發了核心造福了使用者,而開發了 Git 造福了開發者。 ### 為什麼要使用 Git * Git 可以說是接近每一個開發者都在使用的工具(當然也有其他版本控制的工具,但是 git 佔最大宗) * 開發者可以在任何時間、任何地點參與開發 * 開發者可以看到完整的開發歷史紀錄 * 當有問題出現,可以 revert 到之前的版本 ### Git 特性 Git 這個版本控制工具有以下這些特性: * 每個 project 都可以被視為一個 repository (repo) * 可以透過 clone 將在遠端(remote)的 repo 拉到本地端進行開發 * 透過 staging 跟 commit 來處理開發者所做的變更 * 透過 branch 跟 merge 來分開處理不同開發者的所更新的內容 * 透過 pull 來將自己本地端的 repo 更新到目前 remote 最新的 * 透過 push 將自己本地端的 repo 推到 remote ## 實作練習 ### prerequisite 請依照[行前通知](https://hackmd.io/@Niomoo/prepare_before_git)安裝對應軟體並進行設置。 ### config 通常第一次使用 git 會需要透過 `git config` 來設定一下自己的名稱跟信箱 1. `git config --global user.name "你的名字"` 2. `git config --global user.email "你的信箱"` 3. `git config -l` > `git config -l` 讓你可以確認一下自己的設定有沒有正確 ### Terminal 基本指令 | Windows | MacOS/Linux | 說明 | | --------- | ----------- | ---------- | | cd [路徑] | cd [路徑] | 前往資料夾路徑 | | cd | pwd |取得目前所在的位置| | dir | ls | 顯示資料夾裡的檔案 | | mkdir | mkdir | 新增資料夾 | | 無指令 | touch | 開新檔案 | | copy | cp | 複製檔案 | | move | mv | 移動檔案 | | del | rm | 刪除檔案 | | cls | clear | 清除畫面上的內容 | ### Example 1: push a project onto github > 當你想將自己本地端的專案推上 github #### 增加檔案 建立一個 hello.c 檔案 ```c #include<stdio.h> int main(){ printf("hello world\n"); return 0; } ``` 然後進行編譯 `gcc hello.c -o hello`,產生出 `hello` 執行檔。 `./hello` 可以看到 terminal 印出 `hello world`,代表程式是有成功的。 #### init 接下來我們想把寫好的 `hello.c` 上傳到 github 上 透過 `git init` 進行初始化。 ![](https://i.imgur.com/MwEqamA.png) :::info 若folder下有隱藏的資料夾`.git`就代表有成功初始化 ::: #### add & commit 透過 `git add` 跟 `git commit` 就可以將自己的程式碼推到本地端上。 :::warning git add .:將目前所在目錄下的所有檔案(包含子目錄)加入追蹤 git add *.c:將所有以「.c」結尾的檔案(不包含子目錄)加入追蹤 ::: :::warning 各位在寫 commit message 的時候要有良好的書寫習慣,請參考 [How to Write a Git Commit Message](https://cbea.ms/git-commit/) ::: 在這邊我們可以用 `git add hello.c` 將 `hello.c` 加到 staging,然後透過 `git commit` 進行 commit,commit message 可以寫 `Add hello.c file`。 ![](https://i.imgur.com/SiIr62O.png) > 通常不會將執行檔或是編譯過程中產生出的 obj 檔也傳上去,所以可以使用 `.gitignore` 進行忽略檔案的設定 #### push to remote 因為這個是新建立的本地 repo,所以 remote 端也要建立一個新的 repo 進行對應。 [點這邊](https://github.com/new)建立一個新的 repo,並將其命名為 `git_test`。 建立完成後就可以將本地端的 repo 連接到 github 上的 repo。 ```bash git remote add origin git@github.com:你的帳號/git_test.git git branch -M master git push -u origin master ``` `git branch -M` 是將目前的 branch 移到 master 或是 main 上面,這邊要對應到你 github repo 上的 default branch。 `git push -u origin master` 是將本地的 commit 推到遠端上,`-u` 是 `--set-upstream` 的意思,要進行 tracking。 最後就可以到 github 上確認剛剛的檔案有沒有上傳成功了。 ![](https://i.imgur.com/0KfiF3i.png =500x) ### Example 2: fork repo and make changes #### fork & clone 1. 請各位先去 fork 這個 github 連結 https://github.com/steven1lung/ncku-gdsc-git-tutorial > 進去後點選右上角的 fork 2. Fork 到自己的 repo 後請 clone 到自己的本地端 > 請使用 `git clone` #### add & commit clone 下來的 repo 可以看到有一些錯誤(typo 跟 bug),請進行修改並且分別 commit 上去。 > 使用 `git add` `git commit` 預期的結果: > `git log` 可以看之前的 commit msg ![](https://i.imgur.com/QUruDNo.png) 兩個 commit,一個修改 typo,一個修改邏輯錯誤。 Fix typo ![](https://i.imgur.com/i1YDkES.png) Fix add input bug ![](https://i.imgur.com/nqTgaKR.png) > 可以用 `git diff` 來看到所做的變更 #### push 使用 `git push` 將本地端的修改推到遠端上。 之後就可以到 github 上面看剛剛的兩個 commit 了。 #### branch & checkout branch 是 git 非常強大的一個功能,可以讓許多開發者同時進行開發。 請在剛剛修正好的 repo 裡繼續開發,加上這些功能:減、乘、除。 請將 branch 命名為:`feature/minus`、`feature/multiply`、`feature/divide`。 > 新增 branch 的方式為 `git branch 分支名稱`,並且可以使使用 `git checkout 分支名稱` 進行 branch 之間的切換 建立完 branch 後請到各自的 feature branch 中實作功能。 預期結果: `git branch` > 看一下現在本地端的分支狀況 ![](https://i.imgur.com/bJyueN8.png) #### merge 寫好各別分支的程式邏輯後,就可以用 merge 合併剛剛的分支。 先用 `checkout` 回到 master,然後 `git merge branch_name` 就可以合併了。 > 通常在 merge 的時候會有 conflict(衝突),修改好衝突就可以使用 `git merge --continue` 繼續。 > > 如果後悔,merge 到一半不想繼續 merge,可以使用 `git merge --abort` 進行中斷。 ### Example 3: reset commit 以第一個開發的 project 為例,如果我們做了一些修改,但是結果不盡人意,不想要這次的修改有沒有直接 reset 的方法。 `git reset` 就可以做到這個動作,我們也可以帶入 flag,比如說:`--soft`、`--hard` 然後再指定要回到哪一個 commit 就可以囉 。 比如說原本的 `hello.c` 長這樣: ![](https://i.imgur.com/mn0Qzrd.png =500x) 經過修改變成這樣: ![](https://i.imgur.com/S6MTFmy.png =500x) > 這樣會編譯不過,所以我想回到原本的 commit 就可以使用 `git reset --hard HEAD` 強制回到原本的 commit 並且清空我的修改。 ## Conclusion 今天所教的東西的是非常基礎的,因為每個指令都可以再帶入一些參數,來達到一些更進階的操作,或是省略一些指令。 還有許多沒有提到的指令也是開發很常會使用到,比如說:`git stash`、`git rebase`。 如果對 git 有問題都可以私訊我的 DC `steven1lung#4187` `Nio#9994` 或是在 git 討論區詢問,我都會盡量替大家解答。 希望今天大家來是有學到東西,也祝福大家能在開發這條路上變得更厲害,謝謝!