<!-- .slide: data-background="#dfdfdf" -->
# Git 深入淺出
###### 04.09 鄭余玄
---
<!-- .slide: data-background="#dfdfdf" -->
# Git 版本控制摘要

----
<!-- .slide: data-background="#dfdfdf" -->
## 常見版本管理系統
- **分散式**
- **Git**
- TFS (Team Foundation Server)
- 集中式
- CVS, SVN
----
<!-- .slide: data-background="#dfdfdf" -->
## 本地端版本管理

----
<!-- .slide: data-background="#dfdfdf" -->
## 分散式版本管理

---
<!-- .slide: data-background="#dfdfdf" -->
# Git 環境設定
----
<!-- .slide: data-background="#dfdfdf" -->
## git config
- ```--local```: ```.git/config```
- ```--global```: ```~/.gitconfig```
- ```--system```: ```/etc/gitconfig```
```bash
git config --global color.ui auto
git config --global log.abbrevCommit yes
git config --global core.editor vim
git config --global credential.https://github.com.使用者名稱 使用者名稱
git config --global credential.helper 'cache --timeout=3600'
```
- 預設編輯器:```vi```
- 環境參數:```GIT_EDITOR```, ```EDITOR```, ```VISUAL```
<!-- .element: class="fragment" data-fragment-index="1" -->
----
<!-- .slide: data-background="#dfdfdf" -->
## 憑證儲存
```
git config --global credential.https://github.com.使用者名稱 使用者名稱
git config --global credential.helper 'cache --timeout=3600'
```
----
<!-- .slide: data-background="#dfdfdf" -->
## alias
```bash
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit
git config --global alias.st status
```
- [Lesser known Git commands](https://hackernoon.com/lesser-known-git-commands-151a1918a60)
- [Stop Aliasing Your Git Commands](https://shift.infinite.red/stop-aliasing-your-git-commands-248dace51f7c)
----
<!-- .slide: data-background="#dfdfdf" -->
## .gitignore
- Lists all ignored files in this project.
```git ls-files --other --ignored --exclude-standard```
----
<!-- .slide: data-background="#dfdfdf" -->
## .gitattribute
----
<!-- .slide: data-background="#dfdfdf" -->
## .gitkeep
- git add 空資料夾
----
<!-- .slide: data-background="#dfdfdf" -->
## ```vim```
- ```i``` 編輯模式
- ```:wq``` 存檔離開
---
<!-- .slide: data-background="#dfdfdf" -->
# 程式碼倉儲
## Repository
----
<!-- .slide: data-background="#dfdfdf" -->
## Commit 提交
- tree(專案結構)
- author 作者資訊
- committer 提交者資訊
- commit message
- parent commit
----
<!-- .slide: data-background="#dfdfdf" -->
## Object Store

- Blob, Tree, Commit, Tag
- ```.git/``` 儲存元數據與資料庫
----
<!-- .slide: data-background="#dfdfdf" -->
## Object IDs
- SHA-1
- 根據檔案內容計算出幾乎唯一的檔案指紋
- [SHA-1 conflict](https://github.com/blog/2338-sha-1-collision-detection-on-github-com)
----
<!-- .slide: data-background="#dfdfdf" -->
## Refs
- 一般 ref
- 直接指向 object ID(通常是 commit 或 tag)
- ex: ```refs/tags```, ```refs/heads```
- 符號 ref(symref)
- 指向其他 ref

----
<!-- .slide: data-background="#dfdfdf" -->
## ```HEAD```
- 指向當前分支最後 commit 的 ref
- 簡而言之,就是最近一次的 commit
- 下一次 commit 會指向現在的 ```HEAD```
----
<!-- .slide: data-background="#dfdfdf" -->
## Treeish
- 完整 SHA1 / 部份 SHA1
- ```bae865```
- 分支、Tag
- ```master```
- 日期
- ```master@{yesterday}```
- ```master@{1 month ago}```
- 序數(前面第 n 個)
- ```master@{5}```
----
<!-- .slide: data-background="#dfdfdf" -->
## Treeish
- Carrot Parent(第 n 個父節點)
- ```master^2```
- 波浪號(第 n 個祖先)
- ```master~5```,等同 ```master^^^^^```

----
<!-- .slide: data-background="#dfdfdf" -->
# Repo 範例
----
<!-- .slide: data-background="#dfdfdf" -->


----
<!-- .slide: data-background="#dfdfdf" -->


----
<!-- .slide: data-background="#dfdfdf" -->


----
<!-- .slide: data-background="#dfdfdf" -->
## History
- DAG 有向無環圖

----
<!-- .slide: data-background="#dfdfdf" -->
## Traserval
---
<!-- .slide: data-background="#dfdfdf" -->
# 提交變更
## Making Commit
----
<!-- .slide: data-background="#dfdfdf" -->
## ```git add```
- ```-p, --patch``` 部份預存
- ```-i, --interactive``` 互動式提交
----
<!-- .slide: data-background="#dfdfdf" -->
## 追蹤相同檔案
- ```git rm 檔案``` 刪除檔案
- ```git mv 舊檔名 新檔名``` 重新命名檔案
----
<!-- .slide: data-background="#dfdfdf" -->
## ```git commit```
- ```-a```
- good commit message

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git tag```
- 顯示 tag
- ```git tag```
- ```git tag -l "v1.8.7*"```
- ```git show 標籤```
- 加 tag
- ```git tag 標籤```
- ```git tag -a 標籤 -m 訊息```
----
<!-- .slide: data-background="#dfdfdf" -->
## Working Directory
----
<!-- .slide: data-background="#dfdfdf" -->
## Index
- 早期叫做 cache
----
<!-- .slide: data-background="#dfdfdf" -->
# 工作流程範例
----
<!-- .slide: data-background="#dfdfdf" -->
## ```git add```


----
<!-- .slide: data-background="#dfdfdf" -->
## ```git commit```

----
<!-- .slide: data-background="#dfdfdf" -->
## 編輯檔案

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git add```

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git commit```

---
<!-- .slide: data-background="#dfdfdf" -->
# 還原變更
## Roll Back
----
<!-- .slide: data-background="#dfdfdf" -->

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git revert 提交```
- 還原特定提交
---
<!-- .slide: data-background="#dfdfdf" -->
## Reset
- 還原前 n 次提交
- ```git reset --模式 提交```
1. 移動 ```HEAD``` **指向**的 ref (```--soft```)
2. Index (```--mixed```)
3. Work Directory (```--hard```)

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git reset --soft 提交```

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git reset 提交```
- ```git reset (--mixed) 提交```

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git reset --hard 提交```

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git reset 檔案```
- ```git reset --mixed HEAD 檔案```
- 與 ```git add 檔案``` 相反
- 取消預存到編輯區
1. 移動 ```HEAD``` 指向的 ref 到 ```HEAD``` (不動作)
2. Index
----
<!-- .slide: data-background="#dfdfdf" -->
## ```git reset 檔案```

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git reset 提交 檔案```

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git reset -p 檔案```
- ```-p, --patch``` 部份還原
- 與 ```git add -p 檔案``` 相反
---
<!-- .slide: data-background="#dfdfdf" -->
## Checkout
1. 移動 HEAD
2. Index
3. Work Directory
----
<!-- .slide: data-background="#dfdfdf" -->
## ```git checkout 分支```
- **安全**的指令,基本上*類似* ```reset --hard```
- 簡易 merge,更新未變更檔案
----
<!-- .slide: data-background="#dfdfdf" -->
## 移動 ```HEAD```

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git checkout 提交```
- DETACHED HEAD
----
<!-- .slide: data-background="#dfdfdf" -->
## ```git checkout 檔案```
- ```git checkout (提交) 檔案```

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git checkout -p 檔案```
- ```-p, --patch``` 部份還原
----
<!-- .slide: data-background="#dfdfdf" -->
## 還原提交比較
| | HEAD | Index | Workdir | WD Safe? |
|----------------------------|------|-------|---------|----------|
| ```reset --soft 提交``` | REF | - | - | v |
| ```reset 提交``` | REF | v | - | v |
| ```reset --hard 提交``` | REF | v | v | **No** |
| ```checkout 提交``` | HEAD | v | v | v |
----
<!-- .slide: data-background="#dfdfdf" -->
## 還原檔案比較
| | HEAD | Index | Workdir | WD Safe? |
|----------------------------|------|-------|---------|----------|
| ```reset 檔案``` | - | v | - | v |
| ```checkout 檔案``` | - | v | v | **NO** |
---
<!-- .slide: data-background="#dfdfdf" -->
# 分支

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git branch```
- 顯示分支
- ```git branch```
- ```git branch -vv```
- 新增分支
- ```git branch 分支名稱```
- ```git checkout -b 分支名稱```
- 刪除分支
- ```git branch -d 分支名稱```
----
<!-- .slide: data-background="#dfdfdf" -->
# 合併
## Merge
----
<!-- .slide: data-background="#dfdfdf" -->
## Fast Forward

----
<!-- .slide: data-background="#dfdfdf" -->
## 3-way merge

----
<!-- .slide: data-background="#dfdfdf" -->
## Fast Forward

---
<!-- .slide: data-background="#dfdfdf" -->
# 追蹤遠端
## Tracking Remote
----
<!-- .slide: data-background="#dfdfdf" -->
## ```git clone 網址```
1. 建立一個新 repo
2. 新增並指向 ```origin``` 遠端
```
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = server:dir/repo
```
----
<!-- .slide: data-background="#dfdfdf" -->
## ```git fetch 遠端 分支```
- 與遠端同步 git 資料庫
- 不影響 ```Work Directory```, ```Index```, ```Head```
----
<!-- .slide: data-background="#dfdfdf" -->
## ```git pull 遠端```
- ```fetch``` 後 ```merge```
```
git fetch 遠端
git merge origin/當前分支.
```

----
<!-- .slide: data-background="#dfdfdf" -->
## ```git push 遠端 分支```
- ```-u``` 設定 upstream
- 只接受 fast-forward merge
- ```--force``` *危險*,覆寫歷史
- ```--all``` 所有分支
- ```--tags```
----
<!-- .slide: data-background="#dfdfdf" -->
## ```push.default```
- matching
- 所有本地和遠端有相同名稱的分支
- upstream
- 當前分支到 upstream
- **simple**
- 當前分支到同名稱 upstream
- current
- 當前分支到同名稱遠端(沒有則新增)
----
<!-- .slide: data-background="#dfdfdf" -->
## ```git remote```
- 遠端資訊
- ```git remote -v```
- ```git remote show 遠端```
- 重新命名
- ```git remote rename 舊遠端 新遠端```
---
<!-- .slide: data-background="#dfdfdf" -->
# 歷史紀錄
## History
----
<!-- .slide: data-background="#dfdfdf" -->
## ```git log```
- ```-n``` 顯示最近 n 筆
- ```--stat``` 顯示 diff
- ```-p, --patch``` 顯示 patch
- ```--pretty=``` 格式化
- ```--pretty=oneline```
- ```--pretty="%h - %an, %ar : %s"```
- ```git log master..另個分支```
- ```git show 提交```
----
<!-- .slide: data-background="#dfdfdf" -->
# Rebase
---
<!-- .slide: data-background="#dfdfdf" -->
# 第三方託管
- public
- private
----
<!-- .slide: data-background="#dfdfdf" -->
## Github
- GitHub $\neq$ Git
- [Student Pack](https://education.github.com/pack)
----
<!-- .slide: data-background="#dfdfdf" -->
## TFS

----
<!-- .slide: data-background="#dfdfdf" -->
## Others
- Bitbucket
- Gitlab
- Gogs
----
<!-- .slide: data-background="#dfdfdf" -->
## 實用 plugin - [Octotree](https://chrome.google.com/webstore/detail/octotree/bkhaagjahfmjljalopjnoealnfndnagc?hl=zh-TW)

---
<!-- .slide: data-background="#dfdfdf" -->
# 其他
----
<!-- .slide: data-background="#dfdfdf" -->
## 來不及講的主題
- 遠端存取 SSH Keys
- submodule
- [Removing sensitive data from a repository](https://help.github.com/articles/removing-sensitive-data-from-a-repository/)
- ```git stash```
- ```git merge --squash```
- ```git blame```
- ```git bisect```
----
<!-- .slide: data-background="#dfdfdf" -->
## 更深入 Git
- GPG sign
- worktree
- Reflog
- ```git log -g```
- Hook
- Travis CI
----
<!-- .slide: data-background="#dfdfdf" -->
## 延伸閱讀
- [Git SCM](https://git-scm.com/book/zh-tw/v2/%E9%96%8B%E5%A7%8B-%E9%97%9C%E6%96%BC%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6)
- [Atlassian Tut](https://www.atlassian.com/git/tutorials)
- [Git in 2016](https://hackernoon.com/git-in-2016-fad96ae22a15)
- [Git - a powerful version control tool](https://www.slideshare.net/KuoLeMei/git-a-powerful-version-control-tool-69568362)
---
<!-- .slide: data-background="#dfdfdf" -->
# QA