# Git
###### tags: `Tools`
## 版本控制
### 什麼是版本控制?
也可以稱為版本跌代、新的版本、版本管理器。
版本控制(Revision control)是一種開發時用於管理我們對文件、資料夾或項目的修改歷史,方便我們查看更改過的歷史紀錄,備份以方便回復以前版本的軟體工程技術。
* 實現跨區域多人協同開發
* 追蹤與紀錄一個或多個文件的歷史紀錄
* 具有組織性與保護性原始程式碼與文件
* 可以統計工作量(例如commit次數)
* 追蹤並且記錄整個軟體的開發過程
* 減輕開發人員的負擔,節省時間,並降低人為錯誤
簡單來說git就是用於管理多人協同開發專案的技術。
如果沒有進行版本控制或是版本控制缺乏了正確的流程管理,那在軟體開發中會引發很多問題,例如軟體的一致性、軟體內容的冗餘、軟體過程的事務性、軟體開發過程中的併發性、軟體源程式碼的安全性以及軟體整合等問題。
無論是工作、學習或是筆記,肯定都經歷過一個痛苦的階段如下:

所以,我們迫切需要一個版本控制工具!
如果是多人開發,更必須使用版本控制,否則會產生巨大的代價!
### 常見的版本控制工具
主流的版本控制器有這些:
* Git
* SVN(subversion)
* CVS(Concurrent Versions System)
* TFS(Team Foundation Server)
* Visual Studio Online
版本控制的產品非常多,而其中影響力最大且最廣泛的就是Git!
### 版本控制分類
1. 本機版本控制
紀錄文件每次的更新,可以對每個版本做一個快照,或是紀錄補丁文件,適合個人使用,如RCS。

2. 集中版本控制
所有的版本數據都保存在伺服器上,協同開發者從伺服器上同步更新或上傳自己的修改

使用者的本機只有自己以前同步過的版本,如果沒有連接網路,使用者看不到歷史版本,也就無法切換版本驗證問題,或在不同的分支工作,而且,所以的數據都保留在單一的server上,有很大的風險server會損壞,這樣就丟失了所有數據。
3. **分布式版本控制**
所有的版本訊息倉庫全部同步到本機的每個使用者,這樣就可以在本機查看所有版本歷史,可以離線在本機查看所有版本歷史,可以離線在本機提交,只需在連網時push到對應的伺服器或其他使用者即可,由於每個使用者那裡保存的都是所有版本數據,所以只要有一個使用者的設備有問題就可以恢復所有的數據,但也增加了本機儲存空間的占用,**而且每個人都擁有全部的程式碼!存在一些安全隱患!**
但好處是不會因為網路問題或是server損壞造成不能工作的情況!

### Git與SVN最主要的區別
**SVN是集中式版本控制系統**,版本庫是集中方在中央伺服器的,開發時,都需要先從中央伺服器取得最新版本,開發完成後,需要將自己做完的內容推送到中央伺服器。集中式版本控制系統是必須連網才能做開發,對於網路頻寬要求較高。
**而Git是分布式版本控制系統**,沒有中央伺服器,每個人的電腦就是一個完整的版本庫,開發時不需要連網,因為版本都在自己的電腦上,協同:自己在本機修改了文件A,其他人也在電腦上改了文件A,此時,只需把兩人各自的修改推送給對方,就可以互相看到對方的修改了,Git可以直接看到更新了那些程式碼和文件!
<font color=red>**Git是目前世界上最先進的分布式版本控制系統。**</font>
## Git環境設定
### 軟體下載
官網:https://git-scm.com/
### 刪除
直接返安裝即可,然後清理系統變數。
安裝時無腦下一步!
### 啟動Git
安裝成功後在開始目錄中會有Git選項,資料夾下有3個程序,任意資料夾下按右鍵也可以看到對應的程序:

**Git Bash**:Unix與Linux風格的command line,使用最多,推薦最多
**Git CMD**:Windows風格的cmd
**Git GUI**:圖形介面的Git,不建議初學者使用,盡量先熟悉常用命令
### 基本的Linux指令學習
1. cd:改變目錄
2. cd..:回到上一層目錄,直接cd進入默認目錄
3. pwd:顯示當前所在的目錄路徑
4. ls(ll):都是列出當前目錄中所有檔案,只不過ll列出的內容更詳細
5. touch:新建一個檔案,如touch index.js就會在當前目錄下新增一個index.js檔案
6. rm:刪除一個檔案,rm index.js就會把index.js檔案刪除
7. mkdir:新增一個目錄,也就是新增一個資料夾
8. rm -r:刪除一個資料夾,rm -r -src刪除src資料夾
```
rm -rf / 切勿在Linux中嘗試!
```
9. mv:移動檔案,mv index.html src,index.html是我們要移動的檔案,src是目標資料夾,當然,這樣寫必須保證檔案和目標資料夾在同一目錄下
10. reset:重新初始化終端/清屏
11. clear:清屏
12. history:查看指令歷史
13. help:幫助
14. exit:退出
15. #:註釋
### Git設定
所有的設定檔案,其實都保存在本機!
查看設定git config -l:

查看不同級別的設定檔案:
```
#查看系統config
git config --system --list
#查看當前用戶(global)設定
git config --global --list
```
Git相關的設定檔案:
1. Git\etc\gitconfig:Git安裝目錄下的gitconfig --system系統級
2. C:\Users\Administrator\.gitconfig 只適用於當前登陸用戶的設定 --global全局
這裡可以直接編輯設定文件,通過指令設定後會影響到這裡。
### 設定用戶名與電子郵件(標示用戶,必要)
當安裝Git後首先要做的事情就是設定用戶名稱與email地址,這是非常重要的,因為每次Git提交都會使用到該設定,它被永遠的嵌入到了你的提交當中:
```
git config --global user.name "ykma" #名稱
git config --global user.email xxxxxx.gmail.com #電子郵件
```
## Git基本理論(核心)
### 工作區域
Git本機有三個工作區域:工作目錄(Working Directory)、暫存區(Stage/Index)、資源庫(Repository或Git Directory),如果再加上遠端的git倉庫(Remote Directory)就可以分為四個工作區域,檔案在這四個區域之間的轉換關係如下:

* Workspace:工作區,就是平常存放專案程式碼的地方
* Index/Stage:暫存區,用於臨時存放改動,事實上它只是一個檔案,保存即將提交到檔案列表的訊息
* Repository:倉庫區(本機倉庫),就是安全存放數據的位置,這裡面有提交到所有版本的數據,其中HEAD指向最新放入倉庫的版本
* Remote:遠端倉庫,託管程式碼的伺服器,可以想成專案團隊中的一台電腦用於遠端數據交換的
### 工作流程
git的工作流程一般是這樣的:
1. 在工作目錄中添加、修改檔案
2. 將需要進行版本管理的檔案放入暫存區
3. 將暫存區的檔案提交到git倉庫
因此,git管理的文件有三種狀態:已修改(modified)、已暫存(staged)、已提交(committed)

## Git專案搭建
### 創建工作目錄與常用指令
工作目錄(WorkSpace)一般就是希望Git幫助管理的資料夾,可以是專案目錄,也可以是一個空目錄,建議不要有中文。
日常使用只要記住下圖6個命令:

### 本機倉庫搭建
創建本機倉庫的方法有兩種:一種是創建全新的倉庫,另一種是克隆遠端倉庫。
1. 創建全新的倉庫,需要用GIT管理的項目的根目錄執行:
```
#在當前目錄創建一個Git程式碼庫
$git init
```
2. 執行後可以看到,僅僅在專案資料夾中多出一個.git資料夾,關於版本等的所有訊息都在這個資料夾裡面。
### 克隆遠端倉庫
1. 另一種方式是克隆遠端倉庫,由於是將遠端伺服器上的倉庫完全鏡像一份至本機!
```
#克隆一個專案和它的整個程式碼歷史(版本訊息)
$git clone [url]
```
## Git檔案操作
### 檔案的4種狀態
* **Untracked**:未跟蹤,此檔案在資料夾中,但並沒有加入到git庫,不參與版本控制,透過git add狀態變為Staged
* **Unmodify**:檔案已經入庫,未修改,即版本庫中的檔案快照內容與資料夾中完全一致,這種類型的檔案有兩種去處,如果他被修改,就變成Modified狀態,如果使用git rm移出版本庫,則成為Untracked檔案
* **Modified**:檔案已經修改,僅僅是修改,並沒有進行其他的操作,這個檔案也有兩個去處,透過git add可以進入暫存staged狀態,使用git checkout則丟棄修改過,返回到unmodify狀態,這個git checkout即從版本庫中取出檔案,並覆蓋當前修改!
* **Staged**:暫存狀態,執行git commit則將修改同步到庫中,這時庫中的檔案與本機檔案又變為一致,文件為Unmodify狀態,執行git reset HEAD filename取消暫存,檔案狀態為Modified
### 查看檔案狀態
上面提到檔案有4種狀態,透過如下指令可以查看到檔案的狀態:
```
#查看指定檔案狀態
git status [filename]
#查看所有檔案狀態
git status
#提交暫存區中的內容到本機倉庫 -m 提交訊息
git commit -m
```
### 忽略檔案
有時候我們不想要把某些檔案納入版本控制中,比如資料庫檔案、臨時檔案、設計檔案等等。
在主目錄下建立".gitignore"檔案,此檔案有如下規則:
1. 忽略檔案中的空行或以井字(#)開頭的將會被忽略
2. 可以使用Linux通用符號,例如:星號(*)代表任意多個字元、問號(?)代表一個字元、方括號([abc])代表可以選字元的範圍、大括號({sring1,string2,...})代表可以選的字串等。
3. 如果名稱的最前面有一個驚嘆號(!),表示例外規則,將不被忽略。
4. 如果名稱的最前面是一個路徑分隔符號(/),表示要忽略的檔案在此目錄下,而子目錄中的檔案不忽略。
5. 如果名稱的最後面是一個路徑分隔符號(/),表示要忽略的是此目錄下該名稱的子目錄,而非檔案(預設檔案或目錄都忽略)。
## 使用github
1. 註冊並完成個人資料
2. 設定本機綁定SSH公鑰,實現免密碼登入!(重要,避免每次push時寫密碼)
```
#進入 C:\Users\Administrator\.ssh目錄
#生成公鑰
ssh-keygen
```

3. 剛將公鑰添加到github帳號中即可!
4. 使用github創建一個自己的倉庫!
## IDEA中集成Git