###### tags: `git`
# Git 版本管理
當一個工程師先問問自己該如何管理程式碼?
工程師該如何交流程式碼?
用途:
管理程式碼
交流程式碼
新版程式出現錯誤,版本控制系統也還原至舊版(切換版本)
上傳到雲端版本控制服務平台(GitHub)
利用分支同時開發不同功能
## 分支與合併

master 表示穩定版本
其他的分支表示開發新功能(可以同時進行)
開發成功後才合併回 master
## git & github 差異
* Git : 分散式"版本控制"軟體。
* Github : 支援 git 程式碼存取和"遠端托管儲存庫"的平台服務
* git Repository : 儲存庫、數據庫
* Github : 只能放數據庫
## 軟硬體
* macbook air
* macOS 10.15
## 查看 git 是否安裝成功
```
git --version
```
## 操作步驟
> 步驟一:[下載 git](https://git-scm.com/downloads)
[下載 Homebrew](/@wallet69/homebrew) 可以集中管理套件
步驟二:建立一個要做版本管理的資料夾
步驟三:開啟終端機
步驟四:把當前目錄調到這個文件夾 (ex.cd downloads)
步驟五:記錄每一個修改檔案的人
```
git config --global user.name "wallet69"
git config --global user.email "wallet@gmail.com"
```
> 查詢使用者名稱及電子郵件是否設定成功
```
git config --list
git config user.name
git config user.email
```
> 步驟六:對專案註冊 Git 版本控制
```
git init
```
mac 用 command + shift + . 顯示隱藏檔案會看到 `.git` folder
> 步驟七:列出所有文件
```
ls
```
> 步驟八:建立一個新文件(文件存在工作目錄中,尚未加入數據庫)
```
touch 檔案名稱
touch 1.py
```
> 步驟九:查看版本庫的狀態
```
git status #狀態全寫
git status -s # 狀態縮寫
```
:::info
git status 只顯示和上一個 commit 不同的部分
:::
> 步驟十:將檔案加入索引
```
git add 檔案名稱
git add 1.py
git add . # 將所有檔案加入索引
```
> 步驟十ㄧ:提交一個檔案的新版本
```
git commit -m "<填寫版本資訊>"
```

> 步驟十二:查詢所有更改版本的訊息
```
git log
```
## git 中檔案的各個狀態

## diff 不同形式
> 在 unstaged 狀態和先前 commit 狀態的檔案差別
```
git diff
```
> 在 staged 狀態和先前 commit 狀態的檔案差別
```
git diff --cached
```
> staged & unstaged 狀態和先前 commit 狀態的檔案差別
```
git diff HEAD
```
## 修改已 commit 的版本
> 已經commit的版本,忘了附上另一個文件(2.py),但不想增加一個版本
> 版本資訊不會改變,但 id number 會變
```
git add 2.py
git commit --amend --no-edit #修正不編輯,直接合併
git log --oneline
```
> git log --oneline(看到當前變化)

## reset (不可以隨便亂用,可能會造成不可還原的影響)
### 從 staged 回歸 unstaged
```
git reset 1.py
```
### 回到過去各種版本
> 藉由 HEAD 指標的移動更換目前版本

### 回到上一個 commit版本
git reset --hard 表示不保留工作目錄中的檔案
```
git reset --hard HEAD #上一個
git reset --hard HEAD^ #上上個
git reset --hard HEAD~2 #上上個
git reset --hard "id number" #回到指定id 的版本
```
> 黃色字串為 id number

### 看到過去每一步的變化並更換版本
```
git reflog
```
> 此時的 git reset --hard 後面可加入 id number 或是 HEAD@{x}
> 
```
git reset --hard "id number"
git reset --hard "指標"
```
### 檔案已加入索引,退回工作目錄
```
git reset HEAD
```
## git 新增遠端數據庫
* 前往 github 網站
* 註冊會員 or 登入會員
* 右上角有一個 "+" 的符號
* 按下 new repository
* 輸入一個專案名稱
* 在終端機中 cd 到你想遠端分享的檔案
* 輸入 git remote add origin ...(到.git/config 檔案中確認是否成功遠端分享)
* Mac: command + shift + . (dot)顯示隱藏檔案/檔案夾(.git)

* 輸入 git branch -M main
* 輸入 git push -u origin main
* 若發生錯誤,解決方法如下:
> 修改 [remote “origin”]
url = https://github.com/xxx/example.git
[remote “origin”]
url = https://xxx@github.com/xxx/example.git
再次git push,即可提交
## git 縮寫
> 用 co 代替 checkout
```
git config --global alias.co checkout
```
> 這個功能會存放在 使用者/.gitconfig 中,可以直接在這個檔案內修改
## 測試主機與正式主機

> 當程式碼在本地端完成時,會先放到測試主機上運行,再放到正式主機上
> git remote add 因為還沒有 push ,所以一開始 0 commit
> -u 表示預設會推到哪個遠端數據庫
> git push 會推到預設的遠端數據庫
```
git remote add origin ... (先前的 origin 表示正式主機)
git remote add test ... (test可自訂名稱 表示測試主機)
git push -u test main #先 push 到測試
git push -u origin main #再 push 到正式
```

## checkout 指令
> 表示把 HEAD 指標指向某ㄧ個 commit
> git checkout 代碼(可以打幾個字後按tab鍵,git會自動補齊代碼)
> 資料夾會出現當時的檔案(與最新的 commit 不同)
> git checkout main 可以回到最新版本的 commit
> git checkout -- file name 刪掉還未進入索引的步驟
## 清空還沒被追蹤的檔案
> 測試階段創建的檔案可以一次清除
```
git clean -n #查看會刪掉的檔案
git clean -f #強制刪除檔案
```
## branch 分支
> 預設的分支是 main
### 創建分支
```
git branch branch名稱
git branch develop
```
### 查詢分支
```
git branch
```
### 刪除分支
```
git branch -d branch名稱
```
### 在多個分支中轉換 HEAD
```
git checkout branch名稱
```
### 合併
> 當 develop 測試成功後
> 將 main 和 develop 合併
```
git checkout main
git merge develop #預設快轉 (只有一條分支)
git merge --no-ff #取消快轉 (有兩條分支)
```
## git branch 練習
https://learngitbranching.js.org/?NODEMO=&locale=zh_TW
## 參考資料
> [參考資料](https://tw.alphacamp.co/blog/git-github-version-control-guide)
## 將 git 的預設編輯器更改為 Vim
```
git config --global core.editor "vim"
```
> ZQ : 結束 vim 的方式
## 發 PR (pull request)
1. 看到自己喜歡的專案 fork 那個專案
2. 發現那個專案有小問題要修改
3. 下載專案 git clone github給的網址
4. 在 master 上新增一個 commit
5. 對該專案作者發 pull request
6. 作者認為可以提升專案完整度則 merge 了 PR
## git merge 衝突
> 當你在不同分支中修改到同樣的 code 會產生衝突
> 在 visual studio code 可以直接選擇要保留哪一個 code
> 修改完才能正常合併
> 有衝突的檔案會先放到工作目錄上
> 解決衝突後需先 git add 再 git commit
## git pull
> 合併遠端數據庫分支的修改內容
> 當我們不知道 server 上的 code 已經更新,就直接使用 git push 就會被 server 拒絕