通过webpack使用自定义bootstrap解决方案

如何更好地使用自定义的Bootstrap?

bootstrap官网提供自定义版本的下载,用户只要选择需要的组件就能下载对应的版本。但是,这种做法实在是太繁琐了。而且如果我们想要方便选择所需组件,又想通过sass/less修改bootstrap,要通过什么方式?答案就是’bootstrap-loader’(这个是对应修改sass的,本文只讲sass,还有个对应less的,叫’bootstrap-webpack’)。

bootstrap-loader的使用

bootstrap-loader ,从名字上看得出他是一个加载器,配合webpack使用的。它能使页面引用到自定义版本的bootstrap。

###1.安装

安装’bootstrap-loader’

npm install bootstrap-loader

安装所需依赖:

npm install --save-dev bootstrap-sass
npm install --save-dev css-loader node-sass resolve-url-loader sass-loader style-loader url-loader

你有可能还需要安装:

npm install --save-dev imports-loader exports-loader
npm install --save-dev postcss-loader        

###2.使用
1.简单使用方法:

import 'bootstrap-loader'

此时会引用到完整的bootstrap。

注:bootstrap引用了诸如svg、ttf等文件,所以也需要在webpack.config.js配置好对应的加载器:

{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'] },
{ test: /\.css$/, use: ['style-loader', 'css-loader', 'postcss-loader'] },
{
test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: 'url-loader?limit=10000',
},
{
test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/,
use: 'file-loader',
}

2.可自定义版:

首先在入口文件前面加载’bootstrap-loader’(此时不用在index.js里写import 'bootstrap-loader'):

entry: {
    index: ['bootstrap-loader', './index.js'],//webpack数组形式入口文件以数组最后一个作为出口文件
    test: './test.js',
},

然后在根目录添加.bootstraprc文件,即是bootstrap自定义配置文件,文件可以用yml或者json格式编写自定义属性,完整案例(yml格式):

bootstrapVersion: 3

useCustomIconFontPath: false

styleLoaders:
  - style
  - css
  - sass

extractStyles: false

styles:

  # Mixins
  mixins: true

  # Reset and dependencies
  normalize: true
  print: true
  glyphicons: true

  # Core CSS
  scaffolding: true
  type: true
  code: true
  grid: true
  tables: true
  forms: true
  buttons: true

  # Components
  component-animations: true
  dropdowns: true
  button-groups: true
  input-groups: true
  navs: true
  navbar: true
  breadcrumbs: true
  pagination: true
  pager: true
  labels: true
  badges: true
  jumbotron: true
  thumbnails: true
  alerts: true
  progress-bars: true
  media: true
  list-group: true
  panels: true
  wells: true
  responsive-embed: true
  close: true

  # Components w/ JavaScript
  modals: true
  tooltip: true
  popovers: true
  carousel: true

  # Utility classes
  utilities: true
  responsive-utilities: true

### Bootstrap scripts
scripts:
  transition: true
  alert: true
  button: true
  carousel: true
  collapse: true
  dropdown: true
  modal: true
  tooltip: true
  popover: true
  scrollspy: true
  tab: true
  affix: true

如果想给不同页面配置不用的.bootstraprc文件或者不想把.bootstraprc文件放在根目录,可以修改入口文件的bootstrap-loader的后缀,

格式:bootstrap-loader/lib/bootstrap.loader?configFilePath=[文件位置]/[文件名字].[文件类型]!bootstrap-loader/no-op.js

eg:

entry: {
    index: [`bootstrap-loader/lib/bootstrap.loader?configFilePath=${__dirname}/.bootstraprc!bootstrap-loader/no-op.js`, './index.js'],
    test: './test.js',
}

而自定义样式需要在.bootstraprc添加配置(按需要设置,不设置注释就可以):

//在Bootstrap variables之前加载
preBootstrapCustomizations: ./app/styles/bootstrap/pre-customizations.scss

//在Bootstrap variables之后bootstrap之前加载
bootstrapCustomizations: ./app/styles/bootstrap/customizations.scss

//在bootstrap之后加载
appStyles: ./app/styles/app.scss

【附bootstrap 样式变量表

bootstrap-loader的官方源码:https://github.com/shakacode/bootstrap-loader,上面会有更多解决方案。

es6+express+ejs+webpack+sass+mongoDB 部署

项目地址:es6+express+ejs+webpack+sass+mongoDB

使用

npm i //安装
npm start //开启服务
npm run dev  //开发模式
npm run bulid //发布

项目目录

--root
    |--config                //配置文件
    |--middlewares            //中间件
    |--pubulic                //静态资源
     |--js
     |--css/sass
     |--images
    |--router                //路由控制器
    |--tools                //工具
     |--lib
     |--webpack.config.js
    |--views                //视图文件
     |--components
    |--package.json
    |--...

es6预设置

使用babel对es6进行转换:

下载

 "devDependencies": {
"babel": "6.23.0",
"babel-cli": "6.23.0",
"babel-core": "6.23.1",
"babel-loader": "6.4.0",//webpack的babel-loader
"babel-plugin-transform-es2015-modules-commonjs": "6.23.0",//允许使用es6的modules
"babel-preset-env": "1.2.1",
"babel-preset-react": "6.23.0",//支持jsx转换
"babel-preset-stage-0": "6.22.0"
}

配置可以不写在.babelrc里,直接写在package.json

 "babel": {
"presets": [
  "react",
  "stage-0"
],
"plugins": [
  "transform-es2015-modules-commonjs"
]
}

npm script直接运行babel-node

"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "babel-node tools/start",//表示执行tools文件夹的start文件,执行之前进行es6转码
"dev": "supervisor -w tools,router,middlewares,config,views -- -r babel-register tools/dev"
}

es6 - 异步操作 async/await 语法

async函数允许你像同步写法那样去写异步操作,async函数里面关键字await后面接一个Promise,此时函数执行会在await后的Promise执行完成后才会往下执行。

举个例子,创建服务器是异步操作,我们需要在服务器创建完成后才布置路由。首先创建服务器,并把它包在Promise里面:

let runServer = (app)=>{
    return new Promise(resolve=>{
        var server = app.listen('3000',()=>{
            var host = server.address().address;
              var port = server.address().port;
            console.log('server running at http://%s:%s', host, port);
            resolve();
        })
    }) 
} 

然后在主体事件中,写异步操作:

 let appPro = async ()=>{
    let app = express();
    //等待启动服务 
    await runServer(app);
    //启动路由
    router(app);
}

此时,路由 router() 会在服务器创建完成后执行。

express 将session 存入Redis

import session from 'express-session';
import connectRedis from 'connect-redis';

let sessionCfg = {
    secret:'huangxinzheng',
    resave:true,//即使 session 没有被修改,也保存 session 值,默认为 true(!不添加报错,下同)
    saveUninitialized: false,// 设置为 false,强制创建一个 session,即使用户未登录
    cookie: {
        maxAge: 1000*60*60*24// 过期时间,过期后 cookie 中的 session id 自动删除
    }
}

 //设置session,将session存在 Redis 中
var RedisStore = connectRedis(session);
let rs = new RedisStore();
app.use(session(extend(true,{},serverCfg,rs)));

express 中间件的使用

express的中间件很重要,甚至可以说express就是通过中间来实现应用的。express有很多开源中间件可以给我们下载使用(比如express-session)。把中间件放进app.use()里就代表每次服务器请求都会经过这个中间件(假设中间件没有停止下一个的情况下)。我们也可以自己写中间件,其实中间件就是一个函数,这个函数有reqresnext 三个参数,分别代表请求对象,响应对象,和next方法。执行next方法可过渡当前中间件。

写一个记录访问次数的中间件,配合session记录一天内用户的访问次数:

let showReqTimes = (req,res,next) =>{
if(!req.session.reqTimes){
    req.session.reqTimes =1;
    res.send('你第1次访问了本网站');
}else{
    req.session.reqTimes++;
    res.send('<p>你第'+req.session.reqTimes+'次访问了本网站</p>');
}

next();//执行下一个中间件
}

export default showReqTimes

假设是记录在访问’/‘的时候:

import showReqTimes  from './showReqTimes.js'
app.get('/', showReqTimes, (req, res) => {//此时每次访问根目录之后都会进入showReqTimes这个中间件
    //do something..
})

webpack新版本的写法变化-Loader

webpack2.2较上一代在语法方面有了变化,特别是loader:

原先写法:
module: {
    loaders: [{
        test: /\.css$/,
        loader: 'style!css'
    }]
}
现在写法:
 module: {
    rules: [{
        test: /\.css$/,
        use: [ 'style-loader', 'css-loader']
    }]
}

loaders改为了rules,loader改为了use。语义上更加容易理解了,“对不同的文件类型使用不同的规则”。webpack 虽好,但是配置的时候很麻烦,更新了新版本之后,写法不习惯,报错也是莫名其妙。开发的要一边看官方文档,花了很多时间,看来要多花点时间去适应。

问题&解决

1. supervisor 监听 es6 文件

supervisor 默认监听不经过处理的js文件,所如果是直接监听es6语法的js文件,那么会出现语法错。

所以,采用babel-register对es6文件进行预转换,并且设置supervisor

supervisor -w tools,router -- -r babel-register tools/start

supervisor的官方文档可参见 : https://www.npmjs.com/package/supervisor

2. ejs模板引擎不同页面引用不同样式文件

ejs是款简单好用的模板引擎,但是网上很多人说ejs在不同的页面引用不同的文件非常不方便,有人给出在res.locals给模板传参的方法,把页面的引用样式文件从后台传给模板引擎进行解析。个人感觉但是这种方法不妥,管理起来不方便,样式文件就应该写在视图页面,不应该在路由里面写。

其实可以通过ejs的include解决这个问题。

ejs2.0+的include函数已经支持传参功能。利用这个特性我们可以简单实现ejs模板引擎不同页面引用不同样式文件了。具体实现:

在首页的视图中往header里面穿参数:

<%- include('layouts/header',{styles:['index','jquery']}) %>

然后在header的视图中修改引用样式:

 <% for(var i=0; i<styles.length; i++) {%>
   <link rel="stylesheet" href="/css/<%= styles[i] %>.css">
<% } %>

3. server.address().address 获取到IPv6格式的主机地址”::”?

以为如果计算机默认启用了IPv6,那么 server.address().address 获取到的就是IPv6的地址。如下:

var express      = require('express');
var app          = express();
var server = app.listen(3000, function () {
    var host = server.address().address;
    var port = server.address().port;
    console.log('running at http://' + host + ':' + port)
});

res:'server running at http://:::3000'    

如果想得到IPv4的主机地址,请显式得给listen传递主机名:

var express      = require('express');
var app          = express();
var server = app.listen(3000,'localhost', function () {
    var host = server.address().address;
    var port = server.address().port;
    console.log('running at http://' + host + ':' + port)
});

res:'server running at http://127.0.0.1:3000'

4. browser-sync 与 webpack-dev-middleware 的配合?

const bundler = webpack(webpackCfg);
const wpdm = webpackDevMiddleware(bundler,{
    publicPath: webpackCfg.output.publicPath
});

let handleBundleComplete = async () => {
    if(!app){
        await appPro().then(exApp=>{app = exApp});
        //app.use(wpdm)
        //启动 browser-sync
        bs = browserSync.create();
        bs.init({
          files: path.resolve(__dirname, '../public/*/**'),//监听目录
          proxy: {
            target: serverCfg.host+':'+serverCfg.port,
            middleware:[wpdm]
          },
          open: false,
          reloadOnRestart: true
        },resolve);
    }else{
        bs.reload();
    }

};
bundler.plugin('done', () => handleBundleComplete());

具体流程:

  • 1.先webpack生成bundler(此阶段并不执行生成)
  • 2.用webpack-dev-middleware把bundler包成中间件wpdm
  • 3.第一步生成bundler成功后启动服务器
  • 4.启动服务器成功后创建并初始化browser-sync
  • 5.第二步生成的中间件wpdm给到browser-sync中间件设置
  • 6.每次触发browser-sync的时候都执行中间件wpdm
  • 7.第一次之后的中间件wpdm执行都不用再启动服务器和创建browser-sync,只是执行browser-sync的reload事件

webpack实现HMR热加载

“热模块替换”(HMR)是在某个功能活动运行时注入更新的模块。

就像对每一个模块进行LiveReload

也就是说,在开发过程中,我们不用刷新页面,就能实现局部的更新,无论是css代码,还是js代码。

webpack实现HMR热加载

实现webpack HMR需要通过webpack的两个中间件,即webpack-dev-middlewarewebpack-hot-middleware

webpack-dev-middleware是什么:

The webpack-dev-middleware is a small middleware for a connect-based middleware stack. It uses webpack to compile assets in-memory and serve them. When a compilation is running every request to the served webpack assets is blocked until we have a stable bundle.

可以看出webpack-dev-middleware是一个中间件,负责把webpack打包的bundle生成在内存中,而不在磁盘里,而且在其生成稳定的包之前,编译将被阻塞(使网页更新有貌似网络延迟的效果),如此一来我们就不需要去关心编译是否完成了。

webpack-hot-middleware是什么:

This module is only concerned with the mechanisms to connect a browser client to a webpack server & receive updates. It will subscribe to changes from the server and execute those changes using webpack’s HMR API. Actually making your application capable of using hot reloading to make seamless changes is out of scope, and usually handled by another library.

webpack-dev-middleware用来在浏览器客户端和webpack服务端进行连接,监听服务端改变的文件,然后
实现浏览器客户端的热加载。


我写了个 例子 简单实现了HMR。

首先,先安装npm模块(这里我们用express作为服务器):

npm i express webpack webpack-dev-middleware webpack-hot-middleware --save-dev

然后,编写webpack.config.js:

//增加三个插件,并在入口文件后增加一段代码
var path = require('path'),
    webpack =require('webpack');
var config = {
    entry: 
    ["./src/a.js",
    'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000',
    ],
    output: {
        path: path.resolve(__dirname, './output/'),
        filename:'bundle.js',
    },
    plugins: [
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.NoEmitOnErrorsPlugin()
    ]
}

module.exports = config;

然后给express配置中间件:

var express = require('express'),
    app = express(),
    webpack = require('webpack'),
    config = require('./webpack.config.js'),
    webpackDevMiddleware = require('webpack-dev-middleware'),
    webpackHotMiddleware = require('webpack-hot-middleware');


//如果有回调函数并且没有中间件插件则直接运行webpack。如果没有回调函数或没有中间件插件则不直接执行webpack。
var compiler = webpack(config, function() {
    console.log('done')
}); 

/*这里设置bundle生成位置,注意是生成在内存中,由于我们设置了静态目录'output',
所以这里实际上的网络位置是localhost:8080/,文件位置是 根目录/output */
var options = {
    publicPath: "/",
}

app.use(webpackDevMiddleware(compiler, options));
app.use(webpackHotMiddleware(compiler));
app.use(express.static('output'))
app.listen(8080, function() {
    console.log('Example app listening on!')
})

最后在需要热加载的文件下加入(案例中是a.js):

if (module.hot) {
    module.hot.accept();
}

准备就绪,运行:

npm start

浏览器打开localhost:8080 ,会看到控制台输出

[HMR] connected

代表热加载连接成了!

我们点击按钮,弹出1。此时我们尝试修改b.js,把alert(1)改为alert(2),回到浏览器,发现浏览器并没有刷新,再次点击按钮,弹出了2!浏览器在不刷新的情况下,更新了js文件!

经验分享-网页动效之Canvas篇

在处理多元素动效的时候用操作DOM的方法会严重占用内存,拖慢运行速度,所以应该用Canvas画布制作多元素的动效或者游戏。

Canvas是HTML5的新标签。用于绘制图像(通过脚本,通常是 JavaScript),不过,canvas元素本身并没有绘制能力(它仅仅是图形的容器)。

Canvas提供的功能更原始,适合像素处理,动态渲染和大数据量绘制。

我写了一个弹弓射鸟的游戏,用的是JavaScript+Canvas,里面包含大部分Canvas的用法,以及面向对象的JavaScript写法:

(手机扫一扫查看demo,我只写了touch事件,所以只能在手机上玩,或者电脑开发者模式模拟手机。)

项目 源码地址


该游戏优化过,即使出现超大量的元素也不会卡:

优化通过删除冗余对象、去除setInterval改为requestAnimationFrame作为定时器、还有就是规范的游戏的开发模式。


requestAnimationFrame作为定时器:

interval: function() {
     var $this = this;
     this.timer = requestAnimationFrame(function() {
         $this.render();
         //游戏时间用完结束
         if ($this.usedTime < $this.time) {
              $this.timer = requestAnimationFrame(arguments.callee);
         } else {
              $this.over();
         }
     });
}

只要学会了这个,并能自己亲手写出一个这样的游戏,那么你的canvas就可以了。

gulp command not found - error after installing gulp

First,

Be sure that you have gulp and gulp.cmd (use windows search )

Then,

Copy the path of gulp.cmd ( C:\Users\XXXX\AppData\Roaming\npm)

Add this path to the Path envirement variable.

*OR

Edit “PATH” environment variable and add %APPDATA%\npm
(Add %APPDATA%\npm to front of Path, not end of the Path.)

finally,

reopen cmd.

js设计模式-模拟私有变量

//假设有一个人的类,一般的写法:                       
function Person(name,age){
    this.name = name;
    this.age = age;
};
Person.prototype={
    born:function(){
        return this;
    },
    say:function(word){
        var $this = this;
        console.log($this.name);
    }
}

//我们规定这个类创建的对象,其name属性必须小于4个字符
//那么可以这样:
function Person(name,age){
    if(name.length>4) throw new Error('name too long');
    this.name = name;
    this.age = age;
};
Person.prototype={
    born:function(){
        return this;
    },
    say:function(word){
        var $this = this;
        console.log($this.name);
    }
}
//这样的话我们可以在创建对象之初限制对象的属性
var person1 = new Person('Zacarh',23);//这样会报错
//但是有个弊端,程序员创建了符合规定的对象,但是他仍可以修改对象的属性成为不符合规则的值
var person2 = new Person('Tom',22);//成功创建
person2.name = 'Zacarh';//成功修改为不符合规则的值
console.log(person2.name);//Zacarh

//于是就有了私有变量的由来,我们采用闭包模拟私有变量
function Person(){
    var name,age;//这里的变量外部访问不到,可以看成私有变量
    this.setName=function(nameArgument){//这个是特权方法,可以访问私有变量
        if(nameArgument.length>4) throw new Error('name too long');
        name = nameArgument;//特权方法内却可以访问到外部变量。js函数作用域是在定义的时候确定的,不是在执行的时候确定的
    };
    this.say = function(){
        console.log(name);//这里就不用this.name了
    }
}
var person1 = new Person();
// person1.setName('Zacarh');//报错,字符长度大于4
person1.setName('Tom');//可以
person1.say();//输出Tom,而且此时你无法直接更改name的值了,必须要通过setName函数才可以。

//上面那种做法的弊端就是,每创建一个对象,特权函数也会创建一次,这样会耗费更多的内存,不像用prototype那样所有对象共用prototype上面的方法。

经验分享-网页动效之CSS篇

网页动效之CSS篇

在网页中实现动画效果有很多种方式,例如由js控制的canvas、svg、elements动画,还有由css3控制的svg和elements动画等(还有flash?)。css实现elements动画主要通过transition(过渡效果)和animation(动画)来控制。其中animation通过其强大的函数自定义化和丰富的控制接口以及css3与生俱来的流畅高速渲染效果,成为了动画大军的一只劲旅。

在制作一些简单的、动画元素少的、交互小的动画。css3的animation是最好的选择。
这篇文章的主题就是,用好animation的技巧。基础知识网上一大把就不说了。

Tips1:控制动画开始执行时刻

我们从例子出发,假如我们想要一个小球,在某个时刻(例如点击了一个按钮)向左动一下。这时我们就可以借助 animation-play-state 这个属性。

animation-play-state 属性规定动画正在运行还是暂停。

假设我们需要动画的元素为.ele,.ele的上级为.ele-wrap,那么我们可以这样写css:

.ele-wrap .ele{animation-play-state:paused;}

.playing .ele{animation-play-state:running;}

.ele{animation:moveToLeft 1s;}

当我们给ele-wrap 加上playing(例如通过点击事件添加)的时候,这个时候ele就会动起来。

通过这种方法,我们能更加方便清晰地控制某些区域下元素的动画开始执行时刻。

Tips2:叠加动画

animation 是支持叠加动画的写法的,看代码

.ele{animation:fadeIn 1s,sildeLeft 1s}

这个写法的意思是让元素渐显同时向左移动。

这里有一点要注意的是,如果后面的动画改变的元素属性和前面的动画一样的话,那么前面动画的属性改变就失效了。

.ele{animation:fadeIn 1s,sildeLeft 1s,sildeUp 1s}

如果是上面这种写法,那么sildeLeft将被忽略。

另外一种实现方法是采用元素嵌套。

通过给动画元素外包一个父级元素,然后给父级和子级分别加上动画。

.ele-wrap{animation:fadeIn 1s}

.ele-warp .ele{animation:slideLeft 1s}

Tips3:连接动画

通过animaiton的animation-delay可以实现动画连接。比如上个例子我们不要两个动画同时进行,我们想元素渐显后再向左移动,那么我们可以这样写:

.ele{animation:fadeIn 1s,sildeLeft 1s 1s}

sildeLeft后面的第一个1s是指动画执行时间,第二个1s是指动画延迟多久才执行。这样写元素就会延迟1s才向左边移动。

与Tips2一样,用元素嵌套方式可以连接数目更多的动画。

Tips4:规定动画执行位置

animation-delay允许负值,负值动画将马上开始,然后跳过动画的前N秒。比如我们希望ele直接就向左移动就可以这样写:

.ele{animation:fadeIn 1s -1s,sildeLeft 1s}

这样写fadeIn马上执行,而且是从原本执行1s后的状态开始执行。

Tips5:来回播放动画

animation-direction属性在某些情况很好用。比如你想让元素按照轨迹来回移动。按照常规方法你要这样写:

 @keyframes move{
     0%,100%{transform:translate(0,0);}
    25%{transform:translate(0,120px);}
     50%{transform:translate(120px,120px);}
    75%{transform:translate(0,120px);}
  }

.ele{animation:move 4s infinite}

如果用animation-direction ,只要这样

@keyframes move{
     0%{transform:translate(0,0);}
     50%{transform:translate(0,120px);}
    100%{transform:translate(120px,120px);}
 }

.ele{animation:move 4s infinite alternate}

当然了这只是简单的一个例子。

未完待续。。

arguments中的caller与callee

arguments中有两个好用的属性,caller与callee,中文意思为呼叫者和被呼叫者。那么,这两个属性,究竟是啥?

呼叫者caller

含义:返回当前调用该属性的方法的方法

有点绕口,详细点就是:如果一个方法里面,调用了caller,那么caller就返回调用这个方法的方法,如果这个方法是由顶级(浏览器端为window)调用的,则返回undefined。

我们来举个例子

function f1(){
    console.log(arguments.caller);
}

function f2(){
    f1();
}

f1();//undefined
f2();//function f2(){ f1();}

caller在每次函数执行的时候都会重新执行。

这个特性意味着caller可以用来显示函数的反编译文本。

被呼叫者callee

含义:返回当前调用该属性的方法

这个好理解,就是返回调用函数本身。

还是来看看例子

function f1(){
    console.log(arguments.callee);
}
f1(); //function f1(){ ...}

利用callee我们可以轻松实现很多功能,例如递归:

function fact(n){
    if(n<=0){
        return 1;
    }else{
        return n*arguments.callee(n-1);  
    }
}

或者检验实参与形参个数是否相同:

function f4(x,y,z){
    if(arguments.length === arguments.callee.length){
        console.log('实参形参个数相同');
    }else{
        console.log('实参形参个数不同');
    }
}
f4(1,2);//实参形参个数不同
f4(1,2,3);//实参形参个数相同

还有其他功能,有待挖掘。

git常用命令


常用命令:

创建版本库:

git init

添加文件:

git add <files>
git add .   #添加所有文件

删除文件:

git rm <files>

提交:

git commit -m "描述"

显示仓库状态:

git status

显示diff:

git diff

丢弃工作区的修改:

git checkout -- file

创建分支:

git branch dev #dev是分支名字,这里只是一个例子,下同

创建并切换到dev分支:

git checkout -b dev 

查看分支:

git branch  #显示的分支中``*``号位置代表当前分支

切换到dev分支:

git checkout dev

合并dev分支到当前分支:

git merge dev

删除dev分支:

git branch -d dev

显示历史版本:

git log

显示历史信息:

git show

显示历史操作:

git reflog

退回:

git reset --hard <HEAD>

添加远程仓库:

git remote add origin <address>

推送并关联master:

git push -u origin master

关联后简化为:

git push origin master

克隆:

git clone <address>

更加详细的命令大全

配置

配置使用git仓库人员的姓名和email
$ git config --global user.name "Your Name"  
$ git config --global user.email you@yourdomain.example.com 

git config --global credential.helper cache #配置到缓存 默认15分钟   
git config --global credential.helper 'cache --timeout=3600'  #修改缓存时间   

git config --global color.ui true  
git config --global alias.co checkout  
git config --global alias.ci commit  
git config --global alias.st status  
git config --global alias.br branch  
git config --global core.editor "mate -w"    # 设置Editor使用textmate  
git config -1 #列举所有配置用户的git配置文件~/.gitconfig  

查看、添加、提交、删除、找回,重置修改文件

git help <command>  # 显示commandhelp  
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     # 恢复最后一次提交的状态  

查看文件diff

git diff <file>     # 比较当前文件和暂存区文件差异  
git diff  
git diff <$id1> <$id2>   # 比较两次提交之间的差异  
git diff <branch1>..<branch2> # 在两个分支之间比较  
git diff --staged   # 比较暂存区和版本库差异  
git diff --cached   # 比较暂存区和版本库差异  
git diff --stat     # 仅仅比较统计信息  

查看提交记录

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

取得Git仓库

git init  #初始化一个版本仓库   

git clone <address>  #Clone远程版本库  

git remote add origin <address>  #添加远程版本库origin

git remote -v  #查看远程仓库

提交你的修改

git commit –m "你的注释"  #提交你的修改  

git push origin master  #推送你的更新到远程服务器,语法为 git push [远程名] [本地分支]:[远程分支]  

git status  #查看文件状态 

git add readme.txt  #跟踪新文件

git rm readme.txt  #从当前跟踪列表移除文件,并完全删除

git rm –cached readme.txt  #仅在暂存区删除,保留文件在当前目录,不再跟踪 

git mv reademe.txt readme  #重命名文件 

git log  #查看提交的历史记录 

git commit --amend  #修改最后一次提交注释的,利用–amend参数 

-忘记提交某些修改,下面的三条命令只会得到一个提交。 
git commit –m &quot;add readme.txt&quot;  
git add readme_forgotten  
git commit –amend  


git reset HEAD b  #假设你已经使用git add .,将修改过的文件a、b加到暂存区。现在你只想提交a文件,不想提交b文件,应该这样

git checkout –- readme.txt  #取消对文件的修改

查看、切换、创建和删除分支

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>  # 强制删除某个分支 (未被合并的分支被删除的时候需要强制)  

分支合并和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>  

Git补丁管理(方便在多台机器上开发同步时用)

git diff > ../sync.patch         # 生成补丁  
git apply ../sync.patch          # 打补丁  
git apply --check ../sync.patch  #测试补丁能否成功  

Git暂存管理

git stash                        # 暂存  
git stash list                   # 列所有stash  
git stash apply                  # 恢复暂存的内容  
git stash drop                   # 删除暂存区  

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删除远程分支  

基本的分支管理

git branch dev  #创建一个分支 

git chekcout dev  #切换工作目录到dev 

git chekcout –b dev  #将上面的命令合在一起,创建dev分支并切换到dev 

git merge dev  #合并dev分支,当前工作目录为master

git branch –d dev  #合并完成后,没有出现冲突,删除dev分支 

git fetch  #拉去远程仓库的数据,语法为git fetch [remote-name]

git pull  #fetch 会拉去最新的远程仓库数据,但不会自动到当前目录下,要自动合并

git remote show origin  #查看远程仓库的信息  

git checkout –b dev origin/develop  #建立本地的dev分支追踪远程仓库的develop分支 

Git远程仓库管理

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>       # 删除远程仓库  

创建远程仓库

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  

剥皮鱼全接触

剥皮鱼

剥皮鱼学名叫绿鳍马面鲀,又叫马面鱼,潮汕俗名:迪仔。我觉得叫迪克牛仔or德州牛仔帅得多。

剥皮鱼 加辣椒 和 豆酱 真 是 他 妈 的 好 吃 !!

豆酱焖剥皮鱼的做法:
食材
主料
剥皮鱼5条
辅料
豆酱1汤匙、适量辣椒、适量蒜头、适量姜、适量小葱、适量油、适量清水
步骤
1.热锅加油炒蒜头
2.放剥皮鱼煎
3.煎至两面微黄放姜丝、葱段、辣椒下去炒香
4.加入1汤匙的豆酱
5.再加少量清水焖至汁少就可以岀锅了
6.成品
小贴士
豆酱有咸味不用加盐了,鱼很鲜不用加过多的调料。