淺析git

淺析git

筆者在此整理了常見的git命令,git的重要性無需多言,與其再百度海中搜索git命令,不妨嘗試收藏筆者的此篇作品。希望對你的學習有所幫助。
  • 版本控制系統之git

Git:

(一)簡介:
Git 是一款免費的、開源的、分佈式的版本控制系統。旨在快速高效地處理無論規模大小的任何軟件工程。
每一個 Git克隆 都是一個完整的文件庫,含有全部歷史記錄和修訂追蹤能力,不依賴於網絡連接或中心服務器。其最大特色就是“分支”及“合併”操作非常快速、簡便。

(二)Git與svn的主要區別:
Git是分佈式SCM,而SVN是基於服務器的,也就是說每個開發者本地都有一套git庫,每個人維護自己的版本(或者合併其他人的版本),而SVN是每個人寫完代碼後都及時的checkin到服務器上,進行合併。

  • Git的優勢:

說到優勢,那麼自然是相對與SVN而言的
1.版本庫本地化,支持離線提交,相對獨立不影響協同開發。每個開發者都擁有自己的版本控制庫,在自己的版本庫上可以任意的執行提交代碼、創建分支等行爲。例如,開發者認爲自己提交的代碼有問題?沒關係,因爲版本庫是自己的,回滾歷史、反覆提交、歸併分支並不會影響到其他開發者。

2.更少的“倉庫污染”。git對於每個工程只會產生一個.git目錄,這個工程所有的版本控制信息都在這個目錄中,不會像SVN那樣在每個目錄下都產生.svn目錄。

3.把內容按元數據方式存儲,完整克隆版本庫。所有版本信息位於.git目錄中,它是處於你的機器上的一個克隆版的版本庫,它擁有中心版本庫上所有的東西,例如標籤、分支、版本記錄等。

4.支持快速切換分支方便合併,比較合併性能好。在同一目錄下即可切換不同的分支,方便合併,且合併文件速度比SVN快。

5.分佈式版本庫,無單點故障,內容完整性好。內容存儲使用的是SHA-1哈希算法。這能確保代碼內容的完整性,確保在遇到磁盤故障和網絡問題時降低對版本庫的破壞。

  • 本地創建git遠程倉庫:

我這裏使用的是:centos7.2、並且在服務器中已經創建git賬戶;如果沒有創建git賬戶的朋友,需要先創建git,並且在服務器端安裝git

1.在本地建立一個空白的git倉庫:
Git –bare init
注:--bare參數相當與只創建一個空白的倉庫,只包含記錄版本庫歷史記錄的.git目錄下面的文件,不會包含實際項目源文件的拷貝;

2.將本地創建的倉庫添加到遠程服務器,使用的linux上傳命令;
Scp –r 文件夾 linux用戶名@ip:/文件目錄
如:scp –r gittest.git [email protected]:/data./git
(這裏是將本地的gittest.git文件夾拷貝到服務器中 /data/git文件夾下)

3.此時可以直接將本地的gittest文件夾關聯遠程倉庫,也可以在本地再次克隆git倉庫;使用命令如下:
Git clone [email protected]:/data/git/gittest.git

4.可以直接創建一個文件,進行上傳測試;如:
cd gittest 進入文件夾
vi app.js 然後隨便輸入字符,esc+wq!進行保存退出;
然後將操作添加至暫存區:
Git add .
創建本地倉庫的版本:
Git commit –m “haha”
提交至遠程服務器倉庫:
Git push origin master;
注:如果此時出現此種錯誤:
remote: error: insufficient permission for adding an object to repository database ./objects
這時注意自己的服務器git賬戶是否有寫的權限;一般是因爲git賬戶對gittest.git文件夾權限不夠;此時登陸自己的服務器,給git賬戶進行權限的賦予;命令爲:
Chown –R git:git /data/git/gittest.git
權限操作完畢後,再次進行本地倉庫與遠程倉庫的同步,一般此時不再會進行報錯;
注:服務器git倉庫的創建也可以直接在linux操作系統中進行;

  • 本地git創建倉庫與github的遠程倉庫相關聯:

1.首先登陸github官網;進行註冊、登錄

2.創建新的倉庫

3.在本地創建git倉庫

mkdir githubtest
git init
vi app.js
注:https協議和ssh協議的區別就是每次遠程操作都需要輸入github的用戶名和密碼;
4.https協議:
Git remote add origin https://github.com/misterguan...
Git add .
Git commit –m “haha”
Git push –u origin master
此時需要輸入github的用戶名和密碼

此時會報錯: error: failed to push some refs to
(此種原因一般爲在github的遠程倉庫有文件,在本地倉庫沒有,所以此時應該先將遠程倉庫合併到本地倉庫,再進行提交)
git pull --rebase origin master
注意:這裏的rebase和merge的區別,簡單理解,rebase在log中無分叉,而merge有
再次提交,將會成功;

  • ssh協議:

首先需要創建密鑰
ssh-keygen –t rsa –C [email protected]
可以一路回車;
(Enter file in which to save the key (/c/Users/dream/.ssh/id_rsa):
這裏默認就可以,這是存放ssh密鑰的路徑)

(Enter passphrase (empty for no passphrase):這裏爲ssh的密碼,可以爲空)

然後到C:Users用戶 .ssh中找到id_rsa.pub,然後複製裏面的密鑰到github
例:C:Usersdream.ssh
在github的ssh and gpg keys中new ssh key
Title爲此ssh的標記
Key爲你本地的密鑰
測試下:
ssh [email protected]
如果輸出You've successfully authenticated;說明鏈接成功;
下面的操作跟https的一樣:

  • Git的分支管理:

查看本地分支:$ git branch
查看遠程分支:$ git branch -r
創建本地分支:$ git branch [name] ----注意新分支創建後不會自動切換爲當前分支
切換分支:$ git checkout [name]
創建新分支並立即切換到新分支:$ git checkout -b [name]
刪除分支:$ git branch -d [name] ---- -d選項只能刪除已經參與了合併的分支,對於未有合併的分支是無法刪除的。如果想強制刪除一個分支,可以使用-D選項
合併分支:$ git merge [name] ----將名稱爲[name]的分支與當前分支合併
創建遠程分支(本地分支push到遠程):$ git push origin [name]
刪除遠程分支:$ git push origin :heads/[name] 或 $ gitpush origin :[name] 

項目開發的分支:
Master:用於發佈版本的分支;(用於大版本號更新時使用)
Dev:開發時的主分支;
Feature:功能分支;(開發某個局部分支,從dev分支上分出來的)
Release:創建一個預發佈分支(從dev分支上分出來,合併到master分支上,進行tag標註)
Bug:bug分支(從master分支上分出來,修改完畢後合併到master和dev分支)

分支合併
在git進行分支的合併時
如果使用默認的fast-farward merge
直接修改當前HEAD指針的指向然後再修改當前HEAD指針,說白了就是修改兩個指針的指向,而並沒有生成新的commit對象。

如果使用—no-ff 進行合併
這樣會在master分支上創建一個版本;

  • git如何解決代碼衝突:

1.邏輯衝突
git自動處理(合併/應用補丁)成功,但是邏輯上是有問題的。
比如另外一個人修改了文件名,但我還使用老的文件名,這種情況下自動處理是能成功的,但實際上是有問題的。
又比如,函數返回值含義變化,但我還使用老的含義,這種情況自動處理成功,但可能隱藏着重大BUG。這種問題,主要通過自動化測試來保障。所以最好是能夠寫出比較完備的自動化測試用例。
這種衝突的解決,就是做一次BUG修正。不是真正解決git報告的衝突。
2.內容衝突
兩個用戶修改了同一個文件的同一塊區域,git會報告內容衝突。我們常見的都是這種,後面的解決辦法也主要針對這種衝突。如圖中是:app.js衝突:
圖片描述

然後手動修改衝突的文件:
圖片描述
再次進行文件的提交,版本的創建;
3.樹衝突
文件名修改造成的衝突,稱爲樹衝突。
比如,a用戶把app.js改名爲master.js,b用戶把app.js文件改名爲test.js,那麼b將這兩個commit合併時,會產生衝突。
圖片描述
此時打開文件,把需要的刪除的文件刪除掉即可,如把master.js刪除掉;
圖片描述
然後,再次重新創建版本即可:

  • git常用操作命令:

1.查看、添加、提交、刪除、找回,重置修改文件
git help <command> # 顯示command的help
git show # 顯示某次提交的內容 git show $id
git co -- <file> # 拋棄工作區修改
git co . # 拋棄工作區修改
git add <file> # 將工作文件修改提交到本地暫存區
git add . # 將所有修改過的工作文件提交暫存區
git rm <file> # 從版本庫中刪除文件
git rm <file> --cached # 從版本庫中刪除文件,但不刪除文件
git reset <file> # 從暫存區恢復到工作文件
git reset -- . # 從暫存區恢復到工作文件
git reset --hard # 恢復最近一次提交過的狀態,即放棄上次提交後的所有本次修改
git ci <file> git ci . git ci -a # 將git add, git rm和git ci等操作都合併在一起做                                    git ci -am "some comments"
git ci --amend # 修改最後一次提交記錄
git revert <$id> # 恢復某次提交的狀態,恢復動作本身也創建次提交對象
git revert HEAD # 恢復最後一次提交的狀態
2.查看文件diff
git diff <file> # 比較當前文件和暫存區文件差異 git diff
git diff <id1><id1><id2> # 比較兩次提交之間的差異
git diff <branch1>..<branch2> # 在兩個分支之間比較
git diff --staged # 比較暫存區和版本庫差異
git diff --cached # 比較暫存區和版本庫差異
git diff --stat # 僅僅比較統計信息
3.查看提交記錄
git log git log <file> # 查看該文件每次提交記錄
git log -p <file> # 查看每次詳細修改內容的diff
git log -p -2 # 查看最近兩次詳細修改內容的diff
git log --stat #查看提交統計信息
tig
Mac上可以使用tig代替diff和log,brew install tig

4.查看、切換、創建和刪除分支
git br -r # 查看遠程分支
git br <new_branch> # 創建新的分支
git br -v # 查看各個分支最後提交信息
git br --merged # 查看已經被合併到當前分支的分支
git br --no-merged # 查看尚未被合併到當前分支的分支
git co <branch> # 切換到某個分支
git co -b <new_branch> # 創建新的分支,並且切換過去
git co -b <new_branch> <branch> # 基於branch創建新的new_branch
git co $id # 把某次歷史提交記錄checkout出來,但無分支信息,切換到其他分支會自動刪除
git co $id -b <new_branch> # 把某次歷史提交記錄checkout出來,創建成一個分支
git br -d <branch> # 刪除某個分支
git br -D <branch> # 強制刪除某個分支 (未被合併的分支被刪除的時候需要強制)
5. 分支合併和rebase
git merge <branch> # 將branch分支合併到當前分支
git merge origin/master --no-ff # 不要Fast-Foward合併,這樣可以生成merge提交
git rebase master <branch> # 將master rebase到branch,相當於: git co <branch> && git rebase master && git co master && git merge <branch>
6. Git補丁管理(方便在多臺機器上開發同步時用)
git diff > ../sync.patch # 生成補丁
git apply ../sync.patch # 打補丁
git apply --check ../sync.patch #測試補丁能否成功
7. Git暫存管理
git stash # 暫存
git stash list # 列所有stash
git stash apply # 恢復暫存的內容
git stash drop # 刪除暫存區
8.Git遠程分支管理
git pull # 抓取遠程倉庫所有分支更新併合併到本地
git pull --no-ff # 抓取遠程倉庫所有分支更新併合併到本地,不要快進合併
git fetch origin # 抓取遠程倉庫更新
git merge origin/master # 將遠程主分支合併到本地當前分支
git co --track origin/branch # 跟蹤某個遠程分支創建相應的本地分支
git co -b <local_branch> origin/<remote_branch> # 基於遠程分支創建本地分支,功能同上
git push # push所有分支
git push origin master # 將本地主分支推到遠程主分支
git push -u origin master # 將本地主分支推到遠程(如無遠程主分支則創建,用於初始化遠程倉庫)
git push origin <local_branch> # 創建遠程分支, origin是遠程倉庫名
git push origin <local_branch>:<remote_branch> # 創建遠程分支
git push origin :<remote_branch> #先刪除本地分支(git br -d <branch>),然後再push刪除遠程分支
9.Git遠程倉庫管理
GitHub
git remote -v # 查看遠程服務器地址和倉庫名稱
git remote show origin # 查看遠程服務器倉庫狀態
git remote add origin git@ github:robbin/robbin_site.git # 添加遠程倉庫地址
git remote set-url origin git@ github.com:robbin/robbin_site.git # 設置遠程倉庫地址(用於修改遠程倉庫地址) git remote rm <repository> # 刪除遠程倉庫
10.創建遠程倉庫
git clone --bare robbin_site robbin_site.git # 用帶版本的項目創建純版本倉庫
scp -r my_project.git git@ git.csdn.net:~ # 將純倉庫上傳到服務器上
mkdir robbin_site.git && cd robbin_site.git && git --bare init # 在服務器創建純倉庫
git remote add origin git@ github.com:robbin/robbin_site.git # 設置遠程倉庫地址
git push -u origin master # 客戶端首次提交
git push -u origin develop # 首次將本地develop分支提交到遠程develop分支,並且track
git remote set-head origin master # 設置遠程倉庫的HEAD指向master分支
也可以命令設置跟蹤遠程庫和本地庫
git branch --set-upstream master origin/master
git branch --set-upstream develop origin/develop

  • 項目自動化:

現在的前端開發已經不再僅僅只是靜態網頁的開發了,日新月異的前端技術已經讓前端代碼的邏輯和交互效果越來越複雜,更加的不易於管理,模塊化開發和預處理框架把項目分成若干個小模塊,增加了最後發佈的困難,沒有一個統一的標準,讓前端的項目結構千奇百怪。前端自動化構建在整個項目開發中越來越重要。

(一)工具化
在前端的技術棧發展過程中,出現了很多的工具,形成了工具化,能夠用工具完成的絕不要手工完成,來幫助開發者提升效率。

  1. 前端工作流工具: Gulp,Grunt
  2. 前端js模塊編譯工具:Babel,Browserify,Webpack
  3. 包管理器: npm,bower
  4. 前端開發系列工具: livereload,數據mock,代碼監控,代碼檢查。

(二)工程化
工程化是一個發展趨勢,以工具化爲基礎。

工程的核心是流程自動化,又稱爲構建,這些包括了:代碼質量檢測,代碼壓縮,代碼合併,代碼優化,代碼編譯,單元測試等等部分。構建就是把這些以工作流程的方式組合起來,然後用一個命令行運行這整個流程。它有點像批處理,但是是程序開發中使用的特殊批處理。

(三)自動化
自動化是以工程化爲基礎,是在流程自動化上更進一步的自動化。
持續集成就是全自動化的一個終極體現。他的主要流程是:版本控制庫 ->構建 ->測試 ->報告.

(四)代碼規範
代碼規範可以提高代碼的可閱讀性和避免一些低級錯誤。爲了將代碼規範的檢查放到前端開發工程中,各種前端語言都有對應的hint或者lint工具。

(五)預處理
SASS
甚至爲了避免這一點,引入了各種預編譯語言,css的預編譯less,現在流行的是sass,功能也更加強大,語法錯誤無法通過編譯,來彌補css這種缺陷。

(六)ES6
js的預處理語言也有很多,只是爲了讓有其他語言經驗的開發者更容易的上手js的編碼。

因爲瀏覽器的實現大多還是 ES5 的標準,爲了使用最新的 ES6 語法,通常的做法是採用 Babel 將 ES6 編譯爲 ES5。

(七)js模塊化
amd,cmd,common,es6

(八)文件處理
通常一個前端項目會分有一個 src 目錄和 dist 目錄, src 放置源碼,dist 放置編譯後的代碼。所以在前端工程的流程中會涉及到文件的拷貝,刪除,移動等流程。

(九)開發效率
通常的前端開發過程是,修改前端代碼,調用命令編譯代碼,然後瀏覽器 F5 刷新。這個過程可以做到自動化,通過代碼監控工具,指定要監控的目錄和文件,如果對應文件有改變,調用編譯工具編譯源碼,然後通過 livereload 自動刷新瀏覽器。 gulp-browserify也可以實現同樣的功能。

(十)數據的mock
現代化前端項目開發大多是前後端分離的方式,也就是後端基本是提供 API 服務,在真實開發環境中,通常的問題是,後端 API 極其不穩定或者沒開發,爲了不阻礙前端的開發,通常的做法是,前後端先約定 API 接口定義,然後前端根據定義 mock 接口。

(十一)前端工作流
爲了解決前端工程中複雜的流程,出現了很多開源前端流程處理工具。這些工作流工具不僅僅是其本身,都是一個流程生態體系,每個工具都涉及到對應的插件庫,幾乎我們能想到的前端工程問題都有對用的插件能夠解決。

  • Gulp:

Gulp 是基於node.js的一個前端自動化構建工具,開發這可以使用它構建自動化工作流程(前端集成開發環境)。 
使用gulp你可以簡化工作量,讓你把重點放在功能的開發上,從而提高你的開發效率和工作質量。 gulpjs是一個前端構建工具,與gruntjs相比,gulpjs無需寫一大堆繁雜的配置參數,API也非常簡單,學習起來很容易,而且gulpjs使用的是nodejs中stream來讀取和操作數據,其速度更快

(一)安裝:
需要在全局或者項目中同時安裝;
Cnpm install -g gulp
Cnpm install –save-dev gulp

(二)配置文件

使用gulpfile.js進行配置,基於gulp工作流的項目結構如下:
圖片描述

(三)Api:

1.gulp.src(globs[, options]) 輸出(Emits)符合所提供的匹配模式(glob)或者匹配模式的數組(array of globs)的文件。 將返回一個 Vinyl files 的 stream 它可以被 piped 到別的插件中。文件的入口
A.路徑匹配:
1)*  :能匹配 a.js,x.y,abc,abc/,但不能匹配a/b.js
2).  :能匹配 a.js,style.css,a.b,x.y
3)//*.js  :能匹配 a/b/c.js,x/y/z.js,不能匹配a/b.js,a/b/c/d.js
4)** 能匹配 : abc,a/b.js,a/b/c.js,x/y/z,x/y/z/a.b,能用來匹配所有的目錄和文件
5)*/.js  :能匹配 foo.js,a/foo.js,a/b/foo.js,a/b/c/foo.js
6)a/**/z  :能匹配 a/z,a/b/z,a/b/c/z,a/d/g/h/j/k/z
7)a/b/z  :能匹配 a/b/z,a/sb/z,但不能匹配a/x/sb/z,因爲只有單單獨出現才能匹配多級目錄
8)?.js  :能匹配 a.js,b.js,c.js
9)a??  :能匹配 a.b,abc,但不能匹配ab/,因爲它不會匹配路徑分隔符
10)[xyz].js  :只能匹配 x.js,y.js,z.js,不會匹配xy.js,xyz.js等,整個中括號只代表一個字符
11)1.js  :能匹配 a.js,b.js,c.js等,不能匹配x.js,y.js,z.js

B.匹配多種文件
//使用數組的方式來匹配多種文件
gulp.src(['js/.js','css/.css','*.html'])

2.gulp.dest(path[, options]) 能被 pipe 進來,並且將會寫文件。並且重新輸出(emits)所有數據,因此你可以將它 pipe 到多個文件夾。如果某文件夾不存在,將會自動創建它。輸出文件
根路徑:如果在src中不設置base時,所有的默認根路徑,都是從出現匹配符的地方開始截取:
如:
gulp.src('app/src/*/.css') //此時base的值爲app/src,也就是說它的base路徑爲app/src

 //設該模式匹配到了文件 app/src/css/normal.css
.pipe(gulp.dest('dist')) //用dist替換掉base路徑,最終得到 dist/css/normal.css

如果增加base基路徑:

gulp.src(script/lib/*.js, {base:'script'}) //配置了base參數,此時base路徑爲script //假設匹配到的文件爲script/lib/jquery.js .pipe(gulp.dest('build')) //此時生成的文件路徑爲 build/lib/jquery.js
3.gulp.task(name[, deps], fn) 定義一個使用 Orchestrator 實現的任務(task)。

1)參數:
Name:任務的名字,如果你需要在命令行中運行你的某些任務,那麼,請不要在名字中使用空格。
Deps:類型: Array,一個包含任務列表的數組,這些任務會在你當前任務運行之前完成。
Fn:該函數定義任務所要執行的一些操作。

2)異步任務
A.使用callback:

var gulp = require('gulp');
// 返回一個 callback,因此係統可以知道它什麼時候完成
gulp.task('one', function(cb) {

// 做一些事 -- 異步的或者其他的
cb(err); // 如果 err 不是 null 或 undefined,則會停止執行,且注意,這樣代表執行失敗了

});
// 定義一個所依賴的 task 必須在這個 task 執行之前完成
gulp.task('two', ['one'], function() {

// 'one' 完成後

});

gulp.task('default', ['two']);

B.使用promise

var gulp = require('gulp');
// 返回一個 callback,因此係統可以知道它什麼時候完成
gulp.task('one', function(cb) {

// 做一些事 -- 異步的或者其他的
return new Promise((res, rej) => {
    setTimeout(() => {
        res(1344)
    }, 5000)
})

});
// 定義一個所依賴的 task 必須在這個 task 執行之前完成
gulp.task('two', ['one'], function() {

// 'one' 完成後
console.log("two開始")

});

gulp.task('default', ['two']);
注意:5s後纔開始執行的two任務

3)對於同步任務:

  gulp.task('one',function(cb){
    var stream = gulp.src('client/**/*.js')
        .pipe(dosomething()) //dosomething()中有某些異步操作
        .pipe(gulp.dest('build'));
      return stream;
  });
  
  gulp.task('two',['one'],function(){
    console.log('two is done');
  });


4.gulp.watch(glob[, opts], tasks)監視文件,並且可以在文件發生改動時做一些事情;
1)監聽文件改變,並執行相應的task任務
var watcher = gulp.watch('js/*/.js', ['uglify', 'reload']);
watcher.on('change', function(event) {

console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');

});

2)監聽文件改變,並執行回調函數

gulp.watch('js/*/.js', function(event) {

console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');

});

(四)第三方插件:

1.gulp-load-plugins:用來加載插件,避免我們再頭部聲明一堆插件,做到想用就用
2.less:用於編譯 .less文件
3.autoprefixer:自動添加css前綴
4.babel:es6 編譯成 es5
5.uglify:JS壓縮
6.minify:CSS壓縮
7.rename:重命名
8.sourcemaps:資源映射
9.concat:合併文件
10.del:刪除文件、文件夾
11.inject:文件注入
12.notify:提示信息
13.browser-sync:熱啓動
14.http-proxy-middleware:配合browser-sync進行跨域
15.changed:只有發生了改變的文件才能進入流中
16.sequence:讓task按順序完成
17.rev:添加MD5
18.watch:監聽文件變化

(五)實現項目自動化構建:

使用gulp構建項目,項目中支持:
1)js的模塊化(可以實現模塊化(common與require的切換));
2)sass的編譯;
3)jslint的代碼校驗;
4)劃分本地啓動配置和線上打包配置;
5)實現文件的md5加密;
6)實現本地的開發服務;
7)實現mock數據
8)實現本地實時刷新

本篇文章內容還未補全,之後會做更多修改,以期待完成補全,不過對於初學git以及node的同學來說已然是夠用了

  1. xyz
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章