Git 詳細介紹和使用
Git 詳細介紹和使用
一、介紹
git /gɪt/ 是一個開源的分散式版本控制系統
最初是 Linus Torvalds 為了幫助管理 Linux 核心開發而開發的一個開放原始碼的版本控制軟體
1.1 版本控制
版本控制是一種記錄一個或若干檔案內容變化,以便將來查閱特定版本修訂情況的系統。可以對任何型別的檔案進行版本控制,便於不同的開發者協同工作
集中式版本控制
集中化的版本控制系統是為了讓不同系統上的開發者協同工作。例如 SVN,它會有一個單一的集中管理的伺服器,儲存所有檔案的修訂版本,而協同工作的人通過客戶端連線到這臺伺服器,拉取最新的檔案或者是提交更新
在這個系統中,每個人可以看到專案中其他人的工作,管理員也能很好的掌握和分配每個開發者的許可權。但由於版本庫是集中在伺服器上的,如果出現了中央伺服器的單點故障,在這個時間內,誰都無法提交更新,而且整個專案的歷史記錄被儲存在單一位置,就有丟失所有歷史更新記錄的風險
分散式版本控制
分散式的版本控制解決了集中化版本控制的一些問題,客戶端並不只提取最新版本的檔案快照,而是把程式碼倉庫完整地映象下來。這麼一來,任何一處協同工作用的伺服器發生故障,事後都可以用任何一個映象出來的本地倉庫恢復。因為每一次的克隆操作,實際上都是一次對程式碼倉庫的完整備份
更進一步,許多這類系統都可以指定和若干不同的遠端程式碼倉庫進行互動。籍此,你就可以在同一個專案中,分別和不同工作小組的人相互協作。你可以根據需要設定不同的協作流程,比如層次模型式的工作流,而這在以前的集中式系統中是無法實現的
1.2 Git 介紹
直接記錄快照,而非差異比較
Git 儲存的不是檔案的變化或者差異,而是一系列不同時刻的檔案快照
Git 把資料看作是對小型檔案系統的一組快照。 每次提交更新,或在 Git 中儲存專案狀態時,它會對當時的全部檔案製作一個快照並儲存這個快照的索引。 為了高效,如果檔案沒有修改,Git 不再重新儲存該檔案,而是隻保留一個連結指向之前儲存的檔案。Git 對待資料更像是一個快照流
近乎所有操作都是本地執行
在 Git 中的絕大多數操作都只需要訪問本地檔案和資源,因為你在本地磁碟上就有專案的完整歷史,所以大部分操作看起來瞬間完成,
Git 保證完整性
Git 中所有資料在儲存前都計算校驗和,然後以校驗和來引用
Git 一般只新增資料
執行的 Git 操作,幾乎只往 Git 資料庫中增加資料
1.3 Git安裝
Linux 上安裝
Linux 上使用 yum 安裝,yum install git
$ sudo yum install git
Windows 上安裝
官網上下載安裝包安裝即可
配置使用者資訊
安裝完後需要設定使用者名稱稱和郵件地址,這樣做很重要,因為每一個 Git 的提交都會使用這些資訊,並且它會寫入到你的每一次提交中,不可更改
$ git config --global user.name "zou"
$ git config --global user.email [email protected]
配置完後可以使用 git config --list
檢視配置資訊
使用了 --global 選項,表示全域性配置,那麼該命令只需要執行一次,因為之後無論你在該系統上做任何事情, Git 都會使用那些資訊。 當你想針對特定專案使用不同的使用者名稱稱與郵件地址時,可以在那個專案目錄下執行沒有 --global 選項的命令來配置
二、Git 工作區、暫存區和版本庫
在瞭解 Git 的基本操作之前,我們先來了解 Git 工作區、暫存區和版本庫的概念
在 Git 中的檔案有三種狀態:已提交(committed): 表示資料已經安全的儲存在本地資料庫中;已修改(modified): 表示修改了檔案,但還沒儲存到資料庫中;已暫存(staged): 表示對一個已修改檔案的當前版本做了標記,使之包含在下次提交的快照中
由此也引入了 Git 專案的三個工作區域的概念:
- 工作區: 就是專案檔案所在的目錄
- 暫存區: stage 或 index。一般存放在
.git/index
檔案中,所以我們把暫存區有時也叫作索引 - 版本庫: 工作區下隱藏目錄
.git
,這裡記錄著倉庫的版本資訊和歷史記錄
下面這個圖展示了工作區、版本庫中的暫存區和版本庫之間的關係:
下面我們通過建立倉庫和基本操作來了解這三個工作區域的關係
三、Git 倉庫建立及基本操作
3.1 建立 Git 倉庫
倉庫也叫版本庫(repository),可以簡單理解成一個目錄,這個目錄裡面的所有檔案都可以被 Git 管理起來,每個檔案的修改、刪除,Git都能跟蹤,以便任何時刻都可以追蹤歷史,或者在將來某個時刻可以還原
建立並初始化倉庫
git init
是用來初始化一個 Git 倉庫的
git init
該命令會在當前目錄下建立一個 .git
的目錄,這個子目錄含有你初始化的 Git 倉庫中所有的必須檔案。這個時候只是對倉庫做了初始化的操作,假如該目錄下原本就有檔案,需要對這些檔案進行版本控制,可以通過 git add <file>
跟蹤這些檔案並提交 git commit -m <message>
git add .
git commit -m 'initial project version'
上面是把目錄下的所有檔案提交到了倉庫中
克隆現有的倉庫
如果想獲取現有 Git 倉庫的拷貝,需要用 git clone <repo>
或 git clone <repo> <directory>
repo 是倉庫地址,directory 是本地倉庫的名稱,即目錄名稱
如下面我要克隆 github 上的一個倉庫,並制定本地倉庫的名稱為 mylibname
git clone https://github.com/xxxx/xxxx mylibname
3.2 基本操作
工作目錄下的每一個檔案有這兩種狀態:
已跟蹤
已經納入了版本控制的檔案,在上一次快照中有它們的記錄,它們的狀態可能處於 未修改,已修改 或 已放入暫存區。未跟蹤
即還沒有加入到版本控制的檔案
新增的未跟蹤檔案(untracked),和編輯過被 Git 記為已修改的檔案(modified)。 通過 git add
放入暫存區(staged),然後 git commit
提交所有暫存了的修改,提交後的檔案即為未修改檔案(unmodified),如此反覆
操作命令:
git status
檢視檔案狀態git add
新增檔案到暫存區,包括未跟蹤和修改的檔案git diff
檢視修改內容git commit
提交更新,新增暫存區的內容到本地倉庫git reset HEAD
取消暫存git rm
移除檔案git mv
移動檔案
這裡我新建一個 demo 目錄作為倉庫,並初始化這個倉庫
接下來我們使用上面新建的倉庫 demo,並對裡面的檔案做一些操作
先建立一個新的檔案 touch readme.txt
1、檢視當前檔案狀態
要檢視倉庫目錄下哪些檔案處於狀態狀態,使用 git status
命令
Untracked files
未被跟蹤的檔案Changes not staged for commit
修改的檔案Changes to be committed
暫存狀態檔案
可以看到新建的檔案 readme.txt
的檔案狀態為 untracked
,並提示我們要通過 git add <file>
命令去跟蹤我們需要提交的檔案
如果使用
git status -s
命令或git status --short
命令,將得到一種更為緊湊的格式輸出
2、跟蹤新檔案/ 暫存已修改的檔案
使用命令 git add <file>
開始跟蹤一個檔案或暫存修改的檔案,會把檔案新增到暫存區
git add readme.txt
再次使用 git status
命令檢視,會看到 readme.txt 檔案已經被跟蹤,並處於暫存狀態。Changes to be committed
下的檔案就是處於暫存狀態
git add
命令使用檔案或目錄的路徑作為引數;如果引數是目錄的路徑,該命令將遞迴地跟蹤該目錄下的所有檔案
該命令還用來暫存已修改的檔案,就是 Changes not staged for commit
下的檔案
3、檢視已暫存和未暫存的修改
這個時候假如我們對暫存的檔案進行了修改
echo 'My Project' > readme.txt
使用 git status
命令檢視,我們可以看到多出了一個未被暫存,被修改狀態的檔案,而使用 git status
命令並不能看到具體修改的地方,這時可以用 git diff
來檢視未暫存的檔案更新的部分
輸入 git diff
來檢視未暫存的檔案更新的部分
該命令比較的是工作目錄中當前檔案和暫存區域快照之間的差異, 也就是修改之後還沒有暫存起來的變化內容。若要檢視已暫存的將要新增到下次提交裡的內容,可以用 git diff --cached
命令
-
git diff
尚未暫存的改動 -
git diff --cached
檢視已暫存的改動
4、提交更新
當暫存區的檔案已經準備妥當可以提交了,可以通過命令 git commit
來提交,或者直接加入說明 git commit -m <message>
git commit
這種方式會啟動文字編輯器以便輸入本次提交的說明(這裡的編輯器是 vim)
使用 git commit -m <message>
請記住,提交時記錄的是放在暫存區域的快照。 任何還未暫存的仍然保持已修改狀態,可以在下次提交時納入版本管理。 每一次執行提交操作,都是對你專案作一次快照,以後可以回到這個狀態,或者進行比較
跳過使用暫存區域
Git 提供了一個跳過使用暫存區域的方式, 只要在提交的時候,給
git commit
加上-a
選項,Git 就會自動把所有已經跟蹤過的檔案暫存起來一併提交,從而跳過git add
步驟
5、取消暫存
git reset HEAD <file>...
用來取消已暫存的內容
我們修改下 readme.txt ,並 git add
到暫存區
echo 'modify content' > readme.txt
git add readme.txt
通過 git status
可以看到 readme.txt 已經新增到暫存區了
假如這時不想把它提交更新並加入到下一次的快照當中,就可以通過git reset HEAD <file>
去取消已暫存的內容
git reset HEAD readme.txt
撤消對檔案的修改
如果你想撤銷對檔案的修改,也就是還原到未修改前的狀態,可以使用
git checkout -- [file]
命令。該命令會取消你對該檔案做的修改內容。
6、移除檔案
假如我們現在去刪除 readme.txt 這個檔案,再通過 git status
檢視狀態
它是會記錄我們的刪除操作,標記為未暫存的檔案
然後再執行 git rm <file>
記錄此次移除檔案的操作
下次提交更新 git commit
之後,該檔案就不再納入版本控制管理中了
如果刪除之前修改過並且已經放到暫存區域的話,則必須要用強制刪除選項 -f
,即git rm -f <file>
如果把檔案從暫存區域移除,但仍然希望保留在當前工作目錄中,換句話說,僅是從跟蹤清單中刪除,使用 --cached
選項即可
7、移動檔案
git mv
命令用於移動或重新命名一個檔案、目錄、軟連線。
我們先撤銷對 readme.txt 檔案的刪除
git reset HEAD readme.txt
git checkout -- readme.txt
然後使用 git mv
對其重新命名
git mv readme.txt README.md
四、Git 主要功能
4.1 遠端倉庫(github)
上面我們有關的命名操作都是本地執行,如果需要分享程式碼或與其他開發人員協同工作,就需要連線遠端倉庫了。這個遠端倉庫是指託管在因特網或其他網路中的你的專案的版本庫
這裡我們使用 github 作為遠端倉庫
1、新增遠端倉庫
執行 git remote add <shortname> <url>
新增一個新的遠端 Git 倉庫
這裡是以 github 做為遠端倉庫為例,本地 Git 倉庫和 GitHub 倉庫之間的傳輸是通過SSH加密的,我們需要先配置驗證資訊
使用以下命令生成 SSH Key
ssh-keygen -t rsa -C "[email protected]"
這裡的郵箱為你 github 賬號繫結的郵箱,生成 SSH Key 後我們去到它儲存的路徑 ~/.ssh
下開啟 id_rsa.pub
複製裡面的公鑰
然後我們去到 github 的設定中心找到 SSH and GPG keys,點選 New SSH key 設定 SSH 公鑰
將複製的 SSH 公鑰新增並儲存
為了驗證是否成功,使用命令 ssh -T [email protected]
接下來我們在 github上去新建一個倉庫
建立成功後,顯示以下資訊
上面會有一些提示,允許我們建立一個新的本地倉庫或把已存在的倉庫推到 github倉庫上,這裡我們直接把直接的 demo 上傳到這個 github 倉庫中
git remote add origin https://github.com/Morgan412/demo.git
git push -u origin master
第一次會讓我們輸入 github 的賬號密碼
git push
會把本地倉庫的內容推送到遠端倉庫中,這時可以重新整理下 github 的倉庫頁面,會發現已經有上傳的內容了
推送到遠端倉庫的命令為: git push [remote-name] [branchname]
2、檢視當前的遠端倉庫
檢視你已經配置的遠端倉庫伺服器,可以執行 git remote
命令, 它會列出你指定的每一個遠端伺服器的簡寫,也可以指定選項 -v
,會顯示需要讀寫遠端倉庫使用的 Git 儲存的簡寫與其對應的 URL
如果想要檢視某一個遠端倉庫的更多資訊,可以使用 git remote show [remote-name]
命令
3、從遠端倉庫中抓取與拉取
從遠端倉庫獲取資料的命令
git fetch [remote-name]
這個命令會訪問遠端倉庫,從中拉取所有你還沒有的資料,git fetch origin
會抓取克隆(或上一次抓取)後新推送的所有工作。 必須注意 git fetch
命令會將
資料拉取到你的本地倉庫,當它並不會自動合併或修改你當前的工作,這個時候我們可以執行 git merge [alias]/[branch]
來合併分支
現在我們在 github 的遠端倉庫中修改 README.md 檔案,然後執行 git fetch origin
可以看到資訊提示遠端倉庫的 master 有更新,這時再執行 git merge origin/master
README.md 檔案被合併更新
如果你有一個分支設定為跟蹤一個遠端分支,可以使用
git pull <remote> <branch>
命令來自動的抓取然後合併遠端分支到當前分支。預設情況下,git clone
命令會自動設定本地 master 分支跟蹤克隆的遠端倉庫的 master 分支。 執行git pull
通常會從最初克隆的伺服器上抓取資料並自動嘗試合併到當前所在的分支。
4、遠端倉庫的移除與重新命名
git remote rename
去修改一個遠端倉庫的簡寫名
git remote rm [name]
可以去移除一個遠端倉庫
4.2、標籤管理
Git 可以給歷史中的某一個提交打上標籤,可以使用這個功能來標記釋出結點(如v1.0),標籤也是版本庫的一個快照
命令:
-
git tag
檢視所有的標籤 -
git tag <name>
建立標籤 -
git tag -v <name> -m <message>
建立附註標籤 -
git push origin [tagname]
推送標籤到遠端倉庫 -
git tag -d <tagname>
刪除本地倉庫標籤 -
git push <remote> :refs/tags/<tagname>
更新遠端倉庫標籤
1、建立標籤
建立標籤命令 git tag <name>
git tag -v <name> -m <message>
可以建立一個附註標籤
首先我們要切換到需要打標籤的分支上,然後使用建立標籤命令 git tag <name>
git tag v1.0.0
git tag
可以檢視所有的標籤
後期打標籤
預設情況下,標籤是打在最新提交 commit 上的,假如我想對過去的某個歷史快照節點打標籤呢?其實也是可以的
git log --pretty=oneline --abbrev-commit
檢視歷史 commit id,然後打上對應標籤即可
$ git log --pretty=oneline --abbrev-commit
459f6fc (HEAD -> master, origin/master) Update README.md
e241626 修改內容
a9dec5d first commit
如我要給 “修改內容” 這次 commit 打上標籤
git tag v1.0.1 e241626
2、標籤操作
共享標籤
預設情況下,git push
命令並不會傳送標籤到遠端倉庫伺服器上。 在建立完標籤後你必須顯式地推送標籤到共享伺服器上。 這個過程就像共享遠端分支一樣,你可以執行 git push origin [tagname]
如果想要一次性推送很多標籤,也可以使用帶有 --tags
選項的 git push
命令。 這將會把所有不在遠端倉庫伺服器上的標籤全部傳送到那裡
刪除標籤
使用命令 git tag -d <tagname>
可以刪除掉本地倉庫上的標籤
上面的命令並不會從任何遠端倉庫中移除這個標籤,如果要移除遠端倉庫的標籤必須使用 git push <remote> :refs/tags/<tagname>
來更新你的遠端倉庫
4.3 分支管理
分支就像是科幻電影裡面的平行宇宙,當你正在電腦前努力學習Git的時候,另一個你正在另一個平行宇宙裡努力學習SVN
如果兩個平行宇宙互不干擾,那對現在的你也沒啥影響。不過,在某個時間點,兩個平行宇宙合併了,結果,你既學會了Git又學會了SVN!
在實際工作中,當你需要完成某個需要,而這個需求你可能需要2天才能完成,這時你可以新建一個分支,在分支上的任何改動都是不影響其他分支的,當你完成了需求之後,再合併分支
命令:
-
git branch
列出分支,當前分支前面會標一個*
號 -
git branch <branchname>
建立分支 -
git checkout <branchname>
切換分支 -
git checkout -b <branchname>
建立並切換分支 -
git merge
合併分支 -
git branch -d <branchname>
刪除分支
分支的建立和合並
建立分支
git branch <branchname>
git checkout <branchname>
想要新建一個分支並同時切換到那個分支上,你可以執行一個帶有 -b
引數的 git checkout
命令,等同於上面兩個命令
git checkout -b newb
git branch
列出分支,當前分支前面會標一個*
號
合併分支
一旦某分支有了獨立內容,你終究會希望將它合併回到你的主分支
使用 git merge
命令將任何分支合併到當前分支中去
假如我們現在對新的分支內容有了修改,現在要合併到主分支中
合併衝突
當Git無法自動合併分支時,就必須首先解決衝突。解決衝突後,再提交,合併完成
解決衝突就是把 Git 合併失敗的檔案手動編輯為我們希望