「產品前端架構」版本控制

版本控制

版本管理涉及團隊協作,產品質量,和產品上線。使用版本控制工具可使我們自由的做的一些幾點:

  • 回退到任意版本
  • 查看歷史版本
  • 對比兩個版本差異

版本控制系統

版本控制系統(Version Control System)是一種記錄若干文件修訂記錄的系統,它可以幫助開發者查閱或回檔至某個歷史版本。

  • 手動版本控制
  • LVCS 本地
  • CVCS 集中式(例如 SVN)
  • DVCS 分布式(例如 Git)

手動版本控制

vc-manual.png

無法有效找到需要版本和差異,污染工作目錄結構。

Local VCS 本地式

vc-vcs.png

于是出現了本地版本控制系統 RCS(Reversion Control System),其利用本地版本數據庫存儲不斷出現的文件版本。
它可以迅速找出需求的版本和維持工作目錄結構。其缺點是不支持協同開發,這也讓開發者不將其選做通用的版本控制工具來使用。

CVCS 集中式

vc-svn.png

利用中央服務器來管理文件版本,但每一次操作都需要網絡請求,且具有致命的單點故障。
(既中央服務器故障可導致,無法協同工作或數據丟失)

DVCS 分布式

vc-git.png

分布式指的是每一份本地倉庫都是一個完整的項目歷史拷貝,即使一份倉庫丟失或者損壞也可以從其他的倉庫中獲取此項目的完整歷史記錄。
也因為在添加新版本不需要網絡,這可以使操作流程。

分支模型

如果多人并行在一條線上開發會導致開發困難并且難以定位錯誤位置。

vc-git-branch.png

分支,就是從目標倉庫獲得一份項目拷貝,每條分支都具有和原倉庫功能一樣的開發線。

分支模型(Branching Model)或稱之為工作流(Workflow),它是一個圍繞項目
開發部署、測試等工作流的分支操作(創建及合并等)的規范集合。

產品級開發分支模型

常駐分支

  • development,從 master 創建
  • production(master),默認分支可用于發布的代碼

活動分支

  • feature,從 development,創建其為特性分支
  • hotfix,從 master 創建,用于修復 Bug
  • release,從 development 創建
vc-production.png

環境

vs-environment.jpg
  • 開發環境,使用測試開發配置(數據庫,緩存,元數據配置)
    • 使用提交到下一個 release 的特性分支
  • 測試環境,使用測試配置(測試數據庫)
    • 使用 release/development
  • 預發布環境,小范圍發布使用線上數據庫模擬真實環境
    • 使用 release
  • 生產環境,線上配置
    • 使用 master

Git

Git 是一個免費開源的分布式版本控制系統,它也一個基于內容尋址的存儲系統。
Git 是由 Linux 的創造者 Linus Torvalds。

優勢

  • 速度快,不依賴網絡
  • 完全分布式
  • 輕量級分支操作
  • Git 為行業標準版本控制供給
  • 活躍和成熟的社區

安裝

Mac OS X 下使用 brew install git 下載更新既可。

Linux Ubuntu 下可使用 apt-get install git 既可。

Git 介紹

Git 命令

常用 Git 命令,當在命令行中鍵入 git 可以便可以在幫助信息中看到。

git_command.png

獲取幫助

git help <command> git <command> -h git <command> --help 還有
man git-<command> 均可查詢某個命令的幫助文檔。

基本操作

配置 Git 使用 git config 此為創建 Git 倉庫前必須完成的配置。

git config --global user.name "Li Xinyang"
git config --global user.email "lixinyang1026@gmail.com"
  • --local 默認 具有最高優先級 只影響本倉庫 .git/config
  • --global 中級優先級 影響到所有當前用戶的倉庫 ~/.gitconfig
  • --system 最低優先級 影響到全系統的倉庫 /etc/gitconfig

初始化倉庫

git-init.png

初始化倉庫,使用 git status 可以查詢當前倉庫的狀態。
如在未初始化倉庫時查詢狀態會報出錯誤信息。

git init [path]
git init [path] --bare

在初始化倉庫后會出現一個隱藏的目錄 .git
其中包括了所有的當前倉庫的版本信息和本地設置文件(.git/config)。

git-after-init.png

查詢狀態

git status 此命令可以幫助開發者在下面三對關系中找出文件狀態的變化。

  • 未跟蹤 <--> 跟蹤
  • 工作目錄 <--> 暫存區
  • 暫存區 <--> 最新提交
git-status-kind.jpg

Git 中存在兩種狀態內容狀態文件狀態。
倉庫中的文件均可以在狀態和區域之間進行轉換。

git-first-file.png

添加文件到暫存區(同時跟蹤文件)

git add [file]

git-add-file.png

上圖所示,我們將 README.md 文件從工作區提交至暫存區,
并將文件狀態從未跟蹤改變成已跟蹤。

git-first-step.jpg

NOTE:批量增加當前目錄下全部文件 git add .

git-add-multiple.png

忽略文件

.gitignore 可以在添加至倉庫時忽略匹配的文件,但僅作用于未跟蹤的文件。

git-sample-gitignore.png

NOTE:GitHub 為各個類型項目和操作系統提供了忽略文件模板,
可以在這里找到。

暫存區刪除文件

使用 git rm 可以做到從暫存區刪除文件,下面提供幾種常用的使用方法:

  • git rm --cached 僅存暫存區刪除
  • git rm 才暫存區和工作區目錄中刪除
  • git rm $(git ls-files --deleted) 刪除所有被跟蹤但在工作區已經被刪除的文件

NOTE:git-ls-files

  • Show information about files in the index and the working tree

工作區與暫存區

不同的區域中可以存在文件的獨立版本,如下圖所示工作區和暫存區的文件為兩個不同的版本。
(之前上個例子中所創建的 DummyFile 文件已被刪除)

git-file-multiple-version.png

暫存區

我們可以把暫存區比作一個每類物品只能放置一次的購物車此外還具有下面的特質:

  • 貨架和購物車可同時出現同種物品
  • 貨架上的物品可以替換掉購物車的物品
  • 可以刪除物品
  • 提交購物車完成購買并生成購買記錄

其中

  • 物品:文件
  • 貨架:工作目錄
  • 購物車:暫存區
  • 購買:提交內容

提交版本記錄

git-commit.png

git commit 可以根據暫存區的內容創建一個提交目錄。

git-first-commit.png

NOTE:直接提交工作區的內容git commit -a -m 'message',工作中不建議這樣操作。

查詢提交歷史記錄

git log 可以用來顯示提交是記錄信息。

git-log.png

其中包括:

  • 提交編號 SHA-1 編碼的 HASH 標示符
  • git-config 配置的提交者信息
  • 提交日期
  • 提交描述信息

工作中可使用下面簡單的配置進行版本查詢

git log --oneline

# 較長的命令可以使用 alias 的方法簡化
git log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit

Git 中 alias 命令設置

配置 Git 中別名的方法 git config alias.shortname <fullcommand>。

git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

git lg

NOTE:如果你使用 Mac OS X 可以嘗試使用 Oh My Zsh
其中已經預先設置好了非常多常用別名。

顯示版本差異

git-diff-terminal.png

git diff 用于顯示版本差異,下面是幾個常用的方法:

  • git diff 顯示工作目錄與暫存區的差異
  • git diff -cached [<reference>] 暫存區與某次提交的差異(默認為 HEAD)
  • git diff <reference> 工作目錄和某次提交間的差異
  • git diff <reference> <reference> 查詢兩次提交直接的差別
git-diff-overview.png

撤銷工作區的修改

git-checkout-file.jpg

git checkout -- <file>... 可用于撤銷工作區的修改
(此方法會丟棄工作區修改且不可恢復),下面是一些常用方法:

  • git checkout -- <file> 將文件從暫存區復制到工作目錄
git-checkout-file-terminal.png

NOTE:使用 -- 是為了避免路徑和引用(或提交 ID)同名發生的沖突。

撤銷暫存區內容

git-reset-head.jpg

使用 git reset HEAD <file>... 可用于撤銷暫存區的修改,下面是一些常用操作:

  • git reset HEAD <file> 將文件內容存上次提交復制到暫存區。
git-reset-head-terminal.png

撤銷全部修改

git-reset-everything.png

git checkout HEAD -- <file> 可以直接將內容從上次的提交復制到工作區。

git-reset-everything-terminal.png

命令總結

git-command-overview.jpg

分支操作

git branch

使用 git branch 可以對倉庫分支進行增刪查改的操作,下面列舉了一下常用的操作方式:

  • git branch <branchname>,創建指定分支
  • git branch -d <branchname>,刪除指定分支
  • git branch -v,顯示所有分支信息

一份分支的引用只是一個文本文件,里面只有一個 SHA 編碼。它保存于 .get/refs/heads/master 中。

—— 鄭海波 網易工程師

git branch next
git-brnach-next.png
git commit -m 'message'
git-commit-after-next.png

切換至目標分支

git checkout 它可以本枝上根據通過移動 HEAD(指向當前的提交) 檢測出版本,
也可用于切換分支。(其會把當前的工作目錄和暫存區移動到提出分支的版本)
常用命令有:

  • git checkout <branchname>,使指針指向目標分支
  • git checkout -b <branchname>,創建目標分支并切換分支
  • git checkout <reference>,可以指向任何一個版本
git checkout next
git-checkout-next-head.png

NOTE:所有提交是更具 HEAD 向前進的,所以前后分支后則會跟著 Next 分支進行開發。

git commit -m 'message'
git-next-first-commit.png
# -- 為短名與 cd 類似
git checkout --

# 或者使用
# git checkout master
git-next-back-master.png
git checkout -b Issue-26
git-new-b-branch.png

NOTE:使用 git branch -v 可以列出全部分支,帶 *
表示當前所屬分支(HEAD 指向分支)。

git checkout c4006ec
git-checkout-reference.png

當 HEAD 指針與具體的分支分離時,我們將其稱之為 detached head。
如果 HEAD 在分離狀態則因盡量避免在此狀態下進行提交,只做內容的查看。

git-checkout-reference-view.png

完全回退

git-reset-current.jpg

使用git reset可以將當前分支回退到歷史中的某個版本,
下面為常用的三種方式(三種的區別是恢復的內容時候同時會恢復的工作區或暫存區):

  • git reset --mixed <commit> 默認方式,內容存入暫存區
  • git reset --soft <commit> 內容存入暫存區和工作區
  • git reset --hard <commit> 暫存區和工作區保留現有狀態
git reset --mixed e390b3
git-reset-mixed.jpg

如果上一個命令如果使用 hard

git reset --hard e390b3
git-reset-hard.jpg

如果上一個命令如果使用 hard

get reset --soft e390b3
git-reset-soft.jpg

此方法暫存區和工作目錄不會發生任何變化僅僅只是 HEAD 指針發生了變化,
但原有的提交已經無指針指向成為無索引的提交其就有可能被回收。

查詢所有提交記錄

git reflog 會根據倉庫的提交順序按順序來排列,其中包括無索引的提交,
可以在這里使用 HASH 值來進行,但是無索引的提交可能會丟失。

使用捷徑

A^ 表示 A上的父提交,多個 ^ 可表示以上的多個級別。
A~n 則表示在 A 之前的第 n 次提交。

git-move-head.jpg
reset 與 checkout 區別

兩種方法都有兩個作用范圍,一個是分支操作(commit 操作),
另一個是文件操作(file 操作)。

命令 范例 移動 HEAD/Branch 注釋
git reset [commit] git reset HEAD^ --soft 是/是 完全回退到某個提交(之前所在的位置將失去索)
git reset [file] git reset README.md 否/否 恢復暫存區到某個提交狀態(不移動指針)
git checkout [commit] git checkout master 是/否 移動當前指針 HEAD 到某個提交(并復制內容到工作目錄)
git checkout [file] git checkout -- README.md git checkout HEAD -- xx.log 否/否 恢復工作目錄到某個狀態
stash 的作用
git checkout next

# error: Your local change to the following files whould be overwritten by checkout:
#       README.md
# Please, commit your changes or stash them before you can switch branches.
# Aborting...

突然需要切換到其他分支,工作區和暫存區還有在當前分支沒完成的任務。那么 stash 就使用 .git 中的特殊區(Stash 區)來幫你解決這個問題(因為強切回丟失當前的工作區和暫存區的內容)。

git-stash-overview.png
git-stash-terminal.png

stash 可以把當前工作區和暫存區的狀態以棧(Stack)的形式保存起來(每次保存都會推一個內容到 stash 棧中),并返回一個干凈的工作空間(工作區和暫存區)。

NOTE:stash pop = stash apply + stash drop 類似于 JavaScript 中的 pop 操作。

NOTE+:什么是棧?可以把棧想象成一摞盤子堆(一個疊一個)。具體關于堆棧的信息可以在這里找到。如果還看不懂,建議完成哈佛大學在線計算機入門課程 CS50,可以在這里找到。

merge
git-merge-overview.jpg

使用 git merge 可用于合并分支。下面的例子是將 next 分支合并到 master 分支中去。

git-merge-detail.jpg
git-merge-detail-after.jpg
git-merge-detail-terminal.png
解決 merge 沖突

當一個文件被同時修改時(更多情況為同時修改相同的一行代碼時)則極有可能產生合并沖突。

git merge next master
# Autom-merging README.md
# CONFLICT (content): Merge confilict in README.md
# Automatic merge failed; fix confilict and then commit the result

git status
# On branch master
# You have unmerged paths.
#   (fix confilict and run 'git commit')
# ...
#   both:modified: README.md
# no changes added to commit (use "git add" and/or "git commit -a")
git-merge-conflic-code-sample.png

在解決完合并沖突后可以使用 git add . 然后 git commit -m 'resove merge confilict' 來完成合并沖突解決并提交一個新的版本。

NOTE:git cat-file -p HEAD 可用于顯示 git 中某個對象的具體信息。
NOTE+:<<<<<<<< HEAD========= 之間為 HEAD 所在的內容。

merge fast-forward

也并不是所有的合并操作都會造成合并從圖(merge confilic)。最簡單的一種合并是 fast-forward 僅僅只是變化 HEAD 指向的位置(不產生新的合并節點)。

git-fast-forward0.png

如果需要生成新的合并節點可以使用 git merge next --no-ff 意思是合并但不使用 fast-forward。

git-fast-forward-no-ff.jpg
merge 不足
git-merge-bad.jpg

當參與的人閱讀分支越多其分支結構就越復雜和難以被理解。如何實現在任何狀態下的線性提交

如需完成線性提交可以使用 git rebase,其可以修剪提交歷史的基線。它會將不同分支的提交在所選節點上進行重演(重演并重新創造新節點)這里 HEAD/Branch 均會發生移動。

git rebase master
git-rebase-0.jpg

但有時并不需要將其他分支上的全部提交節點統統進行重演。則可以使用 git rebase --onto 來選擇需要重演的提交節點。

git rebase --onto master 5751363
git-rebase-onto.jpg

NOTE:上面的紅色的節點,未被重建(被丟棄)。

rebase 與 merge 區別
git-mergerebase.png

rebase 會產生線性的提交歷史,merge 則會產生多個不同分支的合并節點。所以具體沒有好壞之分,可根據使用的需求來決定。

注意!不要在共有分支上使用 rebase(例如 master 分支)這會導致其他開發者在進行拉取(Pull)時,必須進行合并且合并中包含重復的提交。

tag

不論是 Branch 還是 HEAD 它們均為動態指針,如果想定義一個靜止的標示則可以使用 git tag ,它將給發布的提交版本設置一個別名。在設置了標簽后就可以直接使用標簽名來代替它所指代的版本提交了。

git tag v0.1 e39d9b2

git checkout v0.1
git-tag.jpg

遠程操作

遠程操作可以將本地倉庫推送至遠程倉庫服務器。Git 支持許多主流的通信協議,其中包括 Local、HTTP、SSH、還有Git。服務器只應該是作為同步之用(被動接受既可)。

初始化一個本地的遠程服務器

git init ~/git-server --bare
git-local-server.png

推送

git push 可以將當期的全部版本提交提交推送至遠程倉庫,其完成了提交歷史的完全不復制并同時移動復制版本的 HEAD 與 Branch。

git-push.png

添加遠程倉庫別名

git remote 可用于添加遠程倉庫的別名。

git-remote.png
# 更改倉庫 url 地址
git remote set-url origin 'https://github.com/li-xinyang/FEND_Note.git'

遠程 push 沖突

可以先使用 git fetch + git merge 來解決沖突的問題。git pull 就等同于 fetchmerge 的合并。

克隆遠程倉庫

使用 git clone 可以克隆遠程倉庫,并將克隆地址默認設為 origin

git-clone.png
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容

  • Git 基礎 基本原理 客戶端并不是只提取最新版本的文件快照,而是把代碼倉庫完整的鏡像下來。這樣一來,任何一處協同...
    __silhouette閱讀 15,926評論 5 147
  • Git 命令行學習筆記 Git 基礎 基本原理 客戶端并不是只提取最新版本的文件快照,而是把代碼倉庫完整的鏡像下來...
    sunnyghx閱讀 3,944評論 0 11
  • Git常用語法 [TOC] Git簡介 描述 ? Git(讀音為/g?t/。)是一個開源的分布式版本控制系統,...
    君惜丶閱讀 3,565評論 0 13
  • 通過判斷瀏覽器的userAgent,用正則來判斷是否是ios和Android客戶端 檢查是否是移動端(Mobile...
    jia林閱讀 4,781評論 0 6
  • 五月底,感覺人都變的懶散了起來。 半月前單位組織合唱比賽迎接七一,基本每周一下班后都會集合練習。 我國是講究集體性...
    甲方_5d38閱讀 247評論 0 0