资讯专栏INFORMATION COLUMN

浅析git

explorer_ddf / 3448人阅读

摘要:浅析笔者在此整理了常见的命令,的重要性无需多言,与其再百度海中搜索命令,不妨尝试收藏笔者的此篇作品。旨在快速高效地处理无论规模大小的任何软件工程。其最大特色就是分支及合并操作非常快速简便。

浅析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 root@123.207.172.12:/data./git
(这里是将本地的gittest.git文件夹拷贝到服务器中 /data/git文件夹下)

3.此时可以直接将本地的gittest文件夹关联远程仓库,也可以在本地再次克隆git仓库;使用命令如下:
Git clone git@123.207.172.15:/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 837990335@qq.com
可以一路回车;
(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 git@github.com
如果输出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的help
git show # 显示某次提交的内容 git show $id
git co -- # 抛弃工作区修改
git co . # 抛弃工作区修改
git add # 将工作文件修改提交到本地暂存区
git add . # 将所有修改过的工作文件提交暂存区
git rm # 从版本库中删除文件
git rm --cached # 从版本库中删除文件,但不删除文件
git reset # 从暂存区恢复到工作文件
git reset -- . # 从暂存区恢复到工作文件
git reset --hard # 恢复最近一次提交过的状态,即放弃上次提交后的所有本次修改
git ci 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 # 比较当前文件和暂存区文件差异 git diff
git diff # 比较两次提交之间的差异
git diff .. # 在两个分支之间比较
git diff --staged # 比较暂存区和版本库差异
git diff --cached # 比较暂存区和版本库差异
git diff --stat # 仅仅比较统计信息
3.查看提交记录
git log git log # 查看该文件每次提交记录
git log -p # 查看每次详细修改内容的diff
git log -p -2 # 查看最近两次详细修改内容的diff
git log --stat #查看提交统计信息
tig
Mac上可以使用tig代替diff和log,brew install tig

4.查看、切换、创建和删除分支
git br -r # 查看远程分支
git br # 创建新的分支
git br -v # 查看各个分支最后提交信息
git br --merged # 查看已经被合并到当前分支的分支
git br --no-merged # 查看尚未被合并到当前分支的分支
git co # 切换到某个分支
git co -b # 创建新的分支,并且切换过去
git co -b # 基于branch创建新的new_branch
git co $id # 把某次历史提交记录checkout出来,但无分支信息,切换到其他分支会自动删除
git co $id -b # 把某次历史提交记录checkout出来,创建成一个分支
git br -d # 删除某个分支
git br -D # 强制删除某个分支 (未被合并的分支被删除的时候需要强制)
5. 分支合并和rebase
git merge # 将branch分支合并到当前分支
git merge origin/master --no-ff # 不要Fast-Foward合并,这样可以生成merge提交
git rebase master # 将master rebase到branch,相当于: git co && git rebase master && git co master && git merge
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 origin/ # 基于远程分支创建本地分支,功能同上
git push # push所有分支
git push origin master # 将本地主分支推到远程主分支
git push -u origin master # 将本地主分支推到远程(如无远程主分支则创建,用于初始化远程仓库)
git push origin # 创建远程分支, origin是远程仓库名
git push origin : # 创建远程分支
git push origin : #先删除本地分支(git br -d ),然后再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 # 删除远程仓库
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

项目自动化:

现在的前端开发已经不再仅仅只是静态网页的开发了,日新月异的前端技术已经让前端代码的逻辑和交互效果越来越复杂,更加的不易于管理,模块化开发和预处理框架把项目分成若干个小模块,增加了最后发布的困难,没有一个统一的标准,让前端的项目结构千奇百怪。前端自动化构建在整个项目开发中越来越重要。

(一)工具化
在前端的技术栈发展过程中,出现了很多的工具,形成了工具化,能够用工具完成的绝不要手工完成,来帮助开发者提升效率。

前端工作流工具: Gulp,Grunt

前端js模块编译工具:Babel,Browserify,Webpack

包管理器: npm,bower

前端开发系列工具: 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的同学来说已然是够用了

  • xyz ↩

  • 文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

    转载请注明本文地址:https://www.ucloud.cn/yun/53186.html

    相关文章

    • 浅析webpack源码之Tapable粗解(五)

      摘要:打开是个构造函数,定义了一些静态属性和方法我们先看在插件下地址上面写的解释就跟没写一样在文件下我们看到输出的一些对象方法每一个对应一个模块而在下引入的下面,我们先研究引入的对象的英文单词解释,除了最常用的点击手势之外,还有一个意思是水龙头进 打开compile class Compiler extends Tapable { constructor(context) { ...

      Arno 评论0 收藏0
    • 浅析git

      摘要:浅析笔者在此整理了常见的命令,的重要性无需多言,与其再百度海中搜索命令,不妨尝试收藏笔者的此篇作品。旨在快速高效地处理无论规模大小的任何软件工程。其最大特色就是分支及合并操作非常快速简便。 浅析git 笔者在此整理了常见的git命令,git的重要性无需多言,与其再百度海中搜索git命令,不妨尝试收藏笔者的此篇作品。希望对你的学习有所帮助。 版本控制系统之git Git: (一)简介:G...

      Neilyo 评论0 收藏0
    • 浅析git

      摘要:浅析笔者在此整理了常见的命令,的重要性无需多言,与其再百度海中搜索命令,不妨尝试收藏笔者的此篇作品。旨在快速高效地处理无论规模大小的任何软件工程。其最大特色就是分支及合并操作非常快速简便。 浅析git 笔者在此整理了常见的git命令,git的重要性无需多言,与其再百度海中搜索git命令,不妨尝试收藏笔者的此篇作品。希望对你的学习有所帮助。 版本控制系统之git Git: (一)简介:G...

      Big_fat_cat 评论0 收藏0
    • python setup.py 浅析

      摘要:浅析参数说明对于所有列表里提到的纯模块做处理需要在脚本里有一个包名到目录的映射。阐明包名到目录的映射,见键代表了包的名字,空的包名则代表不在任何包中的顶层包。最终会在下生成可执行文件,调用制定的函数实例分析 python setup.py 浅析 setuptools.setup() 参数说明 packages 对于所有 packages 列表里提到的纯 Python 模块做处理 需要...

      sevi_stuo 评论0 收藏0

    发表评论

    0条评论

    explorer_ddf

    |高级讲师

    TA的文章

    阅读更多
    最新活动
    阅读需要支付1元查看
    <