<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>omiga</title>
	<atom:link href="http://omiga.org/blog/feed" rel="self" type="application/rss+xml" />
	<link>http://omiga.org/blog</link>
	<description>简单就好</description>
	<lastBuildDate>Thu, 26 Apr 2012 04:18:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>LevenshTeinDistance算法的JavaScript实现</title>
		<link>http://omiga.org/blog/archives/2472</link>
		<comments>http://omiga.org/blog/archives/2472#comments</comments>
		<pubDate>Wed, 18 Apr 2012 05:27:15 +0000</pubDate>
		<dc:creator>omiga</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[LevenshteinDistance]]></category>
		<category><![CDATA[相似度]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://omiga.org/blog/?p=2472</guid>
		<description><![CDATA[LevenshTeinDistance是俄罗斯科学家Vladimir Levenshtein在1965年提出的根据编辑距离（Edit Distance）计算字符串相似度的一种算法。 /* * @name:LevenshteinDistance.js * @description: * @author:wondger@gmail.com * @date:2012-04-17 * @param: * @todo: * @changelog: */ var LevenshteinDistance = { _str1:null, _str3:null, _matrix:null, _isString:function(s){ return Object.prototype.toString.call(s) === '[object String]'; }, _isNumber:function(s){ return Object.prototype.toString.call(s) === '[object Number]'; }, init:function(str1,str2){ if(!this._isString(str1) &#124;&#124; !this._isString(str2)) return; this._str1 = str1; this._str2 = str2; str1.length &#38;&#38; str2.length &#38;&#38; [...]]]></description>
			<content:encoded><![CDATA[<p>LevenshTeinDistance是俄罗斯科学家Vladimir Levenshtein在1965年提出的根据编辑距离（Edit Distance）计算字符串相似度的一种算法。</p>
<pre>/*
 * @name:LevenshteinDistance.js
 * @description:
 * @author:wondger@gmail.com
 * @date:2012-04-17
 * @param:
 * @todo:
 * @changelog:
 */
var LevenshteinDistance = {
    _str1:null,
    _str3:null,
    _matrix:null,
    _isString:function(s){
        return Object.prototype.toString.call(s) === '[object String]';
    },
    _isNumber:function(s){
        return Object.prototype.toString.call(s) === '[object Number]';
    },
    init:function(str1,str2){
        if(!this._isString(str1) || !this._isString(str2)) return;

        this._str1 = str1;
        this._str2 = str2;

        str1.length &amp;&amp;  str2.length &amp;&amp; this._createMatrix(str1.length+1,str2.length+1);
        this._matrix &amp;&amp; this._initMatrix();

        return this;
    },
    get:function(){
        return 1 - this._getDistance()/Math.max(this._str1.length,this._str2.length);
    },
    //计算编辑距离
    _getDistance:function(){
        var len1 = this._str1.length,
            len2 = this._str2.length;

        if(!len1 || !len2) return Math.max(len1,len2);

        var str1 = this._str1.split(''),
            str2 = this._str2.split('');

        var i = 0,j = 0,temp = 0;
        while(i++ &lt; len1){
            j = 0;
            while(j++ &lt; len2){
                 temp = str1[i-1] === str2[j-1] ? 0 : 1;
                 this._matrix[i][j] = Math.min(this._matrix[i-1][j]+1,this._matrix[i][j-1]+1,this._matrix[i-1][j-1]+temp);
             }
         }
         return this._matrix[i-1][j-1];
     },
     /*
      * 初始化矩阵
      * 为第一行、第一列赋值
      */
     _initMatrix:function(){
         var cols = this._matrix[0].length,
             rows = this._matrix.length;
         var l = Math.max(cols,rows);
         while(l--){
             cols-1 &gt;= l &amp;&amp; (this._matrix[0][l] = l);
             rows-1 &gt;= l &amp;&amp; (this._matrix[l][0] = l);
        }
    },
    /*
     * 创建矩阵
     * n:行
     * m:列
     */
    _createMatrix:function(n,m){
        if(!this._isNumber(n) || !this._isNumber(m) || n&lt;1 || m&lt;1) return;

        this._matrix = new Array(n),i = 0;
        while(i&lt;n) this._matrix[i++] = new Array(m);
    }
}</pre>
<p>示例：</p>
<pre>alert(LevenshteinDistance.init('omiga.org','omiga').get()); // 0.5555555555555556
alert(LevenshteinDistance.init('omiga','omiga').get()); // 1 完全相同
alert(LevenshteinDistance.init('god','superman').get()); // 0 完全不同</pre>
<hr />
<p><small>© omiga for <a href="http://omiga.org/blog">omiga</a>, 2012. |
<a href="http://omiga.org/blog/archives/2472">Permalink</a> |
<a href="http://omiga.org/blog/archives/2472#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://omiga.org/blog/archives/2472&title=LevenshTeinDistance算法的JavaScript实现">del.icio.us</a>
<br/>
Post tags: <a href="http://omiga.org/blog/archives/tag/levenshteindistance" rel="tag">LevenshteinDistance</a>, <a href="http://omiga.org/blog/archives/tag/%e7%9b%b8%e4%bc%bc%e5%ba%a6" rel="tag">相似度</a>, <a href="http://omiga.org/blog/archives/tag/%e7%ae%97%e6%b3%95" rel="tag">算法</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://omiga.org/blog/archives/2472/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>自定义事件</title>
		<link>http://omiga.org/blog/archives/2425</link>
		<comments>http://omiga.org/blog/archives/2425#comments</comments>
		<pubDate>Fri, 30 Mar 2012 09:18:05 +0000</pubDate>
		<dc:creator>omiga</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[CustomEvent]]></category>
		<category><![CDATA[dispatchEvent]]></category>
		<category><![CDATA[event]]></category>
		<category><![CDATA[fire]]></category>
		<category><![CDATA[fireEvent]]></category>

		<guid isPermaLink="false">http://omiga.org/blog/?p=2425</guid>
		<description><![CDATA[对于一个事件通常我们主要关注两件事情： 怎么注册/注销 何时触发 DOM Level 2 Events和DOM Level 3 Events中已经提供了接口用于对自定义事件的支持，addEventListener/removeEventListener完成对任意事件函数的注册/注销（标准事件、自定义事件），createEvent-initEvent-dispatchEvent完成事件的触发。 注册/注销方式和普通标准事件没有区别，而事件的触发需要自行再包装实现一下，这个方法我们也暂命名为dispatchEvent。 var Event = { dispatchEvent:function(el,type,evtType){ //create Event var evtType = evtType &#124;&#124; 'CustomEvent', evt = document.createEvent(evtType); //init Event evt.initEvent(type,true,true); //dispatch Event el.dispatchEvent(evt); } } createEvent支持多种事件类型丰富，比如"UIEvents"、"MouseEvents"、"MutationEvents"、"HTMLEvents"，具体类型可参考前面的两个文档。不同类型事件具有不同的初始化方法，比如"initUIEvent"、"initMouseEvent"、"initMutationEvent"、"initHTMLEvent"&#8230;使用专有初始化方法具有更多大灵活性，具有更多的参数接口。而"initEvent"是一个基础方法，使用起来更简单，但有时候无法满足更多的需求。 IE9及以后版本开始支持dispatchEvent，而IE8及以前版本并不支持。但好在IE提供了另外一个方法fireEvent用于触发事件函数，而且标准事件模型中的createEvent-initEvent-dispatchEvent过程在IE中只需要createEventObject-fireEvent两个步骤即可完成，当然其实是将initEvent中的初始化工作合并到了createEventObject中。所以我们也有了IE8及以下版本的fireEvent方法实现。 var Event = { fireEvent:function(el,type,cfg){ //create Event var evt = document.createEventObject(cfg); //fire Event el.fireEvent('on'+type,evt); } } 但遗憾的是fireEvent仅能触发通过attachEvent注册的标准事件，对于我们的自定义事件该方法其实形同虚设。 另外：即使对于标准事件，fireEvent还有一个很大的不同：不会触发默认行为。比如有一个form， [...]]]></description>
			<content:encoded><![CDATA[<p>对于一个事件通常我们主要关注两件事情：</p>
<ol>
<li>怎么注册/注销</li>
<li>何时触发</li>
</ol>
<p><a title="DOM Level 2 Events" href="http://www.w3.org/TR/DOM-Level-2-Events/events.html" target="_blank">DOM Level 2 Events</a>和<a title="DOM Level 3 Events" href="http://www.w3.org/TR/DOM-Level-3-Events/" target="_blank">DOM Level 3 Events</a>中已经提供了接口用于对自定义事件的支持，addEventListener/removeEventListener完成对任意事件函数的注册/注销（标准事件、自定义事件），createEvent-initEvent-dispatchEvent完成事件的触发。</p>
<p>注册/注销方式和普通标准事件没有区别，而事件的触发需要自行再包装实现一下，这个方法我们也暂命名为dispatchEvent。</p>
<pre>var Event = {
    dispatchEvent:function(el,type,evtType){
        //create Event
        var evtType = evtType || 'CustomEvent',
            evt = document.createEvent(evtType);
        //init Event
        evt.initEvent(type,true,true);
        //dispatch Event
        el.dispatchEvent(evt);
    }
}</pre>
<p>createEvent支持多种事件类型丰富，比如<code>"UIEvents"</code>、<code>"MouseEvents"</code>、<code>"MutationEvents"</code>、<code>"HTMLEvents"</code>，具体类型可参考前面的两个文档。不同类型事件具有不同的初始化方法，比如<code>"initUIEvent"</code>、<code>"initMouseEvent"</code>、<code>"initMutationEvent"</code>、<code>"initHTMLEvent"</code>&#8230;使用专有初始化方法具有更多大灵活性，具有更多的参数接口。而<code>"initEvent"</code>是一个基础方法，使用起来更简单，但有时候无法满足更多的需求。</p>
<p>IE9及以后版本开始支持dispatchEvent，而IE8及以前版本并不支持。但好在IE提供了另外一个方法fireEvent用于触发事件函数，而且标准事件模型中的createEvent-initEvent-dispatchEvent过程在IE中只需要createEventObject-fireEvent两个步骤即可完成，当然其实是将initEvent中的初始化工作合并到了createEventObject中。所以我们也有了IE8及以下版本的fireEvent方法实现。</p>
<pre>var Event = {
    fireEvent:function(el,type,cfg){
        //create Event
        var evt = document.createEventObject(cfg);
        //fire Event
        el.fireEvent('on'+type,evt);
    }
}</pre>
<p>但遗憾的是fireEvent仅能触发通过attachEvent注册的标准事件，对于我们的自定义事件该方法其实形同虚设。</p>
<p>另外：即使对于标准事件，fireEvent还有一个很大的不同：不会触发默认行为。比如有一个form，</p>
<pre>Event.dispatchEvent(form,'submit'); //会触发submit行为提交表单
Event.fireEvent(form,'submit'); //不会触发submit行为</pre>
<p>对于不支持自定义事件注册/注销、触发的浏览器，可是有如下方案：</p>
<ul>
<li>注册/注销<br />
将DOM与自定义事件对应关系保存，这其中涉及到保存的自定义事件与DOM对象的对应关系数据的结构如何设计；以及如何避免重复注册</li>
<li>触发<br />
对于关系保存下来了，其实触发就很简单，直接调用事件方法即可，唯一需要注意的是一个模拟的Event对象传递个事件函数</li>
</ul>
<p>代码不贴了～···^-^</p>
<p>参考：</p>
<ul>
<li><a href="http://msdn.microsoft.com/en-us/library/ms536390(VS.85).aspx">http://msdn.microsoft.com/en-us/library/ms536390(VS.85).aspx</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/ie/ms536390(v=vs.85).aspx">http://msdn.microsoft.com/en-us/library/ie/ms536390(v=vs.85).aspx</a></li>
<li><a href="https://developer.mozilla.org/en/DOM/document.createEvent">https://developer.mozilla.org/en/DOM/document.createEvent</a></li>
<li><a href="https://developer.mozilla.org/en/DOM/event.initEvent">https://developer.mozilla.org/en/DOM/event.initEvent</a></li>
</ul>
<hr />
<p><small>© omiga for <a href="http://omiga.org/blog">omiga</a>, 2012. |
<a href="http://omiga.org/blog/archives/2425">Permalink</a> |
<a href="http://omiga.org/blog/archives/2425#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://omiga.org/blog/archives/2425&title=自定义事件">del.icio.us</a>
<br/>
Post tags: <a href="http://omiga.org/blog/archives/tag/customevent" rel="tag">CustomEvent</a>, <a href="http://omiga.org/blog/archives/tag/dispatchevent" rel="tag">dispatchEvent</a>, <a href="http://omiga.org/blog/archives/tag/event" rel="tag">event</a>, <a href="http://omiga.org/blog/archives/tag/fire" rel="tag">fire</a>, <a href="http://omiga.org/blog/archives/tag/fireevent" rel="tag">fireEvent</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://omiga.org/blog/archives/2425/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>多个github帐号的SSH key切换</title>
		<link>http://omiga.org/blog/archives/2269</link>
		<comments>http://omiga.org/blog/archives/2269#comments</comments>
		<pubDate>Tue, 18 Oct 2011 06:03:09 +0000</pubDate>
		<dc:creator>omiga</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[SSH]]></category>

		<guid isPermaLink="false">http://omiga.org/blog/?p=2269</guid>
		<description><![CDATA[github使用SSH与客户端连接。如果是单用户（first），生成密钥对后，将公钥保存至github，每次连接时SSH客户端发送本地私钥（默认~/.ssh/id_rsa）到服务端验证。单用户情况下，连接的服务器上保存的公钥和发送的私钥自然是配对的。但是如果是多用户（first，second），我们在连接到second的帐号时，second保存的是自己的公钥，但是SSH客户端依然发送默认私钥，即first的私钥，那么这个验证自然无法通过。不过，要实现多帐号下的SSH key切换在客户端做一些配置即可。 首先cd到~/.ssh 使用 ssh-keygen -t -rsa -C &#8216;second@mail.com&#8217; 生成新的SSH key：id_rsa_second，生成完后将新的SSH public key添加到github。 ssh-keygen -t rsa -C 'second@mail.com' 默认SSH只会读取id_rsa，所以为了让SSH识别新的私钥，需要将其添加到SSH agent ssh-add ～/.ssh/id_rsa_second 该命令如果报错：Could not open a connection to your authentication agent.无法连接到ssh agent，可执行ssh-agent bash命令后再执行ssh-add命令。 完成以上步骤后在~/.ssh目录创建config文件，该文件用于配置私钥对应的服务器。内容如下： # Default github user(first@mail.com) Host github.com HostName github.com User git IdentityFile C:/Users/username/.ssh/id_rsa # second user(second@mail.com) Host github-second HostName github.com User git [...]]]></description>
			<content:encoded><![CDATA[<p>github使用SSH与客户端连接。如果是单用户（first），生成密钥对后，将公钥保存至github，每次连接时SSH客户端发送本地私钥（默认~/.ssh/id_rsa）到服务端验证。单用户情况下，连接的服务器上保存的公钥和发送的私钥自然是配对的。但是如果是多用户（first，second），我们在连接到second的帐号时，second保存的是自己的公钥，但是SSH客户端依然发送默认私钥，即first的私钥，那么这个验证自然无法通过。不过，要实现多帐号下的SSH key切换在客户端做一些配置即可。</p>
<p>首先cd到~/.ssh 使用 ssh-keygen -t -rsa -C &#8216;second@mail.com&#8217; 生成新的SSH key：id_rsa_second，生成完后将新的SSH public key添加到github。</p>
<pre>ssh-keygen -t rsa -C 'second@mail.com'</pre>
<p>默认SSH只会读取id_rsa，所以为了让SSH识别新的私钥，需要将其添加到SSH agent</p>
<pre>ssh-add ～/.ssh/id_rsa_second</pre>
<p>该命令如果报错：Could not open a connection to your authentication agent.无法连接到ssh agent，可执行ssh-agent bash命令后再执行ssh-add命令。</p>
<p>完成以上步骤后在~/.ssh目录创建config文件，该文件用于配置私钥对应的服务器。内容如下：</p>
<pre># Default github user(first@mail.com)
Host github.com
 HostName github.com
 User git
 IdentityFile C:/Users/username/.ssh/id_rsa

# second user(second@mail.com)
Host github-second
 HostName github.com
 User git
 IdentityFile C:/Users/username/.ssh/id_rsa_second</pre>
<p><span id="more-2269"></span>配置完成后，在连接非默认帐号的github仓库时，远程库的地址要对应地做一些修改，比如现在添加second帐号下的一个仓库test，则需要这样添加：</p>
<pre>git remote add test git@github-second:second/test.git #并非原来的git@github.com:second/test.git</pre>
<p>这样每次连接都会使用id_rsa_second与服务器进行连接。至此，大功告成！</p>
<p><strong>注意：</strong>github根据配置文件的user.email来获取github帐号显示author信息，所以对于多帐号用户一定要记得将user.email改为相应的email(second@mail.com)。</p>
<p>参考github帮助文档：</p>
<ul>
<li><a href="http://help.github.com/win-set-up-git/" target="_blank">http://help.github.com/win-set-up-git/</a></li>
<li><a href="http://help.github.com/multiple-ssh-keys/" target="_blank">http://help.github.com/multiple-ssh-keys/</a></li>
</ul>
<hr />
<p><small>© omiga for <a href="http://omiga.org/blog">omiga</a>, 2011. |
<a href="http://omiga.org/blog/archives/2269">Permalink</a> |
<a href="http://omiga.org/blog/archives/2269#comments">2 comments</a> |
Add to
<a href="http://del.icio.us/post?url=http://omiga.org/blog/archives/2269&title=多个github帐号的SSH key切换">del.icio.us</a>
<br/>
Post tags: <a href="http://omiga.org/blog/archives/tag/git" rel="tag">git</a>, <a href="http://omiga.org/blog/archives/tag/github" rel="tag">github</a>, <a href="http://omiga.org/blog/archives/tag/ssh" rel="tag">SSH</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://omiga.org/blog/archives/2269/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>JavaScript中的property和attribute</title>
		<link>http://omiga.org/blog/archives/2055</link>
		<comments>http://omiga.org/blog/archives/2055#comments</comments>
		<pubDate>Wed, 12 Oct 2011 09:41:19 +0000</pubDate>
		<dc:creator>omiga</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[attr]]></category>
		<category><![CDATA[attribute]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[prop]]></category>
		<category><![CDATA[property]]></category>

		<guid isPermaLink="false">http://omiga.org/blog/?p=2055</guid>
		<description><![CDATA[首先看看这两个单词的英文释义（来自有道词典）。先是property： property ['prɔpəti] n. 性质，性能；财产；所有权 英英释义： any area set aside for a particular purpose “the president was concerned about the property across from the White House” 同义词：place something owned; any tangible or intangible possession that is owned by someone “that hat is my property”; ” he is a man of property” 同义词：belongings &#124; holding &#124; material possession a basic or essential attribute [...]]]></description>
			<content:encoded><![CDATA[<p>首先看看这两个单词的英文释义（来自有道词典）。先是property：</p>
<blockquote><p>property ['prɔpəti]</p>
<p>n. 性质，性能；财产；所有权</p>
<p>英英释义：</p>
<ol>
<li>any area set aside for a particular purpose <em>“the president was concerned about the property across from the White House”<br />
</em>同义词：<a href="http://dict.youdao.com/search?q=place&amp;tab=eng&amp;keyfrom=dict.eesy">place</a></li>
<li>something owned; any tangible or intangible possession that is owned by someone <em>“that hat is my property”; ” he is a man of property”<br />
</em>同义词：<a href="http://dict.youdao.com/search?q=belongings&amp;tab=eng&amp;keyfrom=dict.eesy">belongings</a> | <a href="http://dict.youdao.com/search?q=+holding&amp;tab=eng&amp;keyfrom=dict.eesy">holding</a> | <a href="http://dict.youdao.com/search?q=+material+possession&amp;tab=eng&amp;keyfrom=dict.eesy">material possession</a></li>
<li>a basic or essential attribute shared by all members of a class</li>
<li>a construct whereby objects or individuals can be distinguished <em>“self-confidence is not an endearing property”<br />
</em>同义词：<a href="http://dict.youdao.com/search?q=attribute&amp;tab=eng&amp;keyfrom=dict.eesy">attribute</a> | <a href="http://dict.youdao.com/search?q=+dimension&amp;tab=eng&amp;keyfrom=dict.eesy">dimension</a></li>
<li>any movable articles or objects used on the set of a play or movie<br />
同义词：<a href="http://dict.youdao.com/search?q=prop&amp;tab=eng&amp;keyfrom=dict.eesy">prop</a></li>
</ol>
</blockquote>
<p>重点看2、3、4条。</p>
<p>再看attribute：</p>
<blockquote><p>attribute [ə'tribju:t, 'ætribju:t]</p>
<p>n. 属性；特质<br />
vt. 归属；把…归于</p>
<p>英英释义：</p>
<p>n.</p>
<ol>
<li>a construct whereby objects or individuals can be distinguished<br />
同义词：<a href="http://dict.youdao.com/search?q=property&amp;tab=eng&amp;keyfrom=dict.eesy">property</a> | <a href="http://dict.youdao.com/search?q=+dimension&amp;tab=eng&amp;keyfrom=dict.eesy">dimension</a></li>
<li>an abstraction belonging to or characteristic of an entity</li>
</ol>
<p>v.</p>
<ol>
<li>attribute or credit to ”We attributed this quotation to Shakespeare”<br />
同义词：<a href="http://dict.youdao.com/search?q=impute&amp;tab=eng&amp;keyfrom=dict.eesy">impute</a> | <a href="http://dict.youdao.com/search?q=+ascribe&amp;tab=eng&amp;keyfrom=dict.eesy">ascribe</a> | <a href="http://dict.youdao.com/search?q=+assign&amp;tab=eng&amp;keyfrom=dict.eesy">assign</a></li>
<li>decide as to where something belongs in a scheme<br />
同义词：<a href="http://dict.youdao.com/search?q=assign&amp;tab=eng&amp;keyfrom=dict.eesy">assign</a></li>
</ol>
</blockquote>
<p>property，attribute都作“属性”解，但是attribute更强调区别于其他事物的特质/特性，而在<a title="Attribute和Property之区别" href="http://www.blogjava.net/wxb_nudt/archive/2005/06/20/6409.html" target="_blank">这篇文章中</a>也提交到<strong>attribute是property的子集</strong>。</p>
<p>而在JavaScript中，property和attribute更是有明显的区别。众所周知，setAttribute是为DOM节点设置/添加属性的标准方法：</p>
<pre>var ele = document.getElementById("my_ele");
ele.setAttribute("title","it's my element");</pre>
<p>但很多时候我们也这样写：</p>
<pre>ele.title = "it's my element";</pre>
<p>如果不出什么意外，他们都运行的很好，它们似乎毫无区别？而且通常情况下我们还想获取到我们设置的“属性”，我们也很爱这样写：</p>
<pre>alert(ele.title);</pre>
<p>这时候，你便会遇到问题，如果你所设置的属性属于DOM元素本身所具有的标准属性，不管是通过ele.setAttribute还是ele.title的方式设置，都能正常获取。但是如果设置的属性不是标准属性，而是自定义属性呢？</p>
<p><span id="more-2055"></span></p>
<pre>ele.setAttribute('mytitle','test my title');
alert(ele.mytitle);  //undefined
alert(ele.getAttribute('mytitle'));  //'test my title'

ele.yourtitle = 'your test title';
alert(ele.getAttribute('yourtitle'));  //null
alert(ele.yourtitle);  //'your test title'</pre>
<p>通过setAttribute设置的自定义属性，只能通过标准的getAttribute方法来获取；同样通过点号方式设置的自定义属性也无法通过标准方法getAttribute来获取。在对自定义属性的处理方式上，DOM属性的标准方法和点号方法不再具有任何关联性（上诉代码在IE6-有兼容性问题，后面会继续介绍）。</p>
<p>这种设置、获取“属性”的差异性，究其根源，其实也是property与attribute的差异性所致。</p>
<p>通过点号设置的“属性”其实是设置的property，如上所说attribute是property的子集，那么点号设置的property自然无法通过只能获取attribute的getAttribute方法来获取。</p>
<div id="attachment_2223" class="wp-caption alignnone" style="width: 286px"><a href="http://omiga.org/img/prop_attr.png"><img class="size-full wp-image-2223" title="prop_attr" src="http://omiga.org/img/prop_attr.png" alt="property and attribute" width="276" height="211" /></a><p class="wp-caption-text">property and attribute</p></div>
<p>照图似乎更易理解，getAttribute无法获取到不属于attribute的property也是理所应当。但是这时候你会发现另外一个问题，通过setAttribute设置的属性，同样也应该属于property，那么为何无法通过点号获取？</p>
<p>我们换种理解，只有标准属性才可同时使用标准方法和点号方法，而对于自定义属性，标准方法和点号方法互不干扰。</p>
<div id="attachment_2225" class="wp-caption alignnone" style="width: 332px"><a href="http://omiga.org/img/prop_attr2.png"><img class="size-full wp-image-2225" title="自定义属性互不干扰" src="http://omiga.org/img/prop_attr2.png" alt="自定义属性互不干扰" width="322" height="206" /></a><p class="wp-caption-text">自定义属性互不干扰</p></div>
<p>那么，在JavaScript中<strong>attribute并不是property的子集，property与attribute仅存在交集，即标准属性</strong>，这样疑问都可得到合理的解释。</p>
<p>但在IE9-中，上诉结论并不成立。IE9-浏览器中，除了标准属性，自定义属性也是共享的，即标准方法和点号皆可读写。</p>
<p>成功设置的attribute都会体现在HTML上，通过outerHTML可以看到attribute都被添加到了相应的tag上，所以如果attribute不是字符串类型数据都会调用toString()方法进行转换。但是由于IE9-中，标准属性与自定义属性不做区分，attribute依然可以是任意类型数据，并不会调用toString()转换，非字符串attribute不会体现在HTML上，但更为严重的问题是，这样很容易就会导致<a title="ie内存泄漏" href="http://birdshome.cnblogs.com/archive/2006/05/28/IE_MemoryLeak.html" target="_blank">内存泄漏</a>。所以如果不是字符串类型的自定义属性，建议使用成熟框架中的相关方法（如jQuery中的data方法）。</p>
<h2>getAttribute与点号(.)的差异性</h2>
<p>虽然getAttribute和点号方法都能获取标准属性，但是他们对于某些属性，获取到的值存在差异性，比如href,src,value等。</p>
<pre>&lt;a href="#" id="link"&gt;Test Link&lt;/a&gt;
&lt;img src="img.png" id="image" /&gt;
&lt;input type="text" value="enter text" id="ipt" /&gt;
&lt;script&gt;
var $ = function(id){return document.getElementById(id);};
alert($('link').getAttribute('href')); //#
alert($('link').href); //fullpath/file.html#

alert($('image').getAttribute('src')) //img.png
alert($('image').src) //fullpath/img.png

alert($('ipt').getAttribute('value')) //enter text
alert($('ipt').value) //enter text
$('ipt').value = 5;
alert($('ipt').getAttribute('value')) //enter text
alert($('ipt').value) //5
&lt;/script&gt;</pre>
<p>测试可发现<strong>getAttribute获取的是元素属性的字面量，而点号获取的是计算值</strong>。</p>
<p>更多细节可查看这篇文章：<a title="Attributes and custom properties" href="http://javascript.info/tutorial/attributes-and-custom-properties" target="_blank">Attributes and custom properties</a></p>
<h1></h1>
<hr />
<p><small>© omiga for <a href="http://omiga.org/blog">omiga</a>, 2011. |
<a href="http://omiga.org/blog/archives/2055">Permalink</a> |
<a href="http://omiga.org/blog/archives/2055#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://omiga.org/blog/archives/2055&title=JavaScript中的property和attribute">del.icio.us</a>
<br/>
Post tags: <a href="http://omiga.org/blog/archives/tag/attr" rel="tag">attr</a>, <a href="http://omiga.org/blog/archives/tag/attribute" rel="tag">attribute</a>, <a href="http://omiga.org/blog/archives/tag/data" rel="tag">data</a>, <a href="http://omiga.org/blog/archives/tag/jquery" rel="tag">jQuery</a>, <a href="http://omiga.org/blog/archives/tag/prop" rel="tag">prop</a>, <a href="http://omiga.org/blog/archives/tag/property" rel="tag">property</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://omiga.org/blog/archives/2055/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SSI详解</title>
		<link>http://omiga.org/blog/archives/2069</link>
		<comments>http://omiga.org/blog/archives/2069#comments</comments>
		<pubDate>Fri, 30 Sep 2011 09:24:24 +0000</pubDate>
		<dc:creator>omiga</dc:creator>
				<category><![CDATA[LAMP]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[httpd.conf]]></category>
		<category><![CDATA[include]]></category>
		<category><![CDATA[SSI]]></category>

		<guid isPermaLink="false">http://omiga.org/blog/?p=2069</guid>
		<description><![CDATA[SSI（Server Side Include）使用在HTML中，用于在请求内容返回到客户端前执行页面中的SSI命令，生成动态内容。通常用于多个页面引用公共的内容模块，将此模块分离出来，使用SSI引入即可。 &#60;!--#include virtual="/inc/header.html"--&#62; 以上代码便能在服务端完成header.html的动态引入，非常简单。 服务端配置 使用SSI之前需要服务端进行简单的配置，开启SSI功能。SSI是针对HTML增加动态内容的技术，所以只对HTML类型文件（.html,.shtml），使用SSI功能的文件建议使用.shtml后缀，便于维护。如果使用.shtml后缀需在服务端作一些配置： AddType text/html .shtml AddOutputFilter INCLUDES .shtml 第一行命名配置将.shtml作为html文件返回 第二行命令用于在返回请求内容前执行页面中的SSI命令，如果你在.html文件中使用SSI，那么将.shtml改为.html即可。 SSI命令 SSI的语法有点像HTML注释，所以如果SSI不能识别，那么将被视作HTML注释处理。SSI的语法功能主要包括：变量的设置/获取，文件的引用，可执行命令，条件表达式等。 SSI基本语法 &#60;!--#command param="value"--&#62; SSI的语法非常简单，但使用中需注意以下几点： &#60;!&#8211;与#之间无空格 SSI大小写敏感 所有value需写在引号中 config命令 config命令主要用于修改SSI的默认设置，诸如时间格式，默认错误信息，文件大小单位。 设置默认错误信息：errmsg &#60;!--#config errmsg="Error,please contact webmaster@mail.com"--&#62; 定义日期和时间格式：timefmt &#60;!--#config timefmt="%A, %B %d, %Y"--&#62; 定义文件大小单位 &#60;!--#config sizefmt="bytes"--&#62; config命令只对其后使用的命令生效。同时，后定义的设置具有更高的优先级，会覆盖之前的设置。 include命令 include命名可能是SSI中使用最多的命令，也是SSI最主要的功能体现，include命令可以将其他文件引用到当前文档中。 &#60;!--#include virtual="/inc/header.inc"--&#62; &#60;!--#include file="inc/desc.inc"--&#62; include命令支持通过虚拟路径引入文件（virtual），以及相对路径引入文件（file）。 include命令支持引用任何类型的文件，不过我建议最好将需要引入的文件名后缀设置为.inc，或放入固定的文件目录，方便管理。 set命令 使用SSI同样可以使用set进行变量的定义： &#60;!--#set var="blog" value="http://omiga.org/"--&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>SSI（Server Side Include）使用在HTML中，用于在请求内容返回到客户端前执行页面中的SSI命令，生成动态内容。通常用于多个页面引用公共的内容模块，将此模块分离出来，使用SSI引入即可。</p>
<pre>&lt;!--#include virtual="/inc/header.html"--&gt;</pre>
<p>以上代码便能在服务端完成header.html的动态引入，非常简单。</p>
<h2>服务端配置</h2>
<p>使用SSI之前需要服务端进行简单的配置，开启SSI功能。SSI是针对HTML增加动态内容的技术，所以只对HTML类型文件（.html,.shtml），使用SSI功能的文件建议使用.shtml后缀，便于维护。如果使用.shtml后缀需在服务端作一些配置：</p>
<pre>AddType text/html .shtml
AddOutputFilter INCLUDES .shtml</pre>
<p>第一行命名配置将.shtml作为html文件返回</p>
<p>第二行命令用于在返回请求内容前执行页面中的SSI命令，如果你在.html文件中使用SSI，那么将.shtml改为.html即可。</p>
<h2>SSI命令</h2>
<p>SSI的语法有点像HTML注释，所以如果SSI不能识别，那么将被视作HTML注释处理。SSI的语法功能主要包括：变量的设置/获取，文件的引用，可执行命令，条件表达式等。</p>
<h3>SSI基本语法</h3>
<pre>&lt;!--#command param="value"--&gt;</pre>
<p>SSI的语法非常简单，但使用中需注意以下几点：</p>
<ol>
<li>&lt;!&#8211;与#之间无空格</li>
<li>SSI大小写敏感</li>
<li>所有value需写在引号中</li>
</ol>
<h3>config命令</h3>
<p>config命令主要用于修改SSI的默认设置，诸如时间格式，默认错误信息，文件大小单位。</p>
<p>设置默认错误信息：errmsg</p>
<pre>&lt;!--#config errmsg="Error,please contact webmaster@mail.com"--&gt;</pre>
<p>定义日期和时间格式：timefmt</p>
<pre>&lt;!--#config timefmt="%A, %B %d, %Y"--&gt;</pre>
<p>定义文件大小单位</p>
<pre>&lt;!--#config sizefmt="bytes"--&gt;</pre>
<p>config命令只对其后使用的命令生效。同时，后定义的设置具有更高的优先级，会覆盖之前的设置。</p>
<p><span id="more-2069"></span></p>
<h3>include命令</h3>
<p>include命名可能是SSI中使用最多的命令，也是SSI最主要的功能体现，include命令可以将其他文件引用到当前文档中。</p>
<pre>&lt;!--#include virtual="/inc/header.inc"--&gt;
&lt;!--#include file="inc/desc.inc"--&gt;</pre>
<p>include命令支持通过虚拟路径引入文件（virtual），以及相对路径引入文件（file）。</p>
<p>include命令支持引用任何类型的文件，不过我建议最好将需要引入的文件名后缀设置为.inc，或放入固定的文件目录，方便管理。</p>
<h3>set命令</h3>
<p>使用SSI同样可以使用set进行变量的定义：</p>
<pre>&lt;!--#set var="blog" value="http://omiga.org/"--&gt;</pre>
<p>变量定义后便可以使用了：</p>
<pre>&lt;!--#echo var="blog"--&gt;</pre>
<pre>定义变量时使用环境变量：</pre>
<pre>&lt;!--#set var="fname" value="${DOCUMENT_NAME}${DOCUMENT_URI}"--&gt;</pre>
<p>如果是单个环境变量可以不使用{}分割：</p>
<pre>&lt;!--#set var="fname" value="$DOCUMENT_NAME"--&gt;</pre>
<p>环境变量的引用都需要使用$前缀，如果$仅作为字符使用，通过\$转义即可。</p>
<h3>echo命令</h3>
<p>echo显示变量值，包括自定义变量、环境变量</p>
<p>&lt;!&#8211;#echo var=”DOCUMENT_NAME”&#8211;&gt;</p>
<p>注意：echo命令中使用的环境变量不需要使用$前缀。</p>
<p>SSI的主要环境变量如下：</p>
<table>
<tbody>
<tr>
<th>name</th>
<th>description</th>
<th>type</th>
</tr>
<tr>
<td>DOCUMENT_NAME</td>
<td>当前文档名</td>
<td>SSI</td>
</tr>
<tr>
<td>DOCUMENT_URI</td>
<td>当前文档虚拟路径</td>
<td>SSI</td>
</tr>
<tr>
<td>QUERY_STRING_UNESCAPED</td>
<td>未经转义处理的由客户端发送的查询字串，所有的特殊字符前面都有转义符”\”</td>
<td>SSI</td>
</tr>
<tr>
<td>DATE_LOCAL</td>
<td>服务器设定时区的日期和时间</td>
<td>SSI</td>
</tr>
<tr>
<td>DATE_GMT</td>
<td>功能与DATE_LOCAL一样，但返回的是以格林尼治标准时间为基准的日期</td>
<td>SSI</td>
</tr>
<tr>
<td>LAST_MODIFIED</td>
<td>当前文档的最后更新时间</td>
<td>SSI</td>
</tr>
<tr>
<td>SERVER_SOFTWARE</td>
<td>服务器软件的名称和版本</td>
<td>CGI</td>
</tr>
<tr>
<td>SERVER_NAME</td>
<td>服务器的主机名称，DNS别名或IP地址</td>
<td>CGI</td>
</tr>
<tr>
<td>SERVER_PROTOCOL</td>
<td>客户端请求所使用的协议名称和版本</td>
<td>CGI</td>
</tr>
<tr>
<td>SERVER_PORT</td>
<td>服务器的响应端口</td>
<td>CGI</td>
</tr>
<tr>
<td>REMOTE_HOST</td>
<td>发出请求信息的客户端主机名称</td>
<td>CGI</td>
</tr>
<tr>
<td>REMOTE_ADDR</td>
<td>发出请求信息的客户端IP地址</td>
<td>CGI</td>
</tr>
<tr>
<td>AUTH_TYPE</td>
<td>用户身份的验证方法</td>
<td>CGI</td>
</tr>
<tr>
<td>REMOTE_USER</td>
<td>访问受保护页面的用户所使用的帐号名称</td>
<td>CGI</td>
</tr>
</tbody>
</table>
<p>更多的环境变量可使用printenv命令查看</p>
<h3>printenv命令</h3>
<p>显示所有环境变量</p>
<pre>&lt;!--#printenv --&gt;</pre>
<h3>fsize命令</h3>
<p>显示指定文件的大小，可结合config sizefmt指定输出格式。</p>
<pre>&lt;!--输出当前文档大小--&gt;
&lt;!--#fsize file="$DOCUMENT_NAME"--&gt;
&lt;!--#fsize virtual="$DOCUMENT_URI"--&gt;</pre>
<h3>flastmod命令</h3>
<p>显示指定文件的最后更新日期，可结合config sizefmt指定输出格式。</p>
<pre>&lt;!--输出当前文档大小--&gt;
&lt;!--#flastmod file="$DOCUMENT_NAME"--&gt;
&lt;!--#flastmod virtual="$DOCUMENT_URI"--&gt;</pre>
<h3>exec命令</h3>
<p>Exec 命令可以执行 CGI 脚本或者 shell 命令。使用方法如下：</p>
<ul>
<li>CMD：使用 /bin/sh 执行指定的字串。如果 SSI 使用了 IncludesNOEXEC 选项，则该命令将被屏蔽</li>
<li>CGI：可以用来执行 CGI 脚本</li>
</ul>
<h3>if…语句</h3>
<p>SSI中也可以是用条件判断语句if，语法如下：</p>
<pre>&lt;!--#if expr="test_condition" --&gt;
&lt;!--#elif expr="test_condition" --&gt;
&lt;!--#else --&gt;
&lt;!--#endif --&gt;</pre>
<p>示例：</p>
<pre>&lt;!--#if expr="$DOCUMENT_NAME=index.shtml"--&gt;
&lt;p&gt;这是通过if判断当前文档名为"index.shtml"后显示&lt;/p&gt;
&lt;!--#elif expr="$DOCUMENT_NAME=index.html"--&gt;
&lt;p&gt;这是通过if判断当前文档名为"index.html"后显示&lt;/p&gt;
&lt;!--#else --&gt;
&lt;p&gt;既不是"index.shtml"，也不是"index.html"&lt;/p&gt;
&lt;!--#endif --&gt;</pre>
<p><a title="SSI详解" href="http://omiga.org/lab/ssi/" target="_blank">demo</a></p>
<p>&nbsp;</p>
<p>SSI还是在之前公司的使用经常用，好几月不用，所剩已经寥寥。挺好的技术，而且简单方便，于是整理篇文章记录一下。</p>
<hr />
<p><small>© omiga for <a href="http://omiga.org/blog">omiga</a>, 2011. |
<a href="http://omiga.org/blog/archives/2069">Permalink</a> |
<a href="http://omiga.org/blog/archives/2069#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://omiga.org/blog/archives/2069&title=SSI详解">del.icio.us</a>
<br/>
Post tags: <a href="http://omiga.org/blog/archives/tag/apache" rel="tag">apache</a>, <a href="http://omiga.org/blog/archives/tag/httpd-conf" rel="tag">httpd.conf</a>, <a href="http://omiga.org/blog/archives/tag/include" rel="tag">include</a>, <a href="http://omiga.org/blog/archives/tag/ssi" rel="tag">SSI</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://omiga.org/blog/archives/2069/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>博客手机版</title>
		<link>http://omiga.org/blog/archives/2073</link>
		<comments>http://omiga.org/blog/archives/2073#comments</comments>
		<pubDate>Sun, 25 Sep 2011 16:30:03 +0000</pubDate>
		<dc:creator>omiga</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[andriod]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[博客]]></category>

		<guid isPermaLink="false">http://omiga.org/blog/?p=2073</guid>
		<description><![CDATA[心血来潮，简单弄了个手机版。用USER_AGENT判断了下客户端，不是很准确，基本能用。手机上算是比之前web版看得舒服一点，暂时就这样了～··· © omiga for omiga, 2011. &#124; Permalink &#124; 4 comments &#124; Add to del.icio.us Post tags: andriod, wordpress, 博客]]></description>
			<content:encoded><![CDATA[<p>心血来潮，简单弄了个手机版。用USER_AGENT判断了下客户端，不是很准确，基本能用。手机上算是比之前web版看得舒服一点，暂时就这样了～···</p>
<div id="attachment_2074" class="wp-caption alignnone" style="width: 520px"><a href="http://omiga.org/img/omiga_m.jpg" target="_blank"><img class="size-full wp-image-2074  " title="omiga手机版" src="http://omiga.org/img/omiga_m.jpg" alt="omiga手机版" width="510" height="418" /></a><p class="wp-caption-text">omiga手机版</p></div>
<hr />
<p><small>© omiga for <a href="http://omiga.org/blog">omiga</a>, 2011. |
<a href="http://omiga.org/blog/archives/2073">Permalink</a> |
<a href="http://omiga.org/blog/archives/2073#comments">4 comments</a> |
Add to
<a href="http://del.icio.us/post?url=http://omiga.org/blog/archives/2073&title=博客手机版">del.icio.us</a>
<br/>
Post tags: <a href="http://omiga.org/blog/archives/tag/andriod" rel="tag">andriod</a>, <a href="http://omiga.org/blog/archives/tag/wordpress" rel="tag">wordpress</a>, <a href="http://omiga.org/blog/archives/tag/%e5%8d%9a%e5%ae%a2" rel="tag">博客</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://omiga.org/blog/archives/2073/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Git笔记-进阶</title>
		<link>http://omiga.org/blog/archives/2017</link>
		<comments>http://omiga.org/blog/archives/2017#comments</comments>
		<pubDate>Mon, 12 Sep 2011 09:33:13 +0000</pubDate>
		<dc:creator>omiga</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[msysgit]]></category>
		<category><![CDATA[SCM]]></category>
		<category><![CDATA[SVN]]></category>

		<guid isPermaLink="false">http://omiga.org/blog/?p=2017</guid>
		<description><![CDATA[tag 在git中可以为任意其他对象添加tag，包括commit，tree，blob，甚至包括tag自身。git中都是用sha-1标识git对象，这是一个40个字符长度的字符串，不方便记忆，那么可为git对象添加一个tag便于标识不同对象。 添加tag # git tag tag-name sha-1 $ git tag v1.0 bdc390c2 这样便为bdc390c2的对象添加了一个tag，如果不指定sha-1，会为最近的一个commit对象添加tag 查看tag 使用git tag命令便能查看所有tag $ git tag 当然可以筛选 $ git tag -l 'v1.*' 删除tag $ git tag -d &#60;tag-name&#62; 重命名tag 重命名tag有两种方式： 删除原tag，重新添加 git tag -f 强制替换已存在的tag后，再删除原tag $ git tag -f &#60;new-tag&#62; &#60;old-tag&#62; $ git tag -d &#60;old-tag&#62; tag的分类 轻量型标签 轻量型标签直接使用 $ git [...]]]></description>
			<content:encoded><![CDATA[<h2>tag</h2>
<p>在git中可以为任意其他对象添加tag，包括commit，tree，blob，甚至包括tag自身。git中都是用sha-1标识git对象，这是一个40个字符长度的字符串，不方便记忆，那么可为git对象添加一个tag便于标识不同对象。</p>
<h3>添加tag</h3>
<pre># git tag tag-name sha-1
$ git tag v1.0 bdc390c2</pre>
<p>这样便为bdc390c2的对象添加了一个tag，如果不指定sha-1，会为最近的一个commit对象添加tag</p>
<h3>查看tag</h3>
<p>使用git tag命令便能查看所有tag</p>
<pre>$ git tag</pre>
<p>当然可以筛选</p>
<pre>$ git tag -l 'v1.*'</pre>
<h3>删除tag</h3>
<pre>$ git tag -d &lt;tag-name&gt;</pre>
<h3>重命名tag</h3>
<p>重命名tag有两种方式：</p>
<ol>
<li>删除原tag，重新添加</li>
<li>git tag -f 强制替换已存在的tag后，再删除原tag</li>
</ol>
<pre>$ git tag -f &lt;new-tag&gt; &lt;old-tag&gt;
$ git tag -d &lt;old-tag&gt;</pre>
<h3>tag的分类</h3>
<ol>
<li>轻量型标签 轻量型标签直接使用 $ git tag &lt;tag-name&gt; &lt;git-object&gt; 即可创建</li>
<li>标注型(annotated)标签 标注型标签可记录更多的信息，使用 $ git tag -a &lt;tag-name&gt; &lt;git-object&gt; -m &#8216;tag message&#8217;即可创意一个标注性标签</li>
</ol>
<div><span id="more-2017"></span></div>
<h3><span class="Apple-style-span" style="font-size: 20px;">分支</span></h3>
<p>建议多使用分支来维护项目，便于保证主干的稳定性。</p>
<h3>创建分支</h3>
<p>git中创建分支的方法非常简单：</p>
<pre>#git branch &lt;branch-name&gt;
$ git branch dev</pre>
<p>这样便从当前分支创建了一个名为dev的分支，可以让此分支作为开发分支。使用checkout &lt;branch-name&gt;可以很方便地在分支间进行切换：</p>
<pre>$ git checkout master
$ git checkout dev</pre>
<p>还可以直接使用checkout -b命令来创建分支后并切换到新的分支</p>
<pre>$ git checkout -b dev</pre>
<h3>重命名分支</h3>
<pre>$ git branch -rm &lt;old-branch&gt; &lt;new-branch&gt;</pre>
<h3>远程分支</h3>
<p>推送本地分支到远程服务器</p>
<pre>$ git push &lt;remote&gt; &lt;branch-name&gt;[:&lt;remote-branch-name&gt;]</pre>
<p>远程分支名如果省略，则使用本地分支名作为远程分支名</p>
<pre>$ git push &lt;remote&gt; &lt;branch-name&gt;</pre>
<h3>删除分支</h3>
<pre># 删除分支
$ git branch -d &lt;branch-name&gt;
# 强制删除分支
$ git branch -D &lt;branch-name&gt;</pre>
<p>删除远程分支</p>
<pre>$ git push &lt;remote&gt; :&lt;remote-branch-name&gt;</pre>
<p>这个命令是不是可以从推送本地分支到远程分支的命令中得到一点灵感？是的，省略本地分支名后，远程分支即被删除！</p>
<h3>查看分支</h3>
<p>使用git branch命令可查看当前git版本库中所有分支：</p>
<pre>$ git branch</pre>
<div id="attachment_2047" class="wp-caption alignnone" style="width: 110px"><img class="size-full wp-image-2047" title="查看分支" src="http://omiga.org/img/branch.jpg" alt="查看分支" width="100" height="55" /><p class="wp-caption-text">查看分支</p></div>
<p>当前分支会在分支前加以星号（*）标注。</p>
<p>git branch -v命令将附加显示最后一次提交相关信息的分支信息</p>
<pre>$ git branch -v
# 查看已合并的分支
$ git branch --merge
# 查看未合并的分支
$ git branch --no-merged</pre>
<h3>分支合并</h3>
<p>当一个分支完成预期的工作，通过测试后，便可合并到主干，作为稳定版本进行后续开发，合并分支的命令非常简单：merge branch-name</p>
<pre>$ git merge dev</pre>
<p>如果顺利，dev分支将自动地合并到当前分支。当然很多时候会产生冲突，这个时候就需要手动坚决冲突后再进行合并。</p>
<p>在git中如遇冲突，会显示冲突提示，合并会中断</p>
<div id="attachment_2062" class="wp-caption alignnone" style="width: 530px"><img class="size-full wp-image-2062" title="conflict" src="http://omiga.org/img/conflict.jpg" alt="conflict" width="520" height="78" /><p class="wp-caption-text">conflict</p></div>
<p>此时你可以使用git mergetool命令调用merge工具进行手动合并</p>
<pre>$ git mergetool</pre>
<p>mergetool在配置项进行配置，以下是使用vimdiff的merge操作界面</p>
<div id="attachment_2063" class="wp-caption alignnone" style="width: 653px"><img class="size-full wp-image-2063" title="mergetool vimdiff" src="http://omiga.org/img/mergetool.jpg" alt="mergetool vimdiff" width="643" height="403" /><p class="wp-caption-text">mergetool vimdiff</p></div>
<p>手动解决完冲突后，还需要进行一次提交，便完成了整个手动合并过程。</p>
<h3>rebase</h3>
<p>rebase亦是将分支的修改进行“合并”。但在具体行为上略有不同，使用merge进行合并，更新部分依然会视作是从分支而来；而rebase则是直接将更新合并到新分支，相当于是在合并分支的直接修改。如果我们的更新是非常小，不足以作为一个分支进行合并，并且不想污染版本日志，那么便可以使用rebase来合并更新。</p>
<h2>ignore</h2>
<p>在一个git版本仓库中，有时候很多文件/目录并不需要使用git进行版本维护，那么就可以将这些文件/目录加入.gitignore文件中，在.gitignore文件中可定义要排除在git版本管理之外的文件/目录，git默认会读取项目目录下的.gitignore文件。</p>
<p>.gitignore使用标准的shell glob模式匹配，shell glob你可以简单地理解为一种特特殊化的正则表达式，其实要比正则表达式简单许多，语法如下：</p>
<ul>
<li> 允许使用空行，没有实际语法作用</li>
<li># 开头的行视作注释</li>
<li>! 开头的模式会覆盖之前的定义，将匹配的对象重新加入跟踪列表</li>
<li>以/结尾的模式，git会屏蔽掉该目录及其所有子目录及文件（只屏蔽目录）</li>
<li>不以/结尾的模式，git屏蔽同名的文件名及目录（屏蔽目录和同名文件）</li>
<li>以/开头的模式，git只会屏蔽项目根目录下的匹配对象</li>
</ul>
<div>示例：</div>
<pre>#.gitignore example
.txt
.gitignore
!readme.txt
exclude/*.txt</pre>
<p>该.gitignore中定义的屏蔽规则为：</p>
<p>屏蔽所有的txt文件，但是readme.txt例外；屏蔽所有的.gitignore文件；屏蔽exclude目录下的所有txt文件（包括readme.txt）。</p>
<p>另外，还可以在配置项中通过<span class="Apple-style-span">c</span><span class="Apple-style-span">ore.excludesfile来指定ignore文件。</span></p>
<pre>$ git config core.excludesfile '_myignore'</pre>
<h2>git配置</h2>
<p>git配置文件根据作用域的不同分为三种：</p>
<ul>
<li>系统配置文件（git安装目录/gitconfig）</li>
<li>用户配置文件（用户主目录/.gitconfig）</li>
<li>项目配置文件（.git/config）</li>
</ul>
<p>git配置项都通过git config命令写入，传入不同参数写入不同的配置文件</p>
<pre>$ git config --system/--global/</pre>
<ul>
<li>git config &#8211;system 写入系统配置</li>
<li>git config &#8211;global 写入用户配置</li>
<li>git config 写入项目配置</li>
</ul>
<p>具体的配置项设置参考帮助文档，$ git config &#8211;help</p>
<h2>git中的对象</h2>
<div id="attachment_2123" class="wp-caption alignnone" style="width: 510px"><a href="http://omiga.org/img/git-object.png"><img class="size-full wp-image-2123" title="git对象" src="http://omiga.org/img/git-object.png" alt="git对象" width="500" height="338" /></a><p class="wp-caption-text">git对象</p></div>
<p>git中包含4类对象：</p>
<ul>
<li>commit 提交对象</li>
<li>tree 目录</li>
<li>blob 文件</li>
<li>tag 标记</li>
</ul>
<p>git提交便产生一个commit对象，commit对象中包含一个tree对象，tree对象中又会包含其他的tree对象或是blob对象，blob对象是最小的组成单元，即独立的文件。每个对象都对应一个唯一的SHA-1值，只有当文件或目录有修改时这个值才会重新计算发生改变。</p>
<ul>
<li>$ git log 可以查看所有commit对象</li>
<li>$ git ls-tree &lt;commit&gt; 查看commit对象中的tree对象</li>
<li>$ git show &lt;blob&gt; 查看blob的具体内容</li>
</ul>
<h2>git原理</h2>
<p>究竟git是如何工作的？打开.git目录便可一目了然。</p>
<ul>
<li>HEAD 指向当前分支</li>
<li>config 项目配置文件</li>
<li>description 供GitWeb程序使用</li>
<li>hooks/ 客户端与服务端钩子脚本</li>
<li>info/ 忽略模式</li>
<li>index 暂存区域信息</li>
<li>objects/ 所有数据内容</li>
<li>refs/ 指向所有commit的指针</li>
</ul>
<p>HEAD文件中是形如以下代码的内容：</p>
<pre>ref: refs/heads/dev</pre>
<p>它指向refs/heads/dev，而dev文件中代码指向当前分支最近的commit对象</p>
<p>objects目录中保存有所有git对象，这些对象取sha-1值的前两个字母为一个目录，剩下的38个字符作为文件名保存，在上一节“git中对象”中能查看到的所有git对象都保存在这个目录中，可以使用git cat-file &lt;sha-1&gt;来获取对象内容。</p>
<pre>$ git cat-file -p 63a46849</pre>
<p>不妨多使用cat-file命名多看看各种对象的内容，有助于理解git对象的结构。</p>
<p>refs目录中保存了git中使用的所有引用或指针，因为不可能任何时候都是用sha-1值来指代对象，git对象也可以有“缩略名”。通常refs目录会包含以下目录：</p>
<ul>
<li>heads 保存所有分支的HEAD指针</li>
<li>remotes 保存远程仓库信息</li>
<li>tags 保存所有tag指针</li>
</ul>
<p>逐一地查看这些文件内容，你就什么都明白了。使用 git update-ref 命令可以直接新建一个引用。</p>
<pre>$ git update-ref refs/heads/test-branch c56dce
$ git update-ref refs/tags/test-tag c56dce</pre>
<p>执行上述命令，这样你的git版本库中就多了一个test-branch分支和一个名为test-tag的tag。</p>
<p>其他的比如git还有些底层的命令，我在文中所列举的，包括之前基础篇的都是一些高级命令。可以使用这些底层命名直接对git库进行一些操作，有关git底层命名的详细内容，可以到网上去找找。</p>
<hr />
<p><small>© omiga for <a href="http://omiga.org/blog">omiga</a>, 2011. |
<a href="http://omiga.org/blog/archives/2017">Permalink</a> |
<a href="http://omiga.org/blog/archives/2017#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://omiga.org/blog/archives/2017&title=Git笔记-进阶">del.icio.us</a>
<br/>
Post tags: <a href="http://omiga.org/blog/archives/tag/git" rel="tag">git</a>, <a href="http://omiga.org/blog/archives/tag/github" rel="tag">github</a>, <a href="http://omiga.org/blog/archives/tag/msysgit" rel="tag">msysgit</a>, <a href="http://omiga.org/blog/archives/tag/scm" rel="tag">SCM</a>, <a href="http://omiga.org/blog/archives/tag/svn" rel="tag">SVN</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://omiga.org/blog/archives/2017/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Git笔记-基础</title>
		<link>http://omiga.org/blog/archives/1896</link>
		<comments>http://omiga.org/blog/archives/1896#comments</comments>
		<pubDate>Wed, 10 Aug 2011 09:03:10 +0000</pubDate>
		<dc:creator>omiga</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[msysgit]]></category>
		<category><![CDATA[SCM]]></category>
		<category><![CDATA[SVN]]></category>
		<category><![CDATA[版本管理]]></category>

		<guid isPermaLink="false">http://omiga.org/blog/?p=1896</guid>
		<description><![CDATA[Git是什么？ Git是一个分布式版本控制系统（Distributed Version Control System，简称 DVCS）。 Git与svn有什么关系？ 对于大多数人而言，或许对svn更为熟悉，svn属于集中化的版本控制系统（ Centralized Version Control Systems，简称 CVCS ），在CVCS中会有一个对版本进行集中管理的服务器，协同工作的人都通过客户端连接到该服务器，检出最新文件或提交更新。CVCS在协同开发中有两个比较主要的缺点： 如遇服务器宕机，整个协同工作无法进行，因为此时无法进行代码更新提交，当然也不能checkout最新代码 如果服务器数据丢失，整个版本数据也将丢失，除非刻意为版本管理服务器备份 对于这两个主要问题，DVCS都有比较好的解决方案： 首先，DVCS可以方便地在本地进行版本管理，就如同在你本地有一个版本管理服务器一样。你可以选择在合适的时候将本地版本推送到统一的版本管理服务器。 其次，DVCS每次都会提取整个代码仓库的完整镜像，即相当于对整个代码仓库进行了一次备份。这样即使版本管理服务器出现意外，也可以轻松地采用任一本地仓库恢复。结合本地版本管理功能，在远程版本管理服务器出现故障的情况下，你依然可以放心的进行工作，当远程服务器恢复工作时，再提交你的本地版本。 直接记录快照，而非差异比较 Git只关心文件数据的整体是否发生变化，而大多数其他系统则关心文件内容的具体差异，并记录这些差异。git则是更像一个微型文件系统，保存更新文件的快照，并为之创建一个索引。 如何开始? 你需要安装一个Git客户端来开始使用Git，你可以使用msysgit作为你windows上的git客户端，msysgit包含一个命令行工具Git Bash和一个gui工具Git GUI。对于习惯TortoiseSVN的同学来说，或许Git GUI太简陋了，没关系，安装完msysgit后你依然可以安装TortoiseGit，实现svn到git的平滑过渡。TortoiseGit不单独介绍，本文主要介绍通过Git Bash使用git进行版本管理，在你熟悉Git Bash后相信你对TortoiseGit也会有更深入的掌握。 安装好msysgit后，运行Git Bash，在开始所有工作之前我们需要先做一些配置，现在我们只需做一些基础配置，详细的配置后面再讲： # 用户名 $ git config --global user.name 'omiga' # email $ git config --global user.email 'omiga@sample.com' # 文本编辑器，默认vim $ git config --global core.editor vim # [...]]]></description>
			<content:encoded><![CDATA[<h2>Git是什么？</h2>
<p>Git是一个分布式版本控制系统（Distributed Version Control System，简称 DVCS）。</p>
<h2>Git与svn有什么关系？</h2>
<p>对于大多数人而言，或许对svn更为熟悉，svn属于集中化的版本控制系统（ Centralized Version Control Systems，简称 CVCS ），在CVCS中会有一个对版本进行集中管理的服务器，协同工作的人都通过客户端连接到该服务器，<strong>检出最新文件或提交更新</strong>。CVCS在协同开发中有两个比较主要的缺点：</p>
<ol>
<li>如遇服务器宕机，整个协同工作无法进行，因为此时无法进行代码更新提交，当然也不能checkout最新代码</li>
<li>如果服务器数据丢失，整个版本数据也将丢失，除非刻意为版本管理服务器备份</li>
</ol>
<p>对于这两个主要问题，DVCS都有比较好的解决方案：</p>
<p>首先，DVCS可以方便地在本地进行版本管理，就如同在你本地有一个版本管理服务器一样。你可以选择在合适的时候将本地版本推送到统一的版本管理服务器。</p>
<p>其次，DVCS每次都会提取整个代码仓库的完整镜像，即相当于对整个代码仓库进行了一次备份。这样即使版本管理服务器出现意外，也可以轻松地采用任一本地仓库恢复。结合本地版本管理功能，在远程版本管理服务器出现故障的情况下，你依然可以放心的进行工作，当远程服务器恢复工作时，再提交你的本地版本。</p>
<h3 id="id228">直接记录快照，而非差异比较</h3>
<p>Git只关心文件数据的整体是否发生变化，而大多数其他系统则关心文件内容的具体差异，并记录这些差异。git则是更像一个微型文件系统，保存更新文件的快照，并为之创建一个索引。</p>
<div id="attachment_1911" class="wp-caption alignnone" style="width: 510px"><img class="size-full wp-image-1911" title="CVS，Subversion，Perforce，Bazaar 等等）每次记录有哪些文件作了更新，以及都更新了哪些行的什么内容" src="http://omiga.org/img/git-notes-01.png" alt="CVS，Subversion，Perforce，Bazaar 等等）每次记录有哪些文件作了更新，以及都更新了哪些行的什么内容" width="500" height="223" /><p class="wp-caption-text">CVS，Subversion，Perforce，Bazaar 等等）每次记录有哪些文件作了更新，以及都更新了哪些行的什么内容</p></div>
<div id="attachment_1912" class="wp-caption alignnone" style="width: 510px"><img class="size-full wp-image-1912" title="Git 保存每次更新时的文件快照" src="http://omiga.org/img/git-notes-02.png" alt="Git 保存每次更新时的文件快照" width="500" height="222" /><p class="wp-caption-text">Git 保存每次更新时的文件快照</p></div>
<h2 style="text-align: left;"><span style="font-size: 20px;">如何开始?</span></h2>
<p>你需要安装一个Git客户端来开始使用Git，你可以使用<a title="msysgit" href="http://code.google.com/p/msysgit/" target="_blank">msysgit</a>作为你windows上的git客户端，msysgit包含一个命令行工具Git Bash和一个gui工具Git GUI。对于习惯TortoiseSVN的同学来说，或许Git GUI太简陋了，没关系，安装完msysgit后你依然可以安装<a title="TortoiseGit" href="http://code.google.com/p/tortoisegit/" target="_blank">TortoiseGit</a>，实现svn到git的平滑过渡。TortoiseGit不单独介绍，本文主要介绍通过Git Bash使用git进行版本管理，在你熟悉Git Bash后相信你对TortoiseGit也会有更深入的掌握。</p>
<p>安装好msysgit后，运行Git Bash，在开始所有工作之前我们需要先做一些配置，现在我们只需做一些基础配置，详细的配置后面再讲：</p>
<pre># 用户名
$ git config --global user.name 'omiga'
# email
$ git config --global user.email 'omiga@sample.com'
# 文本编辑器，默认vim
$ git config --global core.editor vim
# 差异分析工具
$ git config --global merge.tool vimdiff</pre>
<p>因为每次提交git都会记录committer信息，完成上述配置后，通过cd命令进入到任意文件目录，然后使用git init命名即可初始化一个git版本库。</p>
<pre>$ cd /d/ohmygod
$ git init</pre>
<p>这样ohmygod目录下的任何改动都处于git版本库的管理下了。在该目录下创建一个README文件，再运行git status命令，将会看到git提示README文件处于为“Untracked files”列表中，并给出了“(use git add &lt;file&gt;&#8230; to include in what will be committed)”的建议。此时可以使用git add README命名将README文件加入到暂存区。</p>
<pre>$ git add README</pre>
<p>此时再执行git status，会看到“new file: README”的提示信息。继续执行git commit README -m “create README”</p>
<pre>$ git commit README -m "create README"</pre>
<p>这样README文件就被提交到了本地版本库，完成了一个文件从创建到提交的完整过程：</p>
<ol>
<li>git status &#8211; 查看git版本库的状态（这一步不是必须的，但是个好习惯）</li>
<li>git add &lt;file&gt; &#8211; 将文件提交到暂存区（通常是在通过git status命令后，可以很清楚地看到文件的变更信息，决定哪些文件需要提交到暂存区）</li>
<li>git commit &#8211; 提交更改（只有处于暂存区的文件会被提交），直接使用git commit命令会调用提交说明窗口。</li>
</ol>
<p><span id="more-1896"></span></p>
<h3>文件的三种状态</h3>
<p>处于git跟踪下的文件具有三种状态：</p>
<ul>
<li>已修改(modified) 已修改过的文件</li>
<li>已暂存(staged) 通过git add命令添加到暂存区域的文件</li>
<li>已提交(committed) 通过git commit命令提交过的文件</li>
</ul>
<div id="attachment_1932" class="wp-caption alignnone" style="width: 510px"><img class="size-full wp-image-1932" title="工作目录，暂存区域，以及本地仓库" src="http://omiga.org/img/git-notes-03.png" alt="工作目录，暂存区域，以及本地仓库" width="500" height="460" /><p class="wp-caption-text">工作目录，暂存区域，以及本地仓库</p></div>
<h3>查看帮助</h3>
<pre>$ git help &lt;verb&gt;
$ git &lt;verb&gt; --help
$ man git-&lt;verb&gt; # windows下不可用</pre>
<p>如查看init命令的帮助信息：</p>
<pre>$ git help init
$ git init --help</pre>
<h2>Git基本操作</h2>
<h3>创建Git版本库</h3>
<h4>初始化Git版本库</h4>
<p>git init命名将在当前目录新建一个版本库</p>
<h4>克隆Git版本库</h4>
<p>从你的git版本服务器上clone版本库到本地开展工作，或者从github上clone一个开源项目的代码库，这时候你就需要git clone命令：</p>
<pre># git clone url [newname]
# 克隆到当前目录
$ git clone https://github.com/octocat/Spoon-Knife.git
# 在当前目录新建目录knife 将Spoon-Knife克隆到knife目录
$ git clone https://github.com/octocat/Spoon-Knife.git knife</pre>
<p>不管是git init还是git clone都会在你的本地创建一个包含.git目录的git版本库</p>
<h3>提交更新</h3>
<p>通过git init命名或git clone命令都可以在本地创建一个git版本库，版本库创建成功后便可以在本地进行暂存文件，提交更新等操作了。</p>
<p>在git中可以使用git status查看文件的更改信息，但这个信息比较概要。如果想获取更为详细的更改信息，可以使用git diff命令：</p>
<pre># 查看未暂存文件的变化（与最近一次的暂存/提交比较）
$ git diff
# 查看已暂存文件的变化（与最近一次提交比较）
$ git diff --cached
# 查看与版本库中任一版本的变化
$ git diff 2bd094a
# 查看任意两个版本间的变化
$ git diff 2bd094a 78ab3d1
# 具体到某个文件
$ git diff 2bd094a 78ab3d1 README</pre>
<p>关于diff再补充一点内容：如果暂存区/已暂存区都不存在任何未提交的文件，那么diff将对最新版本中与上一版本进行比较。</p>
<p>清楚文件更改信息之后，便可使用git commit对暂存区文件进行提交操作。</p>
<p>如果想提交未暂存文件，可以使用git commit -a命令：</p>
<pre>$ git commit -a -m 'all changes'</pre>
<h3>删除文件</h3>
<h4>删除Git版本库中的某个文件</h4>
<p>可以使用git rm &lt;file&gt;：</p>
<pre>$ git rm myfile</pre>
<p>当然其实你也可以直接在文件目录中手动删除，这两者的区别在于：使用git rm命令相当于手动删除后使用add命令将更改添加到暂存区域。</p>
<h4>删除暂存区的某个文件</h4>
<pre>$ git reset HEAD &lt;file&gt;</pre>
<h3 id="git-reset">回退版本</h3>
<p>如果想撤销某（几）次提交，回退到某个版本，可以使用git reset [--mode] &lt;commit&gt;：</p>
<pre>$ git reset [--(mixed|soft|hard)] cec8506</pre>
<ul>
<li>&#8211;mixed 默认模式，回退到某次提交后的未暂存状态</li>
<li>&#8211;soft 回退到某次提交后的暂存状态</li>
<li>&#8211;hard 回退到某次提交完整状态，舍弃提交后的所有修改</li>
</ul>
<h4>文件重命名</h4>
<p>git不会跟踪在文件目录中手动的文件重命名操作，如果手动重命名了某个文件，git会认为这是一次delete-create操作。但是，你可以使用git mv命令完成重命名（文件目录亦使用该命令）：</p>
<pre>$ git mv oldfile newfile</pre>
<h3>查看提交历史</h3>
<p>这是git中使用平率非常高的一个操作，git中查看提交历史的功能也非常强大，提供各种筛选和输出格式定制功能。</p>
<p>最简单的，运行git log命令，你将看到一个详细的提交日志：</p>
<div id="attachment_1962" class="wp-caption alignnone" style="width: 435px"><img class="size-full wp-image-1962" title="git-log" src="http://omiga.org/img/git-log.jpg" alt="git-log" width="425" height="93" /><p class="wp-caption-text">git-log</p></div>
<pre># 当然也可以只查看某个版本
$ git log fd0a1b2</pre>
<p>信息内容都很好理解，重点说说第一行commit后这个40个字符的字符串，这是该次提交的对应的SHA-1值，在git中，会对提交（commit）、文件（blob）、目录（tree）、标签（tag）生成一个唯一的SHA-1值，git就是基于此来得知文件或目录的改动，因为这四类对象计算得到的SHA-1值都是唯一的，同时你也可以直接使用SHA-1值来指代相应的对象。比如：</p>
<pre>$ git show bdd3996
# 查看某个版本下具体某个文件
$ git show bdd3996 README</pre>
<p>git log还有很多命令选项来定制历史记录</p>
<table>
<tbody>
<tr>
<th style="width: 120px;">选项</th>
<th>说明</th>
</tr>
<tr>
<td>-(n)</td>
<td>仅显示最近的 n 条提交</td>
</tr>
<tr>
<td>&#8211;since,&#8211;after</td>
<td>仅显示指定时间之后的提交</td>
</tr>
<tr>
<td>&#8211;until,&#8211;before</td>
<td>仅显示指定时间之前的提交</td>
</tr>
<tr>
<td>&#8211;author</td>
<td>仅显示指定作者相关的提交</td>
</tr>
<tr>
<td>&#8211;committer</td>
<td>仅显示指定提交者相关的提交</td>
</tr>
<tr>
<td>&#8211;reverse</td>
<td>按时间倒序显示</td>
</tr>
<tr>
<td>-p</td>
<td>按补丁格式显示每个更新之间的差异</td>
</tr>
<tr>
<td>&#8211;stat</td>
<td>显示每次更新的文件修改统计信息</td>
</tr>
<tr>
<td>&#8211;shortstat</td>
<td>只显示 &#8211;stat 中最后的行数修改添加移除统计</td>
</tr>
<tr>
<td>&#8211;name-only</td>
<td>仅在提交信息后显示已修改的文件清单</td>
</tr>
<tr>
<td>&#8211;name-status</td>
<td>显示新增、修改、删除的文件清单</td>
</tr>
<tr>
<td>&#8211;abbrev-commit</td>
<td>仅显示 SHA-1 的前几个字符，而非所有的 40 个字符</td>
</tr>
<tr>
<td>&#8211;relative-date</td>
<td>使用较短的相对时间显示（比如，“2 weeks ago”）</td>
</tr>
<tr>
<td>&#8211;graph</td>
<td>显示 ASCII 图形表示的分支合并历史</td>
</tr>
<tr>
<td>&#8211;pretty</td>
<td>使用其他格式显示历史提交信息。可用的选项包括 oneline，short，full，fuller 和 format（后跟指定格式）</td>
</tr>
</tbody>
</table>
<p>可以通过对上述选项进行组合定制出更为个性化的日志信息，比如：</p>
<pre>$ git log --committer 'god' --shortstat --pretty=oneline</pre>
<p>该命令将以单行模式显示由god提交的统计信息。</p>
<pre>$ git log -p -5</pre>
<p>显示最近5次提交的，并显示其差异</p>
<p>除此之外，git log &#8211;graph也很好玩。我git log &#8211;graph了一下git项目的日志，非常壮观。</p>
<div id="attachment_1983" class="wp-caption alignnone" style="width: 206px"><a href="http://omiga.org/img/git.png" target="_blank"><img class="size-medium wp-image-1983  " title="git graph log" src="http://omiga.org/img/git-196x300.png" alt="git graph log" width="196" height="300" /></a><p class="wp-caption-text">git graph log</p></div>
<h4>&#8211;pretty=format</h4>
<p>单独介绍下&#8211;pretty=format选项。使用format和占位符可以定制出更为个性化的显示格式。</p>
<table>
<tbody>
<tr>
<th style="width: 120px;">选项</th>
<th>说明</th>
</tr>
<tr>
<td>%H</td>
<td>提交对象（commit）的完整哈希字串</td>
</tr>
<tr>
<td>%h</td>
<td>提交对象的简短哈希字串</td>
</tr>
<tr>
<td>%T</td>
<td>树对象（tree）的完整哈希字串</td>
</tr>
<tr>
<td>%t</td>
<td>树对象的简短哈希字串</td>
</tr>
<tr>
<td>%P</td>
<td>父对象（parent）的完整哈希字串</td>
</tr>
<tr>
<td>%p</td>
<td>父对象的简短哈希字串</td>
</tr>
<tr>
<td>%an</td>
<td>作者（author）的名字</td>
</tr>
<tr>
<td>%ae</td>
<td>作者的电子邮件地址</td>
</tr>
<tr>
<td>%ad</td>
<td>作者修订日期（可以用 -date= 选项定制格式）</td>
</tr>
<tr>
<td>%ar</td>
<td>作者修订日期，按多久以前的方式显示</td>
</tr>
<tr>
<td>%cn</td>
<td>提交者(committer)的名字</td>
</tr>
<tr>
<td>%ce</td>
<td>提交者的电子邮件地址</td>
</tr>
<tr>
<td>%cd</td>
<td>提交日期</td>
</tr>
<tr>
<td>%cr</td>
<td>提交日期，按多久以前的方式显示</td>
</tr>
<tr>
<td>%s</td>
<td>提交说明</td>
</tr>
</tbody>
</table>
<pre>$ git log --pretty=format:'%h by %ce at %cd'</pre>
<p>该命令将以“简短SHA-1 by 提交者 at 提交时间”的格式显示日志</p>
<h3>图形化日志界面gitk</h3>
<p>gitk命名会启用图形化的日志界面</p>
<div id="attachment_1995" class="wp-caption alignnone" style="width: 486px"><a href="http://omiga.org/img/gitk.jpg" target="_blank"><img class="size-full wp-image-1995  " title="gitk" src="http://omiga.org/img/gitk.jpg" alt="gitk" width="476" height="335" /></a><p class="wp-caption-text">gitk</p></div>
<h3>撤销操作</h3>
<p>前面已经介绍过使用<a href="#git-reset">git reset</a>来撤销暂存区的文件，以及回退整个版本。但如果只想恢复某个文件，则需要使用checkout &#8212; &lt;file&gt;命名：</p>
<pre>$ git checkout -- README</pre>
<p>它只有在修改文件还没有暂存的情况下，使用最近的提交版本进行恢复。如果文件已经暂存，则需要先使用git reset HEAD &lt;file&gt;从暂存区删除文件，再使用该命令。</p>
<h4>修改最后一次提交</h4>
<p>git commit &#8211;amend命名允许你对最后一次提交信息重新编辑。相当于重新进行一次提交，覆盖掉上一次提交。</p>
<h3>远程版本库的使用</h3>
<p>尽管git在本地也可以方便地进行版本管理，但是多人协作，或者是多地操作时，总需要使用到远程仓库来进行版本维护。在前面创建版本库的内容中其实使用clone命名就已经是在与远程版本库进行交互了，clone远程库后便会自动创建一个名为origin的远程库，可以使用git remote -v命名查看远程库的详细信息。</p>
<pre>$ git remote -v</pre>
<p>而在实际工作中，我们可能需要频繁地与某一个或几个远程库交互，那么更好的办法是使用一个别名把远程库保存起来。git添加远程库的方法很简单：</p>
<pre># $ git remote add &lt;name&gt; &lt;remote-url&gt;
$ git remote add pro-git https://github.com/progit/progit.git</pre>
<p>这样便将https://github.com/progit/progit.git这个远程git版本库添加并命名为pro-git，后续你只需要使用pro-git便可以指代progit的远程库。</p>
<h4>push</h4>
<p>当你完成本地工作，并将改动提交到本地版本库后，你便可以使用push将本地提交推送到远程仓库了：</p>
<pre># $ git push &lt;remote-name&gt; &lt;branch-name&gt;
$ git push pro-git master</pre>
<p>默认会使用origin和master作为远程仓库和本地分支的名称。</p>
<p>当然你也可以将本地分支推送到远程仓库作为一个分支：</p>
<pre># $ git push &lt;remote-name&gt; &lt;local-branch&gt;:&lt;remote-branch&gt;
$ git push pro-git master:git-branch</pre>
<p>当&lt;local-branch&gt;为空时，会尝试删除远程分支：</p>
<pre>$ git push pro-git :git-branch</pre>
<p>上述命令会删除远程仓库中的”git-branch”分支</p>
<h4>fetch与pull</h4>
<p>fetch与pull命令都会将一个远程仓库抓取到本地，不同的是fetch仅仅是将远程仓库抓取到本地，以供进行后续操作；pull除了将远程仓库抓取到本地，还会试图与本地当前分支进行合并。</p>
<p>他们与clone不同的是，clone会copy一份版本仓库到本地，如果本地已存在版本仓库，则会被clone后的仓库替换。而fetch和pull都需要在已有本地仓库的条件下操作，不能作为创建本地仓库的方法，即是必须先git init或是git clone后才能使用fetch和pull。</p>
<h4>删除远程仓库</h4>
<pre>$ git remote -d &lt;remote-name&gt;</pre>
<p>准确一点说，这只是删除远程仓库在本地的别名，而不是真正删除远程服务器上的git仓库。</p>
<h4>重命名远程仓库</h4>
<pre>$ git remote rename oldname newname</pre>
<h2>Git别名</h2>
<p>虽然git中很多命名都简单易记，但每次都手动输入这些命令确实会浪费不少时间，而且也有那么些命令选项非常冗长，这时就可以使用别名来简化命令的输入了。</p>
<p>别名属于配置项内容，所以需要使用git config命令，如可以为“checkout -b”命令配置别名“cob”</p>
<pre>$ git config --global alias.cob 'checkout -b'</pre>
<p>为“commit -a -m”配置别名“cam”:</p>
<pre>$ git config --global alias.cam 'commit -a -m'</pre>
<p>为单行图像化显示log命令“log &#8211;pretty=oneline &#8211;graph”配置别名“lol”:</p>
<pre>$ git config --global alias.lol 'log --pretty=oneline --graph'</pre>
<p>至此，git基础篇结束。你已经可以使用git进行日常的代码管理维护，下一篇进阶篇将着重介绍分支，git配置，git原理以及github等内容。</p>
<hr />
<p><small>© omiga for <a href="http://omiga.org/blog">omiga</a>, 2011. |
<a href="http://omiga.org/blog/archives/1896">Permalink</a> |
<a href="http://omiga.org/blog/archives/1896#comments">2 comments</a> |
Add to
<a href="http://del.icio.us/post?url=http://omiga.org/blog/archives/1896&title=Git笔记-基础">del.icio.us</a>
<br/>
Post tags: <a href="http://omiga.org/blog/archives/tag/git" rel="tag">git</a>, <a href="http://omiga.org/blog/archives/tag/github" rel="tag">github</a>, <a href="http://omiga.org/blog/archives/tag/msysgit" rel="tag">msysgit</a>, <a href="http://omiga.org/blog/archives/tag/scm" rel="tag">SCM</a>, <a href="http://omiga.org/blog/archives/tag/svn" rel="tag">SVN</a>, <a href="http://omiga.org/blog/archives/tag/%e7%89%88%e6%9c%ac%e7%ae%a1%e7%90%86" rel="tag">版本管理</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://omiga.org/blog/archives/1896/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>查找数组中被删除的一个元素</title>
		<link>http://omiga.org/blog/archives/1863</link>
		<comments>http://omiga.org/blog/archives/1863#comments</comments>
		<pubDate>Wed, 13 Apr 2011 18:40:27 +0000</pubDate>
		<dc:creator>omiga</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[时间复杂度]]></category>
		<category><![CDATA[查找算法]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://omiga.org/blog/?p=1863</guid>
		<description><![CDATA[一个数组arr0，长度任意，删除其中某个元素后得到数组arr，求删除的元素 最容易想到的方法：顺序查找，两个循环 function findItem1(arr0,arr){ /* arr0:原始数组 arr: 随机去除某一个元素后的数组 */ if(!arr0&#124;&#124;arr0.length&#60;1&#124;&#124;arr0.length-arr.length!=1) return 'error'; if(arr0.length==1) return arr0[0]; for(var i=0,l=arr0.length;i&#60;l;i++){ for(var m=0,n=arr.length;m&#60;n&#38;&#38;arr0[i]!==arr[m];m++){ if(m==n-1) return arr0[i]; } } } 最容易想到的方法一般都是效率最低的方法，发了半天呆又想到了二分查找 function findItem2(arr0,arr){ /* arr0:原始数组 arr: 随机去除某一个元素后的数组 */ if(!arr0&#124;&#124;!arr&#124;&#124;arr0.length&#60;1&#124;&#124;arr0.length-arr.length!=1) return 'error'; if(arr0.length==1) return arr0[0]; function compare(ascArr1,ascArr2){ //ascArr1.length-ascArr2.length==1 var ci = Math.floor(ascArr1.length/2); if(ascArr1[ci]!==ascArr2[ci]){ if(ci==0&#124;&#124;ascArr1[ci-1]==ascArr2[ci-1]) return ascArr1[ci]; else return compare(ascArr1.slice(0,ci),ascArr2.slice(0,ci)); }else{ if(ci==ascArr2.length-1) [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>一个数组arr0，长度任意，删除其中某个元素后得到数组arr，求删除的元素</p></blockquote>
<p>最容易想到的方法：<strong>顺序查找</strong>，两个循环</p>
<pre>function findItem1(arr0,arr){
    /*
        arr0:原始数组
        arr: 随机去除某一个元素后的数组
    */
    if(!arr0||arr0.length&lt;1||arr0.length-arr.length!=1) return 'error';
    if(arr0.length==1) return arr0[0];
    for(var i=0,l=arr0.length;i&lt;l;i++){
        for(var m=0,n=arr.length;m&lt;n&amp;&amp;arr0[i]!==arr[m];m++){
            if(m==n-1) return arr0[i];
        }
    }
}</pre>
<p>最容易想到的方法一般都是效率最低的方法，发了半天呆又想到了<strong>二分查找</strong></p>
<pre>function findItem2(arr0,arr){
    /*
        arr0:原始数组
        arr: 随机去除某一个元素后的数组
    */
    if(!arr0||!arr||arr0.length&lt;1||arr0.length-arr.length!=1) return 'error';
    if(arr0.length==1) return arr0[0];
    function compare(ascArr1,ascArr2){ //ascArr1.length-ascArr2.length==1
        var ci = Math.floor(ascArr1.length/2);
        if(ascArr1[ci]!==ascArr2[ci]){
            if(ci==0||ascArr1[ci-1]==ascArr2[ci-1]) return ascArr1[ci];
            else return compare(ascArr1.slice(0,ci),ascArr2.slice(0,ci));
        }else{
            if(ci==ascArr2.length-1) return ascArr1[ci+1];
            else return compare(ascArr1.slice(ci+1),ascArr2.slice(ci+1));
        }
    }
    return compare(arr0,arr);
}</pre>
<p>暂时只想到这两种方法，应该还有更高效的方法，想到了再补充。<a href="/lab/find_array_item.html" target="_blank">查看本文demo</a></p>
<hr />
<p><small>© omiga for <a href="http://omiga.org/blog">omiga</a>, 2011. |
<a href="http://omiga.org/blog/archives/1863">Permalink</a> |
<a href="http://omiga.org/blog/archives/1863#comments">4 comments</a> |
Add to
<a href="http://del.icio.us/post?url=http://omiga.org/blog/archives/1863&title=查找数组中被删除的一个元素">del.icio.us</a>
<br/>
Post tags: <a href="http://omiga.org/blog/archives/tag/%e6%97%b6%e9%97%b4%e5%a4%8d%e6%9d%82%e5%ba%a6" rel="tag">时间复杂度</a>, <a href="http://omiga.org/blog/archives/tag/%e6%9f%a5%e6%89%be%e7%ae%97%e6%b3%95" rel="tag">查找算法</a>, <a href="http://omiga.org/blog/archives/tag/%e7%ae%97%e6%b3%95" rel="tag">算法</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://omiga.org/blog/archives/1863/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>VIM插入当前时间</title>
		<link>http://omiga.org/blog/archives/1828</link>
		<comments>http://omiga.org/blog/archives/1828#comments</comments>
		<pubDate>Wed, 30 Mar 2011 15:45:30 +0000</pubDate>
		<dc:creator>omiga</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[getftime]]></category>
		<category><![CDATA[localtime]]></category>
		<category><![CDATA[strftime]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://omiga.org/blog/?p=1828</guid>
		<description><![CDATA[VIM有一个可以用来获取时间的内置函数：strftime strftime({format} [, {time}]) *strftime()* The result is a String, which is a formatted date and time, as specified by the {format} string.  The given {time} is used, or the current time if no time is given.  The accepted {format} depends on your system, thus this is not portable! See the manual page of the [...]]]></description>
			<content:encoded><![CDATA[<p>VIM有一个可以用来获取时间的内置函数：<strong>strftime</strong></p>
<blockquote><p>strftime({format} [, {time}])				*strftime()*</p>
<p>The result is a String, which is a formatted date and time, as		specified by the {format} string.  The given {time} is used,		or the current time if no time is given.  The accepted		{format} depends on your system, thus this is not portable!		See the manual page of the C function strftime() for the		format.  The maximum length of the result is 80 characters.		See also |localtime()| and |getftime()|.</p>
<p>The language can be changed with the |:language| command.</p>
<p>Examples:</p>
<p>:echo strftime(“%c”)		   Sun Apr 27 11:49:23 1997</p>
<p>:echo strftime(“%Y %b %d %X”)	   1997 Apr 27 11:53:25</p>
<p>:echo strftime(“%y%m%d %T”)	   970427 11:53:55</p>
<p>:echo strftime(“%H:%M”)	   11:55</p>
<p>:echo strftime(“%c”, getftime(“file.c”))						   Show mod time of file.c</p>
<p>Not available on all systems.  To check use:</p>
<p>:if exists(“*strftime”)</p></blockquote>
<ul>
<li>{format}是必须的，用来指定时间的输出格式</li>
<li>{time}缺省为当前系统时间，严格来说strftime是一个格式化输出时间的函数</li>
</ul>
<p>然后根据习惯随便定义一个映射就OK了：</p>
<pre>imap &lt;silent&gt;&lt;leader&gt;t &lt;c-r&gt;=strftime('%c')&lt;cr&gt;</pre>
<p>另外，vim还有两个获取时间的内置函数：localtime()、getftime()</p>
<p><strong>localtime() </strong> 返回本地时间距1970-01-01 08:00:00的秒数；</p>
<p>可以使用strftime进行格式化输出，如：</p>
<pre>strftime('%c',localtime())</pre>
<p>当然，它的输出结果和strftime(&#8216;%c&#8217;)是相同的。</p>
<p><strong>getftime() </strong> 返回一个文件的最后修改时间，时间也是以距1970-01-01 08:00:00的秒数返回。</p>
<p>如：</p>
<pre>strftime('%c',getftime('index.html'))</pre>
<p>更多的<a title="VIM function-list" href="http://vimcdoc.sourceforge.net/doc/usr_41.html#function-list" target="_blank">VIM内置函数</a></p>
<p>&nbsp;</p>
<hr />
<p><small>© omiga for <a href="http://omiga.org/blog">omiga</a>, 2011. |
<a href="http://omiga.org/blog/archives/1828">Permalink</a> |
<a href="http://omiga.org/blog/archives/1828#comments">No comment</a> |
Add to
<a href="http://del.icio.us/post?url=http://omiga.org/blog/archives/1828&title=VIM插入当前时间">del.icio.us</a>
<br/>
Post tags: <a href="http://omiga.org/blog/archives/tag/getftime" rel="tag">getftime</a>, <a href="http://omiga.org/blog/archives/tag/localtime" rel="tag">localtime</a>, <a href="http://omiga.org/blog/archives/tag/strftime" rel="tag">strftime</a>, <a href="http://omiga.org/blog/archives/tag/vim" rel="tag">vim</a><br/>
</small></p>]]></content:encoded>
			<wfw:commentRss>http://omiga.org/blog/archives/1828/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

