git /gɪt/ 是一個開源的分佈式版本控制系統git
最初是 Linus Torvalds 爲了幫助管理 Linux 內核開發而開發的一個開放源碼的版本控制軟件github
版本控制是一種記錄一個或若干文件內容變化,以便未來查閱特定版本修訂狀況的系統。能夠對任何類型的文件進行版本控制,便於不一樣的開發者協同工做shell
集中式版本控制數據庫
集中化的版本控制系統是爲了讓不一樣系統上的開發者協同工做。例如 SVN,它會有一個單一的集中管理的服務器,保存全部文件的修訂版本,而協同工做的人經過客戶端鏈接到這臺服務器,拉取最新的文件或者是提交更新vim
在這個系統中,每一個人能夠看到項目中其餘人的工做,管理員也能很好的掌握和分配每一個開發者的權限。但因爲版本庫是集中在服務器上的,若是出現了中央服務器的單點故障,在這個時間內,誰都沒法提交更新,並且整個項目的歷史記錄被保存在單一位置,就有丟失全部歷史更新記錄的風險安全
分佈式版本控制bash
分佈式的版本控制解決了集中化版本控制的一些問題,客戶端並不僅提取最新版本的文件快照,而是把代碼倉庫完整地鏡像下來。這麼一來,任何一處協同工做用的服務器發生故障,過後均可以用任何一個鏡像出來的本地倉庫恢復。由於每一次的克隆操做,實際上都是一次對代碼倉庫的完整備份服務器
更進一步,許多這類系統均可以指定和若干不一樣的遠端代碼倉庫進行交互。籍此,你就能夠在同一個項目中,分別和不一樣工做小組的人相互協做。你能夠根據須要設定不一樣的協做流程,好比層次模型式的工做流,而這在之前的集中式系統中是沒法實現的網絡
直接記錄快照,而非差別比較ssh
Git 保存的不是文件的變化或者差別,而是一系列不一樣時刻的文件快照
Git 把數據看做是對小型文件系統的一組快照。 每次提交更新,或在 Git 中保存項目狀態時,它會對當時的所有文件製做一個快照並保存這個快照的索引。 爲了高效,若是文件沒有修改,Git 再也不從新存儲該文件,而是隻保留一個連接指向以前存儲的文件。Git 對待數據更像是一個快照流
近乎全部操做都是本地執行
在 Git 中的絕大多數操做都只須要訪問本地文件和資源,由於你在本地磁盤上就有項目的完整歷史,因此大部分操做看起來瞬間完成,
Git 保證完整性
Git 中全部數據在存儲前都計算校驗和,而後以校驗和來引用
Git 通常只添加數據
執行的 Git 操做,幾乎只往 Git 數據庫中增長數據
Linux 上安裝
Linux 上使用 yum 安裝,yum install git
$ sudo yum install git
複製代碼
Windows 上安裝
官網上下載安裝包安裝便可
配置用戶信息
安裝完後須要設置用戶名稱和郵件地址,這樣作很重要,由於每個 Git 的提交都會使用這些信息,而且它會寫入到你的每一次提交中,不可更改
$ git config --global user.name "zou"
$ git config --global user.email zouxq412@foxmail.com
複製代碼
配置完後可使用 git config --list
查看配置信息
使用了 --global 選項,表示全局配置,那麼該命令只須要運行一次,由於以後不管你在該系統上作任何事情, Git 都會使用那些信息。 當你想針對特定項目使用不一樣的用戶名稱與郵件地址時,能夠在那個項目目錄下運行沒有 --global 選項的命令來配置
在瞭解 Git 的基本操做以前,咱們先來了解 Git 工做區、暫存區和版本庫的概念
在 Git 中的文件有三種狀態:已提交(committed): 表示數據已經安全的保存在本地數據庫中;已修改(modified): 表示修改了文件,但還沒保存到數據庫中;已暫存(staged): 表示對一個已修改文件的當前版本作了標記,使之包含在下次提交的快照中
由此也引入了 Git 項目的三個工做區域的概念:
.git/index
文件中,因此咱們把暫存區有時也叫做索引.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
複製代碼
工做目錄下的每個文件有這兩種狀態:
已跟蹤
已經歸入了版本控制的文件,在上一次快照中有它們的記錄,它們的狀態可能處於 未修改,已修改 或 已放入暫存區。未跟蹤
即尚未加入到版本控制的文件新增的未跟蹤文件(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
要查看倉庫目錄下哪些文件處於狀態狀態,使用 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
命令,將獲得一種更爲緊湊的格式輸出
使用命令 git add <file>
開始跟蹤一個文件或暫存修改的文件,會把文件添加到暫存區
git add readme.txt
複製代碼
再次使用 git status
命令查看,會看到 readme.txt 文件已經被跟蹤,並處於暫存狀態。Changes to be committed
下的文件就是處於暫存狀態
git add
命令使用文件或目錄的路徑做爲參數;若是參數是目錄的路徑,該命令將遞歸地跟蹤該目錄下的全部文件
該命令還用來暫存已修改的文件,就是 Changes not staged for commit
下的文件
這個時候假如咱們對暫存的文件進行了修改
echo 'My Project' > readme.txt
複製代碼
使用 git status
命令查看,咱們能夠看到多出了一個未被暫存,被修改狀態的文件,而使用 git status
命令並不能看到具體修改的地方,這時能夠用 git diff
來查看未暫存的文件更新的部分
輸入 git diff
來查看未暫存的文件更新的部分
該命令比較的是工做目錄中當前文件和暫存區域快照之間的差別, 也就是修改以後尚未暫存起來的變化內容。若要查看已暫存的將要添加到下次提交裏的內容,能夠用 git diff --cached
命令
git diff
還沒有暫存的改動git diff --cached
查看已暫存的改動當暫存區的文件已經準備穩當能夠提交了,能夠經過命令 git commit
來提交,或者直接加入說明 git commit -m <message>
git commit
複製代碼
這種方式會啓動文本編輯器以便輸入本次提交的說明(這裏的編輯器是 vim)
使用 git commit -m <message>
請記住,提交時記錄的是放在暫存區域的快照。 任何還未暫存的仍然保持已修改狀態,能夠在下次提交時歸入版本管理。 每一次運行提交操做,都是對你項目做一次快照,之後能夠回到這個狀態,或者進行比較
跳過使用暫存區域
Git 提供了一個跳過使用暫存區域的方式, 只要在提交的時候,給
git commit
加上-a
選項,Git 就會自動把全部已經跟蹤過的文件暫存起來一併提交,從而跳過git add
步驟
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]
命令。該命令會取消你對該文件作的修改內容。
假如咱們如今去刪除 readme.txt 這個文件,再經過 git status
查看狀態
它是會記錄咱們的刪除操做,標記爲未暫存的文件
而後再運行 git rm <file>
記錄這次移除文件的操做
下次提交更新 git commit
以後,該文件就再也不歸入版本控制管理中了
若是刪除以前修改過而且已經放到暫存區域的話,則必需要用強制刪除選項 -f
,即git rm -f <file>
若是把文件從暫存區域移除,但仍然但願保留在當前工做目錄中,換句話說,僅是從跟蹤清單中刪除,使用 --cached
選項便可
git mv
命令用於移動或重命名一個文件、目錄、軟鏈接。
咱們先撤銷對 readme.txt 文件的刪除
git reset HEAD readme.txt
git checkout -- readme.txt
複製代碼
而後使用 git mv
對其重命名
git mv readme.txt README.md
複製代碼
上面咱們有關的命名操做都是本地執行,若是須要分享代碼或與其餘開發人員協同工做,就須要鏈接遠程倉庫了。這個遠程倉庫是指託管在因特網或其餘網絡中的你的項目的版本庫
這裏咱們使用 github 做爲遠程倉庫
運行 git remote add <shortname> <url>
添加一個新的遠程 Git 倉庫
這裏是以 github 作爲遠程倉庫爲例,本地 Git 倉庫和 GitHub 倉庫之間的傳輸是經過SSH加密的,咱們須要先配置驗證信息
使用如下命令生成 SSH Key
ssh-keygen -t rsa -C "zouxq412@foxmail.com"
複製代碼
這裏的郵箱爲你 github 帳號綁定的郵箱,生成 SSH Key 後咱們去到它保存的路徑 ~/.ssh
下打開 id_rsa.pub
複製裏面的公鑰
而後咱們去到 github 的設置中心找到 SSH and GPG keys,點擊 New SSH key 設置 SSH 公鑰
將複製的 SSH 公鑰添加並保存
爲了驗證是否成功,使用命令 ssh -T git@github.com
接下來咱們在 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]
查看你已經配置的遠程倉庫服務器,能夠運行 git remote
命令, 它會列出你指定的每個遠程服務器的簡寫,也能夠指定選項 -v
,會顯示須要讀寫遠程倉庫使用的 Git 保存的簡寫與其對應的 URL
若是想要查看某一個遠程倉庫的更多信息,可使用 git remote show [remote-name]
命令
從遠程倉庫獲取數據的命令
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
一般會從最初克隆的服務器上抓取數據並自動嘗試合併到當前所在的分支。
git remote rename
去修改一個遠程倉庫的簡寫名
git remote rm [name]
能夠去移除一個遠程倉庫
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>
更新遠程倉庫標籤建立標籤命令 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
複製代碼
共享標籤
默認狀況下,git push
命令並不會傳送標籤到遠程倉庫服務器上。 在建立完標籤後你必須顯式地推送標籤到共享服務器上。 這個過程就像共享遠程分支同樣,你能夠運行 git push origin [tagname]
若是想要一次性推送不少標籤,也可使用帶有 --tags
選項的 git push
命令。 這將會把全部不在遠程倉庫服務器上的標籤所有傳送到那裏
刪除標籤
使用命令 git tag -d <tagname>
能夠刪除掉本地倉庫上的標籤
上面的命令並不會從任何遠程倉庫中移除這個標籤,若是要移除遠程倉庫的標籤必須使用 git push <remote> :refs/tags/<tagname>
來更新你的遠程倉庫
分支就像是科幻電影裏面的平行宇宙,當你正在電腦前努力學習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 合併失敗的文件手動編輯爲咱們但願的內容,再提交