公司內部分享之git的使用

1.簡介

1.1 關於版本控制

版本控制是一種記錄一個或若干文件內容變化,以便未來查閱特定版本修訂狀況的系統。linux

1.2 版本控制發展史

1.2.1 本地版本控制

記錄文件每次的更新,能夠對每一個版本作一個快照,或是記錄補丁文件,適合我的用,如RCS。git

1.2.2 集中式的版本控制

全部的版本數據都保存在服務器上,協同開發者從服務器上同步更新或上傳本身的修改github

全部的版本數據都存在服務器上,用戶的本地只有本身之前所同步的版本,若是不連網的話,用戶就看不到歷史版本,也沒法切換版本驗證問題,或在不一樣分支工做。並且,全部數據都保存在單一的服務器上,有很大的風險這個服務器會損壞,這樣就會丟失全部的數據,固然能夠按期備份。表明產品:SVN、CVS、VSS安全

1.2.3 分佈式版本控制系統

全部版本信息倉庫所有同步到本地的每一個用戶,這樣就能夠在本地查看全部版本歷史,能夠離線在本地提交,只需在連網時push到相應的服務器或其餘用戶那裏。因爲每一個用戶那裏保存的都是全部的版本數據,只要有一個用戶的設備沒有問題就能夠恢復全部的數據,但這增長了本地存儲空間的佔用。bash

1.3 什麼是git

Git是目前世界上最早進的分佈式版本控制系統。服務器

優勢:ssh

  • 適合分佈式開發,強調個體。
  • 公共服務器壓力和數據量都不會太大。
  • 速度快、靈活。
  • 任意兩個開發者之間能夠很容易的解決衝突。
  • 離線工做。

缺點:分佈式

  • 模式上比SVN更加複雜。
  • 不符合常規思惟。
  • 代碼保密性差,一旦開發者把整個庫克隆下來就能夠徹底公開全部代碼和版本信息。

2.本地操做

2.1 安裝git

2.1.1 window安裝

在官網下載安裝文件,雙擊打開,而後一直「NEXT」就好。 下載地址以下: git-scm.com/download/wi…工具

2.1.2 linux 安裝

若是你想在 Linux 上用二進制安裝程序來安裝 Git,可使用發行版包含的基礎軟件包管理工具來安裝。 若是以 Fedora 上爲例,你可使用 yum:學習

sudo yum install git
複製代碼

若是你在基於 Debian 的發行版上,請嘗試用 apt-get:

sudo apt-get install git
複製代碼

2.2 初始化一個本地倉庫

咱們如今要初始化一個本地倉庫:

git init
複製代碼

建立以後,目錄下會多一個".git"的文件夾,這個項目git的配置都在這個文件夾下面。通常咱們不須要修改此文件夾下的內容。

2.3 新增修改文件而且提交到git

咱們如今須要提交一個文件到git上應該如何作呢?咱們先來看一個栗子:

vi readme.md // 新增一個文件
## --- start
 這個一個git測試文件?
## --- end
git add . // 更新到暫存區
git commit -m "build: 初始化項目" // 更新到資源庫
複製代碼

執行後出現了個錯誤:

這裏是說咱們得告訴git咱們是誰,因此執行一下下面的命令

git config --global user.email "tjlovecl@example.com"
    git config --global user.name "tjlovecl"
複製代碼

再次執行 commit 命令

git commit -m "build: 初始化項目"
複製代碼

這樣文件就提交上去了。

這裏簡單說明一下:

Git本地有三個工做區域:工做目錄(Working Directory)、暫存區(Stage/Index)、資源庫(Repository或Git Directory)。

  • Workspace:工做區,就是你平時存放項目代碼的地方
  • Index / Stage:暫存區,用於臨時存放你的改動,事實上它只是一個文件,保存即將提交到文件列表信息
  • Repository:倉庫區(或本地倉庫),就是安全存放數據的位置,這裏面有你提交到全部版本的數據。其中HEAD指向最新放入倉庫的版本

總結:

  • 咱們使用 git add 工做區的文件添加到暫存區。

  • 使用 git commit -m "xxxx" 將暫存取的內容推到倉庫。裏面的內容信息能夠參照 「Conventional Commits」 書寫規則。

  • loveky.github.io/2018/06/04/…

2.4 查看歷史紀錄和狀態

咱們可使用 git status 查看狀態, 使用 git log 查看歷史紀錄。

咱們來看下面的栗子:

咱們先創建三個文件

vi a.txt // 新增 a.txt 文件
## --- start
aaa
## --- end
git add . 
git commit -m "feat: 新增a.txt文件"
vi b.txt // 新增 b.txt 文件
## --- start
bbb
## --- end
git add b.txt 
vi c.txt // 新增 c.txt 文件
## --- start
ccc
## --- end
複製代碼

咱們使用 git status 查看狀態

git status
複製代碼

咱們能夠看到 a.txt 已提交到版本庫裏面,這裏不存在, b.txt 在暫存區中, c.txt在工做區。

咱們使用 git log 查看歷史紀錄:

2.5 版本回退

2.5.1 工做區的回退

咱們先把上面栗子中的文件提交到資源庫:

git add .
    git commit -m "feat: 新增b,c模塊"
複製代碼

而後對文件進行修改:

echo ddd >> c.txt // 修改c.txt文件
    echo ddd > d.txt // 新增d.txt文件
    git status
複製代碼

咱們能夠看到, c.txt以前存在版本庫中,咱們須要把修改丟棄。 d.txt在版本庫中沒有,因此咱們須要刪除文件。 使用以下命令:

git checkout -- c.txt
    rm d.txt
複製代碼

總結:

  • 對於版本庫中存在的文件使用 git checkout -- <filename> 命令放棄修改
  • 對於版本庫中不存在的文件使用 rm <filename> 命令刪除文件

2.5.2 暫存區回退

當文件已提交到暫存區,咱們應該如何回退呢?咱們先來修改一些文件,而且提交到暫存區

echo ddd >> c.txt // 修改c.txt文件
    echo ddd > d.txt // 新增d.txt文件
    git add .
    git status
複製代碼

使用以下命令移除暫存區,讓文件回到工做區,而後使用上一節的方法丟棄修改

git reset HEAD .
    git status
複製代碼

總結:

  • 使用 git reset HEAD <filename> 命令使文件移除暫存區,回到工做區

2.5.2 資源庫版本切換

咱們先新增修改了一些文件,而且把他們提交到了暫存區,而後再新增修改一些文件,這些文件在工做區

echo ddd > d.txt // 新增 d.txt 文件
echo aaa >> a.txt // 修改 a.txt 文件
git add . // 把d.txt 和 a.txt文件加入暫存區
echo fff  > f.txt // 新增 f.txt 文件
echo bbb >> readme.md // 修改 readme.md 文件
git status
複製代碼

接下來咱們要回退到最初的版本:

咱們先查看一下歷史:

git log
複製代碼

咱們查到了版本對應的git的id,接下來使用下面命令回退

git reset --hard a8b3ad1643671b30681b33c7506bec9badee6505
   git status
複製代碼

咱們發現暫存區的文件所有丟失了,工做區的修改的文件也丟失了,只保存了工做區新增的文件。 忽然咱們發現本身回退錯版本了,須要回退到 "新增a模塊"的那個版本,咱們可使用下面命令找到因此變動的版本歷史:

git reflog
複製代碼

git reset --hard 2a39656
git log
複製代碼

PS:咱們常常看到 git reset --hard HEAD^ 這樣的命令, 這句話表示放棄修改的內容,回退當前的版本,HEAD 表示當前版本,HEAD^ 表示上一個版本, HEAD~100表示上100個版本。

總結:

  • 使用git reset --hard <版本號> 進行版本切換
  • 使用git reflog 查看全部的版本變動歷史
  • HEAD 表示當前版本

2.6 文件忽略

在項目中,又些文件咱們並不須要上傳到git,只須要保留在本地,好比配置文件,第三包下載的文件,日誌文件等。 咱們先來新建文件和文件夾。

echo abc > ignore.txt
mkdir ignore
echo abc > ignore/a.txt
git status
複製代碼

這裏咱們須要新建".gitignore"文件:

vi .gitignore
## --- start
ignore.txt  // 忽略 ignore.txt 文件
ignore/  // 忽略 ignore 文件夾
## --- end
git status
複製代碼

發現工做區只有 .gitignore文件,其餘的文件已被忽略。

總結:

  • 編輯 ".gitignore" 來忽略文件

3 分支

3.1 分支介紹

分支就是科幻電影裏面的平行宇宙,當你正在電腦前努力學習Git的時候,另外一個你正在另外一個平行宇宙裏努力學習SVN。 若是兩個平行宇宙互不干擾,那對如今的你也沒啥影響。不過,在某個時間點,兩個平行宇宙合併了,結果,你既學會了Git又學會了SVN!

分支在實際中有什麼用呢?假設你準備開發一個新功能,可是須要兩週才能完成,第一週你寫了50%的代碼,若是馬上提交,因爲代碼還沒寫完,不完整的代碼庫會致使別人不能幹活了。若是等代碼所有寫完再一次提交,又存在丟失天天進度的巨大風險。

如今有了分支,就不用怕了。你建立了一個屬於你本身的分支,別人看不到,還繼續在原來的分支上正常工做,而你在本身的分支上幹活,想提交就提交,直到開發完畢後,再一次性合併到原來的分支上,這樣,既安全,又不影響別人工做。

其餘版本控制系統如SVN等都有分支管理,可是用過以後你會發現,這些版本控制系統建立和切換分支比蝸牛還慢,簡直讓人沒法忍受,結果分支功能成了擺設,你們都不去用。

但Git的分支是不同凡響的,不管建立、切換和刪除分支,Git在1秒鐘以內就能完成!不管你的版本庫是1個文件仍是1萬個文件。

3.2 分支的建立與合併

當咱們建立新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:

你看,Git建立一個分支很快,由於除了增長一個dev指針,改改HEAD的指向,工做區的文件都沒有任何變化!

不過,從如今開始,對工做區的修改和提交就是針對dev分支了,好比新提交一次後,dev指針往前移動一步,而master指針不變:

假如咱們在dev上的工做完成了,就能夠把dev合併到master上。Git怎麼合併呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合併:

因此Git合併分支也很快!就改改指針,工做區內容也不變!

合併完分支後,甚至能夠刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉後,咱們就剩下了一條master分支:

下面開始實戰:

1)建立分支

git checkout -b dev
複製代碼

git checkout命令加上-b參數表示建立並切換,至關於如下兩條命令:

git branch dev
  git checkout dev
複製代碼

2) 查看分支

git branch
複製代碼

  1. 修改文件並提交
echo aaaa >> a.txt
git add .
git commit -m "feat: a模塊新增一行"
複製代碼
  1. 合併dev到master
git checkout master // 切回master分支
git merge dev // 合併dev分支到master
複製代碼
  1. 刪除dev分支
git branch -d dev
複製代碼

接下來咱們來探討切換分支對於暫存區和工做區文件的影響

1)咱們先來修改一些文件

echo bbb > b.txt
   git add .
   echo cccc > a.txt
   git status
複製代碼

  1. 接下來新建並切換到qa分支
git checkout -b qa
   git status
複製代碼

因此咱們能夠得出結論,有文件存在工做區或者暫存區時,切換分支後,這些文件會原封不動的帶到新的分支。

咱們能夠看一下以前的log,並無發現從dev合併到master的痕跡,那麼又沒有辦法能夠在日誌裏面留下點痕跡?

咱們能夠在merge命令中增長 "--no--ff"參數, 咱們已上面的qa分支爲例

git add .
   git commit -m "feat: 新增b文件"
   git checkout master
   git merge --no-ff -m "chore: qa分支合併到master上" qa
   git log --graph --pretty=oneline --abbrev-commit
複製代碼

總結:

1)Git鼓勵大量使用分支:

查看分支:git branch

建立分支:git branch <name>

切換分支:git checkout <name>或者git switch <name>

建立+切換分支:git checkout -b <name>或者git switch -c <name>

合併某分支到當前分支:git merge <name>

刪除分支:git branch -d <name>
複製代碼

2)有文件存在工做區或者暫存區時,切換分支後,這些文件會原封不動的帶到新的分支。

3)合併分支時,加上 --no-ff 參數就能夠用看出歷史有分支曾經作過合併。

3.3 解決衝突

人生不如意之事十之八九,合併分支每每也不是一路順風的。

咱們先修改一下master分支的a.txt文件

echo master >> a.txt
 git add .
 git commit -m "feat: 新增一行master"
複製代碼

咱們再切到qa分支上,修改a.txt文件

git checkout qa
 echo qa >> a.txt
 git add .
 git commit -m "feat: 新增一行qa"
複製代碼

而後咱們再master分支合併一下

git checkout master
 git merge --no-ff -m "chore: qa分支合併到master上" qa
 git status
複製代碼

咱們打開 a.txt

Git用<<<<<<<,=======,>>>>>>>標記出不一樣分支的內容。 ======= 上面的內容爲當前分支的內容,下面的爲合併過來分支的內容咱們作相應的修改,而後提交.

git add .
git commit -m "chore: 解決qa合併到master的衝突"
複製代碼

小結:

  • 當Git沒法自動合併分支時,就必須首先解決衝突。解決衝突後,再提交,合併完成。

  • 解決衝突就是把Git合併失敗的文件手動編輯爲咱們但願的內容,再提交。

3.4 bug分支

軟件開發中,bug就像屢見不鮮同樣。有了bug就須要修復,在Git中,因爲分支是如此的強大,因此,每一個bug均可以經過一個新的臨時分支來修復,修復後,合併分支,而後將臨時分支刪除。

當你接到一個修復一個代號101的bug的任務時,很天然地,你想建立一個分支bug-101來修復它,可是,等等,當前正在dev上進行的工做尚未提交:

echo tmpEdit >> a.txt 
git add .
echo tmpEdit2 >> b.txt
git status
複製代碼

咱們可使用 stash命令把修改儲藏起來

git stash 
   git status
複製代碼

咱們再建立bug-101分支進行修改

git checkout -b bug-101
   echo bbb >> b.txt
   git add .
   git commit -m "fix: 修正bug101"
複製代碼

切回master分支,而且合併

git checkout master
   git merge --no-ff -m "chore: bug101合併到master上" bug-101
複製代碼

取出儲藏的修改

git stash list
   git stash pop
   git status
複製代碼

咱們發現b.txt文件衝突了,根據上面的內容解決衝突就能夠了。

總結: 修復bug時,咱們會經過建立新的bug分支進行修復,而後合併,最後刪除; 當手頭工做沒有完成時,先把工做現場git stash一下,而後去修復bug,修復後,再git stash pop,回到工做現場。 通常咱們都是切獨立分支修改的,因此這個方法咱們用的不是特別多。

4 遠程倉庫的使用

上面的章節裏面,咱們介紹了git的本地使用,知道了在本地各版本之間進行穿梭。 但這僅限於咱們本身玩,若是要你們一塊兒工做完成一個項目,勢必須要遠程倉庫。

雖然git是分佈式的,你們能夠相互傳輸文件,但其實不多在兩人之間的電腦上推送版本庫的修改,由於可能大家倆不在一個局域網內,兩臺電腦互相訪問不了,也可能今天你的同事病了,他的電腦壓根沒有開機。所以,分佈式版本控制系統一般也有一臺充當「中央服務器」的電腦,但這個服務器的做用僅僅是用來方便「交換」你們的修改,沒有它你們也同樣幹活,只是交換修改不方便而已。而爲了方便管理,咱們通常會把託管平臺選爲「中央服務器」。

4.1 託管平臺

託管平臺能夠是第三方提供的,如github,碼雲等,也能夠是咱們本身搭建的(公司使用gogs本身搭建了一個)。各類託管平臺操做大同小異,下面我就用第三方提供的github來看成咱們的「中央處理器」。

接下來咱們在github上新建一個項目:

1) 註冊登錄github

2) 新建倉庫

4.2 本地倉庫與遠程倉庫關聯

在倉庫頁面,咱們有兩種關聯倉庫的方式,咱們使用SSH的方式來關聯。

執行下面命令:

git remote add origin git@github.com:tjlovecl/git_yanshi.git // 關聯遠程倉庫
git push -u origin master
複製代碼

執行完成後會報一個權限驗證不經過的錯誤。

要消除這個錯誤,須要把咱們服務器的SSH公鑰放到github上。

4.2.1 生成ssh公鑰

咱們使用下面命令生成公鑰和私鑰。

ssh-keygen -t rsa 
 ll ~/.ssh
複製代碼

把公鑰的內容複製到gitthub上。

cat ~/.ssh/id_rsa.pub
複製代碼

咱們再執行一次,就能夠把master 分支推到遠程倉庫中去了。

git push -u origin master
複製代碼

小結:

  • 咱們使用 git remote add origin <遠程地址> 關聯遠程倉庫
  • 第一次使用 git push -u origin master 推送
  • 使用SSH協議,須要配置SSHkey
  • 之後再次推送直接使用 git push 便可

4.3 推送遠程分支和刪除遠程分支

咱們把qa推送到遠程倉庫:

git checkout qa 
   git push --set-upstream origin qa //第一次使用和遠程qa分支想關聯
複製代碼

之後可使用下面命令來推送

git push
複製代碼

使用下面命令來刪除遠程分支:

git push origin --delete qa 
複製代碼

4.4 從遠程倉庫克隆

若是咱們本地沒有倉庫,須要把線上的倉庫克隆下來,可使用下面的命令,這裏咱們使用http的方式

cd ~
    git clone https://github.com/tjlovecl/git_yanshi.git -b qa yanshi
複製代碼

咱們來解釋一下里面的兩個參數

  • -b qa: 表示克隆qa分支,若是不加,默認拷貝master分支
  • yanshi: 把克隆下來的內容放在"yanshi"文件夾下面

若是咱們咱們本地有倉庫,只要拷貝線上的分支到本地: 可使用以下命令:

cd yanshi
   git checkout -b master origin/master
複製代碼

小結:

  • 使用 git clone github.com/tjlovecl/gi… [-b 分支名] [目錄名] 來克隆倉庫
  • 使用 git checkout -b [本地分支名] origin/[線上分支名] 來克隆線上分支
  • 咱們不建議使用htts的方式,由於https除了慢,還要常常輸入口令很是麻煩

思考題

若是咱們遠程分支推錯了怎麼辦?

5. 操做git的兩種工做流程

1)第一種

  1. 把遠程的dev分支拷貝到本地
  2. 修改dev分支,並push給遠程倉庫
  3. 遠程倉庫把dev分支合併到qa
  4. 遠程倉庫把qa合併到prod

2)第二種

  1. 從遠程prod分支check出一個tmp分支
  2. 修改tmp分支,把tmp分支合併到遠程倉庫的dev
  3. 把tmp分支合併到遠程倉庫的qa
  4. 把tmp分支合併到遠程倉庫的prod

思考題:

這兩種方式孰優孰劣?咱們應該如何選擇?

相關文章
相關標籤/搜索