# 擁抱 Git CLI
## ToC
[ToC]
## 為什麼要用 CLI
Pros:
- 搭配 vi, vscode, sublime 等工具, 編輯 commit message(別人都已打完 message,而你還在等 IDE 開編輯訊息的彈窗?
- Learn once, use everywhere!
- 不需要滑鼠(你也有滑鼠突然沒電的困擾嗎?
- 提升英打速度(?
- 完整高階指令支援 e.g., `git log --grep 'some message'`
Cons:
- 移除你的 IDE, 重新適應 CLI
## 概念
### 日常操作,僅需熟悉以下七個指令就已足夠
|指令|說明|
|---|---|
|`git branch my-branch`|開始開發,開一個新分支|
|`git checkout my-branch`|切換至該新分支|
|`git add -p`|增加修改的檔案至暫存區|
|`git commit -m"first commit"`|將暫存區的檔案提交至本地儲存庫|
|`git fetch origin develop`|取得遠端分支的資訊|
|`git rebase origin/develop`|遠端分支可能有更新,要先 rebase 分支|
|`git push origin my-branch`|推當前分支至遠端|
### 檔案狀態
每個檔案都有三個對應的狀態:
```sequence
participant 工作目錄
participant 暫存區
participant 本地儲存庫
Note over 工作目錄: 已追蹤,並且有變更的檔案/未追蹤的檔案
Note over 暫存區: 將被記錄的檔案
Note over 本地儲存庫: 已記錄的檔案
```
```sequence
participant 工作目錄
participant 暫存區
participant 本地儲存庫
工作目錄->暫存區: git add -p
暫存區->本地儲存庫: git commit -m"增加新功能 blah blah..."
NOTE over 本地儲存庫: SHA1: 9afc5562
本地儲存庫-->暫存區: git reset 9afc5562 --soft
暫存區-->工作目錄: git reset
```
### checkout 用來切換紀錄

```sequence
participant 工作目錄
participant 暫存區
participant 本地儲存庫
Note over 本地儲存庫: 9afc5562
本地儲存庫->本地儲存庫: git checkout 18872304
Note over 本地儲存庫: 18872304
```
> 延伸閱讀 [git object of the Git Book](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects)
### branch / tag 都只是 SHA1 的別名
只要有 git 就一定會處於 HEAD ,任何變更都會影響到當前的 HEAD
#### `HEAD -> 9afc5562`

#### `HEAD -> feature/sticky-table-ernest -> 9afc5562`

```sequence
participant 工作目錄
participant 暫存區
participant 本地儲存庫
Note over 本地儲存庫: 9afc5562
本地儲存庫->本地儲存庫: git checkout 18872304
本地儲存庫->本地儲存庫: git checkout HEAD~
本地儲存庫->本地儲存庫: git checkout feature/sticky-table~
Note over 本地儲存庫: 18872304
```
### 操作都是在 HEAD 指向的紀錄上執行
HEAD 沒有指向任何分支,此時 Commit 一筆紀錄,僅 HEAD 自己會指到新的 SHA1,而其他分支不會影響

HEAD 指向某一分支,此時 Commit 一筆紀錄,HEAD、分支都會跟著指到新的 SHA1

> 延伸閱讀 [HEAD~ HEAD^ 有何不同](https://stackoverflow.com/questions/26785118/head-vs-head-vs-head-also-known-as-tilde-vs-caret-vs-at-sign/26785200)
### 接力
```sequence
participant 本地儲存庫
participant 遠端儲存庫
participant 開發者B的儲存庫
Note over 本地儲存庫: 版本一
本地儲存庫->遠端儲存庫: git push branch/tag
Note over 遠端儲存庫: 版本一
遠端儲存庫-->開發者B的儲存庫: git pull branch/tag
Note over 開發者B的儲存庫: 版本一
Note over 開發者B的儲存庫: 版本二
開發者B的儲存庫->遠端儲存庫: git push branch/tag
Note over 遠端儲存庫: 版本二
遠端儲存庫-->本地儲存庫: git pull branch/tag
Note over 本地儲存庫: 版本二
```
## 總結
```sequence
participant 工作目錄
participant 暫存區
participant 本地儲存庫
participant 遠端儲存庫
participant 開發者B的儲存庫
工作目錄->暫存區: git add -p
暫存區->本地儲存庫: git commit -m"移除未使用..."
Note over 本地儲存庫: 版本一
本地儲存庫->遠端儲存庫: git push branch/tag
Note over 遠端儲存庫: 版本一
遠端儲存庫-->開發者B的儲存庫: git pull branch/tag
Note over 開發者B的儲存庫: 版本一
Note over 開發者B的儲存庫: 版本二
Note over 開發者B的儲存庫: 版本三
開發者B的儲存庫 ->開發者B的儲存庫: git checkout HEAD~
Note over 開發者B的儲存庫: 版本二
開發者B的儲存庫->遠端儲存庫: git push branch/tag
Note over 遠端儲存庫: 版本二
遠端儲存庫-->本地儲存庫: git pull branch/tag
Note over 本地儲存庫: 版本二
本地儲存庫-->暫存區: git reset 9afc5562 --soft
暫存區-->工作目錄: git reset
```
## 遇到困難怎麼辦?
直接找官方文件是最周全的方式:
[the Git Book](https://git-scm.com/book/zh/v2)
此外也可以利用以下指令查詢:
`git help`
`git help tutorial`
`git help everyday`
## 搭配視覺化的練習網站
[](https://learngitbranching.js.org/?demo)
## 參考來源
- https://zh.wikipedia.org/wiki/%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6
- https://git-scm.com/book/en/v2/Git-Internals-Git-Objects
- https://www.datanamic.com/repository/
<style>
html {
font-size: 1vw;
}
th, td {
font-size: 1rem;
line-height: 1;
}
</style>
{"metaMigratedAt":"2023-06-15T09:23:56.259Z","metaMigratedFrom":"Content","title":"擁抱 Git CLI","breaks":true,"contributors":"[{\"id\":\"e77f9ae0-feb2-4c38-9ae8-f06f8655e3a4\",\"add\":14844,\"del\":11114},{\"id\":\"2fbb4d16-4c3e-4fb1-938b-00f89a4261c1\",\"add\":240,\"del\":310}]"}