﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-jasmine214--love-随笔分类-Git</title><link>http://www.blogjava.net/jasmine214--love/category/48930.html</link><description>只有当你的内心总是充满快乐、美好的愿望和宁静时，你才能拥有强壮的体魄和明朗、快乐或者宁静的面容。</description><language>zh-cn</language><lastBuildDate>Thu, 16 Jan 2014 23:13:11 GMT</lastBuildDate><pubDate>Thu, 16 Jan 2014 23:13:11 GMT</pubDate><ttl>60</ttl><item><title>Git服务器Gitosis安装设置-git权限管理</title><link>http://www.blogjava.net/jasmine214--love/archive/2014/01/15/408987.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Wed, 15 Jan 2014 09:48:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2014/01/15/408987.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/408987.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2014/01/15/408987.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/408987.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/408987.html</trackback:ping><description><![CDATA[<div><div>             <p><em id="AnchorContentToggle" title="点击收起目录" style="cursor:pointer;">目录[-]</em></p>             <div id="AnchorContent"><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_1">1. 准备环境，安装更新</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_2">2. 安装 openssh服务器</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_3">3. 安装 git服务器</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_4">4. 配置 git服务器</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_5">5. 安装python的setup tool</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_6">6. 获取并安装gitosis</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_7">7. 配置gitosis</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_8">8.创建个人公钥和私钥，另外一台pc机（git客户端）</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_9">9. 管理gitosis配置</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_10">10. 安装apache2&nbsp;</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_11">11. 安装gitweb</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_12">12. 配置 gitweb</a></li><li><a href="http://my.oschina.net/mercury5/blog/146171#OSC_h1_13">13. 配置apache2</a></li></div>     	  </div>            	  	  <div> <h1>1. 准备环境，安装更新</h1>  <div "="" id="highlighter_559291"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>sudo</code>&nbsp;<code>apt-get&nbsp;update&nbsp;</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>2</code></td><td><code>sudo</code>&nbsp;<code>apt-get&nbsp;upgrade</code></td></tr></tbody></table></div></div></div>   <h1>2. 安装 openssh服务器</h1>  <div "="" id="highlighter_411197"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>sudo</code> <code>apt-get </code><code>install</code> <code>openssh-server openssh-client</code></td></tr></tbody></table></div></div></div>   <h1>3. 安装 git服务器</h1>  <div "="" id="highlighter_430240"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>sudo</code> <code>apt-get </code><code>install</code> <code>git-core</code></td></tr></tbody></table></div></div></div>   <h1>4. 配置 git服务器</h1>  <ul><li><p>创建git服务器管理用户</p> <div "="" id="highlighter_941348"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>sudo</code> <code>useradd</code> <code>-m git</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>2</code></td><td><code>sudo</code> <code>passwd</code> <code>git</code></td></tr></tbody></table></div></div></div> </li></ul>  <blockquote>   <p>用户名和密码均为git</p>  </blockquote>  <ul><li><p>创建git仓库存储目录</p> <div "="" id="highlighter_83500"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>sudo</code> <code>mkdir</code> <code>/home/git/repositories</code></td></tr></tbody></table></div></div></div> </li><li><p>设置git仓库权限</p> <div "="" id="highlighter_490648"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>sudo</code> <code>chown</code> <code>git:git /home/git/repositories</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>2</code></td><td><code>sudo</code> <code>chmod</code> <code>755 /home/git/repositories</code></td></tr></tbody></table></div></div></div> </li><li><p>初始化全局设置</p> <div "="" id="highlighter_418475"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>git config --global user.name </code><code>"myname"</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>2</code></td><td><code>git config --global user.email </code><code>"myname@server"</code></td></tr></tbody></table></div></div></div> </li></ul>   <h1>5. 安装python的setup tool</h1>  <div "="" id="highlighter_340610"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>sudo</code> <code>apt-get </code><code>install</code> <code>python-setuptools</code></td></tr></tbody></table></div></div></div>   <h1>6. 获取并安装gitosis</h1>  <div "="" id="highlighter_482850"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>cd</code> <code>/tmp</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>2</code></td><td><code>git clone https://github.com/res0nat0r/gitosis.git</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>3</code></td><td><code>cd</code> <code>gitosis</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>4</code></td><td><code>sudo</code> <code>python setup.py </code><code>install</code></td></tr></tbody></table></div></div></div>   <h1>7. 配置gitosis</h1>  <div "="" id="highlighter_774903"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>cp</code> <code>~/.</code><code>ssh</code><code>/id_rsa.pub /tmp</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>2</code></td><td><code>sudo</code> <code>-H -u git gitosis-init &lt; /tmp/id_rsa.pub</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>3</code></td><td><code>sudo</code> <code>chmod</code> <code>755 /home/git/repositories/gitosis-admin.git/hooks/post-update</code></td></tr></tbody></table></div></div></div>   <h1>8.创建个人公钥和私钥，另外一台pc机（git客户端）</h1>  <ul><li><p>在默认用户的主目录路径下，运行以下命令，按照提示创建公钥和私钥</p> <div "="" id="highlighter_9232"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>ssh</code><code>-keygen -t rsa</code></td></tr></tbody></table></div></div></div> </li><li><p>默认情况下，公钥和私钥会保存在~/.ssh目录下，如下所示：</p> <div "="" id="highlighter_220576"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>id_rsa&nbsp; id_rsa.pub&nbsp; known_hosts</code></td></tr></tbody></table></div></div></div> </li></ul>   <h1>9. 管理gitosis配置</h1>  <ul><li><p>在git客户端</p> <div "="" id="highlighter_758743"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>cd</code> <code>~</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>2</code></td><td><code>git clone git@</code><code>hostname</code><code>:用户名/gitosis-admin.git</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>3</code></td><td><code>cd</code> <code>gitosis-admin/</code></td></tr></tbody></table></div></div></div> </li><li><p>各个用户按照前面提到的办法生成各自的ssh公钥文件后，服务器管理员把所有人的 ssh公钥文件都拿来，拷贝到keydir目录下。修改gitosis.conf文件，如下所示</p> <div "="" id="highlighter_256026"><div><div alt1"=""><table><tbody><tr><td><code>01</code></td><td><code>[gitosis]</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>02</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>03</code></td><td><code>[group gitosis-admin]</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>04</code></td><td><code>writable = gitosis-admin</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>05</code></td><td><code>members = a@server1</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>06</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>07</code></td><td><code>[group developers]</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>08</code></td><td><code>writable = helloworld</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>09</code></td><td><code>members = a@server1 b@server2</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>10</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>11</code></td><td><code>[group </code><code>test</code><code>] </code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>12</code></td><td><code>readonly</code> <code>= helloworld</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>13</code></td><td><code>members = c@server3</code></td></tr></tbody></table></div></div></div> </li><li><p>这个配置文件表达了如下含义：gitosis-admin组成员有a，该组对gitosis-admin仓库有读写权限；  developers组有a，b两个成员，该组对helloworld仓库有读写权限；  test组有c一个成员，对helloworld仓库有只读权限。  当然目前这些配置文件的修改只是在你的本地，你必须推送到gitserver上才能真正生效。 加入新文件、提交并push到git服务器：</p> <div "="" id="highlighter_817296"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>git add .</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>2</code></td><td><code>git commit -am </code><code>"add helloworld project and users"</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>3</code></td><td><code>git remote add origin </code><code>ssh</code><code>://git@</code><code>hostname</code><code>/helloworld.git</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>4</code></td><td><code>git push origin master</code></td></tr></tbody></table></div></div></div> </li></ul>   <h1>10. 安装apache2&nbsp;</h1>  <div "="" id="highlighter_359378"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>sudo</code> <code>apt-get </code><code>install</code> <code>apache2</code></td></tr></tbody></table></div></div></div>   <h1>11. 安装gitweb</h1>  <div "="" id="highlighter_692523"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>sudo</code> <code>apt-get </code><code>install</code> <code>gitweb</code></td></tr></tbody></table></div></div></div>   <h1>12. 配置 gitweb</h1>  <ul><li><p>默认没有 css 加载，把 gitweb 要用的静态文件连接到 DocumentRoot 下：</p> <div "="" id="highlighter_750698"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>cd</code> <code>/var/www/</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>2</code></td><td><code>sudo</code> <code>ln</code> <code>-s /usr/share/gitweb/* .</code></td></tr></tbody></table></div></div></div> </li><li><p>修改配置：</p> <div "="" id="highlighter_566822"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>sudo</code> <code>vi</code> <code>/etc/gitweb.conf</code></td></tr></tbody></table></div></div></div> </li></ul>  <blockquote>   <p>将 $projectroot 改为git仓库存储目录(例如：/home/git/repositories)，保存后刷新浏览器。 <br />如果没有找到项目，你需要将$projectroot/*.git 的属性改为755，让apache用户有可读权限。可以只改你需要让别人通过web访问的那个git。 http://localhost/cgi-bin/gitweb.cgi</p>  </blockquote>  <ul><li><p>修改/etc/gitweb.conf 内容：</p> <div "="" id="highlighter_117310"><div><div alt1"=""><table><tbody><tr><td><code>01</code></td><td><code># path to git projects (&lt;project&gt;.git)</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>02</code></td><td><code>#$projectroot = "/var/cache/git";</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>03</code></td><td><code>$projectroot = </code><code>"/home/git/repositories"</code><code>;</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>04</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>05</code></td><td><code># directory to use for temp files</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>06</code></td><td><code>$git_temp = </code><code>"/tmp"</code><code>;</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>07</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>08</code></td><td><code># target of the home link on top of all pages</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>09</code></td><td><code>$home_link = $my_uri || </code><code>"/"</code><code>;</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>10</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>11</code></td><td><code># html text to include at home page</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>12</code></td><td><code>$home_text = </code><code>"indextext.html"</code><code>;</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>13</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>14</code></td><td><code># file with project list; by default, simply scan the projectroot dir.</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>15</code></td><td><code>$projects_list = $projectroot;</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>16</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>17</code></td><td><code># stylesheet to use</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>18</code></td><td><code>@stylesheets = (</code><code>"/gitweb/static/gitweb.css"</code><code>);</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>19</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>20</code></td><td><code># javascript code for gitweb</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>21</code></td><td><code>$javascript = </code><code>"/gitweb/static/gitweb.js"</code><code>;</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>22</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>23</code></td><td><code># logo to use</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>24</code></td><td><code>$logo = </code><code>"/gitweb/static/git-logo.png"</code><code>;</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>25</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>26</code></td><td><code># the 'favicon'</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>27</code></td><td><code>$favicon = </code><code>"/gitweb/static/git-favicon.png"</code><code>;</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>28</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>29</code></td><td><code># git-diff-tree(1) options to use for generated patches</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>30</code></td><td><code>#@diff_opts = ("-M");</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>31</code></td><td><code>@diff_opts = ();</code></td></tr></tbody></table></div></div></div> </li></ul>   <h1>13. 配置apache2</h1>  <p>ubuntu中默认的web目录是/var/www，默认的cgi目录是 /usr/lib/cgi-bin/,安装完成gitweb后，gitweb的gitweb.cgi会自动放置到该目录下。</p>  <p>如果你的cgi路径不是默认的/usr/lib/cgi-bin/，需要将gitweb安装在/usr/lib/cgi-bin中的 gitweb.cgi复制到原来配置的cgi-bin路径，并在apache的配置文件/etc/apache2/apache.conf末尾加上以下内 容：</p>  <div "="" id="highlighter_617844"><div><div alt1"=""><table><tbody><tr><td><code>01</code></td><td><code>SetEnv&nbsp; GITWEB_CONFIG&nbsp;&nbsp; /etc/gitweb.conf </code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>02</code></td><td><code>&lt;Directory </code><code>"/srv/www/cgi-bin/gitweb"</code><code>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>03</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>Options FollowSymlinks ExecCGI&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>04</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>Allow from all&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>05</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>AllowOverride all&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>06</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>Order allow,deny&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>07</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;Files gitweb.cgi&gt; </code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>08</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>SetHandler cgi-script </code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>09</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>&lt;/Files&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>10</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>RewriteEngine on </code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>11</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>RewriteCond %{REQUEST_FILENAME} !-f </code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>12</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>RewriteCond %{REQUEST_FILENAME} !-d </code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>13</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>RewriteRule ^.* /gitweb.cgi/$0 [L,PT] </code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>14</code></td><td><code>&lt;/Directory&gt;</code></td></tr></tbody></table></div></div></div>  <p>重新启动apache：sudo /etc/init.d/apache2 restart，访问http://localhost/cgi-bin/gitweb.cgi</p><p>转自：<div>http://my.oschina.net/mercury5/blog/146171</div><br /></p></div></div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/408987.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2014-01-15 17:48 <a href="http://www.blogjava.net/jasmine214--love/archive/2014/01/15/408987.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Git使用基础篇 </title><link>http://www.blogjava.net/jasmine214--love/archive/2013/12/05/407236.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Thu, 05 Dec 2013 02:20:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2013/12/05/407236.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/407236.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2013/12/05/407236.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/407236.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/407236.html</trackback:ping><description><![CDATA[<div>Git 是一个分布式的版本控制工具，本篇文章从介绍Git开始，重点在于介绍Git的基本命令和使用技巧，让你尝试使用Git的同时，体验到原来一个版  本控制工具可以对开发产生如此之多的影响，文章分为两部分，第一部分介绍Git的一些常用命令，其中穿插介绍Git的基本概念和原理，第二篇重点介绍  Git的使用技巧，最后会在Git Hub上创建一个开源项目开启你的Git实战之旅 <h1>1、Git是什么</h1> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Git 在Wikipedia上的定义：它是一个免费的、分布式的版本控制工具，或是一个强调了速度快的源代码管理工具。Git最初被Linus  Torvalds开发出来用于管理Linux内核的开发。每一个Git的工作目录都是一个完全独立的代码库，并拥有完整的历史记录和版本追踪能力，不依赖  于网络和中心服务器。</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Git 的出现减轻了许多开发者和开源项目对于管理分支代码的压力，由于对分支的良好控制，更鼓励开发者对自己感兴趣的项目做出贡献。其实许多开源项目  包括Linux kernel, Samba, X.org Server, Ruby on  Rails，都已经过渡到使用Git作为自己的版本控制工具。对于我们这些喜欢写代码的开发者嘛，有两点最大的好处，我们可以在任何地点(在上班的地铁  上)提交自己的代码和查看代码版本;我们可以开许许多多个分支来实践我们的想法，而合并这些分支的开销几乎可以忽略不计。</p> <h1>2、Git 1+1</h1> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;现在进入本篇文章真正的主题，介绍一下Git的基本命令和操作，会从Git的版本库的初始化，基本操作和独有的常用命令三部分着手，让大家能够开始使用Git。</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Git通常有两种方式来进行初始化:</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;git  clone: 这是较为简单的一种初始化方式，当你已经有一个远程的Git版本库，只需要在本地克隆一份，例如'git clone  git://github.com/someone/some_project.git  some_project'命令就是将'git://github.com/someone/some_project.git'这个URL地址的远程版  本库完全克隆到本地some_project目录下面</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;git  init和git remote：这种方式稍微复杂一些，当你本地创建了一个工作目录，你可以进入这个目录，使用'git  init'命令进行初始化，Git以后就会对该目录下的文件进行版本控制，这时候如果你需要将它放到远程服务器上，可以在远程服务器上创建一个目录，并把  可访问的URL记录下来，此时你就可以利用'git remote add'命令来增加一个远程服务器端，例如'git remote add  origin git://github.com/someone/another_project.git'这条命令就会增加URL地址为'git:  //github.com/someone/another_project.git'，名称为origin的远程服务器，以后提交代码的时候只需要使用  origin别名即可</p> <h1><span style="text-align:left;line-height:28px;background-color:#f8f8f8;font-family:Arial,Helvetica,sans-serif;color:#333333;">3、Git的基本命令</span>&nbsp;&nbsp;&nbsp;&nbsp;</h1> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp; &nbsp; &nbsp;现在我们有了本地和远程的版本库，让我们来试着用用Git的基本命令吧：</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;font-size:14px;padding-top:0px;"><span style="color:#333333;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><strong><span style="color:#3333ff;">git pull：</span></strong><span style="color:#333333;">从其他的版本库(既可以是远程的也可以是本地的)将代码更新到本地，例如：'git pull origin master'就是将origin这个版本库的代码更新到本地的master主枝，该功能类似于SVN的update</span></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;font-size:14px;padding-top:0px;"><span style="background-color:#f8f8f8;color:#333333;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="background-color:#ffffff;"><strong><span style="color:#3333ff;">git add</span><span style="color:#333333;">：</span></strong></span><span style="background-color:#f8f8f8;color:#333333;">是将当前更改或者新增的文件加入到Git的索引中，加入到Git的索引中就表示记入了版本历史中，这也是提交之前所需要执行的一步，例如'git add app/model/user.rb'就会增加app/model/user.rb文件到Git的索引中</span></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;font-size:14px;padding-top:0px;"><span style="color:#333333;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:#3333ff;"><strong>git rm：</strong></span><span style="color:#333333;">从当前的工作空间中和索引中删除文件，例如'git rm app/model/user.rb'</span></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;font-size:14px;padding-top:0px;"><span style="color:#333333;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:#3333ff;"><strong>git commit：</strong></span><span style="color:#333333;">提交当前工作空间的修改内容，类似于SVN的commit命令，例如'git commit -m "story #3, add user model"'，提交的时候必须用-m来输入一条提交信息</span></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;font-size:14px;padding-top:0px;"><span style="color:#333333;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:#3333ff;"><strong>git push：</strong></span><span style="color:#333333;">将本地commit的代码更新到远程版本库中，例如'git push origin'就会将本地的代码更新到名为orgin的远程版本库中</span></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;font-size:14px;padding-top:0px;"><span style="color:#333333;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><strong><span style="color:#3333ff;">git log：</span></strong><span style="color:#333333;">查看历史日志</span></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;font-size:14px;padding-top:0px;"><span style="color:#333333;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color:#3333ff;"><strong>git revert：</strong></span><span style="color:#333333;">还原一个版本的修改，必须提供一个具体的Git版本号，例如'git revert bbaf6fb5060b4875b18ff9ff637ce118256d6f20'，Git的版本号都是生成的一个哈希值、</span></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上面的命令几乎都是每个版本控制工具所公有的，下面就开始尝试一下Git独有的一些命令：</p> <h1><span style="text-align:left;line-height:28px;background-color:#f8f8f8;font-family:Arial,Helvetica,sans-serif;color:#333333;">4、Git独有的一些命令</span></h1> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp; &nbsp; &nbsp; <strong>&nbsp;git branch</strong>： 对分支的增、删、查等操作，例如'git branch new_branch'会从当前的工作版本创建一个叫做new_branch的新分支，'git  branch -D new_branch'就会强制删除叫做new_branch的分支，'git branch'就会列出本地所有的分支</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>git checkout</strong>：Git 的checkout有两个作用，其一是在不同的branch之间进行切换，例如 'git checkout  new_branch'就会切换到new_branch的分支上去;另一个功能是还原代码的作用，例如'git checkout  app/model/user.rb'就会将user.rb文件从上一个已提交的版本中更新回来，未提交的内容全部会回滚</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>git rebase</strong>：用下面两幅图解释会比较清楚一些，rebase命令执行后，实际上是将分支点从C移到了G，这样分支也就具有了从C到G的功能&nbsp;</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<img alt="Git使用基础篇 " src="http://static.open-open.com/lib/uploadImg/20120328/20120328111440_202.png" height="170" width="500" /></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>git reset</strong>： 将当前的工作目录完全回滚到指定的版本号，假设如下图，我们有A-G五次提交的版本，其中C 的版本号是  bbaf6fb5060b4875b18ff9ff637ce118256d6f20，我们执行了'git reset  bbaf6fb5060b4875b18ff9ff637ce118256d6f20'那么结果就只剩下了A-C三个提交的版本</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<img alt="Git使用基础篇 " src="http://static.open-open.com/lib/uploadImg/20120328/20120328111443_111.png" height="159" width="500" /></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>git stash</strong>：将当前未提交的工作存入Git工作栈中，时机成熟的时候再应用回来，这里暂时提一下这个命令的用法，后面在技巧篇会重点讲解</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>git config</strong>： 利用这个命令可以新增、更改Git的各种设置，例如'git config branch.master.remote  origin'就将master的远程版本库设置为别名叫做origin版本库，后面在技巧篇会利用这个命令个性化设置你的Git，为你打造独一无二的  Git</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong>git tag</strong>： 可以将某个具体的版本打上一个标签，这样你就不需要记忆复杂的版本号哈希值了，例如你可以使用 'git tag revert_version  bbaf6fb5060b4875b18ff9ff637ce118256d6f20'来标记这个被你还原的版本，那么以后你想查看该版本时，就可以使用  revert_version标签名，而不是哈希值了</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Git之所以能够提供方便的本地分支等特性，是与它的文件存储机制有关的。Git存储版本控制信息时使用它自己定义的一套文件系统存储机制，在代码根目录下有一个.git文件夹，会有如下这样的目录结构：</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p> <center style="padding-bottom:0px;line-height:18px;background-color:#f8f8f8;margin:0px;padding-left:0px;padding-right:0px;font-family:Arial,Helvetica,sans-serif;color:#333333;font-size:12px;padding-top:0px;"><img alt="Git使用基础篇 " src="http://static.open-open.com/lib/uploadImg/20120328/20120328111443_875.png" height="79" width="634" /> <br /> </center> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;有 几个比较重要的文件和目录需要解释一下：HEAD文件存放根节点的信息，其实目录结构就表示一个树型结构，Git采用这种树形结构来存储版本信息，  那么HEAD就表示根;refs目录存储了你在当前版本控制目录下的各种不同引用(引用指的是你本地和远程所用到的各个树分支的信息)，它有heads、  remotes、stash、tags四个子目录，分别存储对不同的根、远程版本库、Git栈和标签的四种引用，你可以通过命令'git  show-ref'更清晰地查看引用信息;logs目录根据不同的引用存储了日志信息。因此，Git只需要代码根目录下的这一个.git目录就可以记录完  整的版本控制信息，而不是像SVN那样根目录和子目录下都有.svn目录。那么下面就来看一下Git与SVN的区别吧</p> <h1>5、Git与SVN的不同</h1> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SVN(Subversion)是当前使用最多的版本控制工具。与它相比较，Git最大的优势在于两点：易于本地增加分支和分布式的特性。</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面两幅图可以形象的展示Git与SVN的不同之处</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img alt="Git使用基础篇 " src="http://static.open-open.com/lib/uploadImg/20120328/20120328111443_802.png" height="195" width="400" /></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<img alt="Git使用基础篇 " src="http://static.open-open.com/lib/uploadImg/20120328/20120328111444_659.png" height="195" width="400" /></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对 于易于本地增加分支，图中Git本地和服务器端结构都很灵活，所有版本都存储在一个目录中，你只需要进行分支的切换即可达到在某个分支工作的效果。  而SVN则完全不同，如果你需要在本地试验一些自己的代码，只能本地维护多个不同的拷贝，每个拷贝对应一个SVN服务器地址。举一个实际的例子，以前我所   在的小组使用SVN作为版本控制工具，当我正在试图增强一个模块，工作做到一半，由于会改变原模块的行为导致代码服务器上许多测试的失败，所以并没有提交  代码。这时候上级对我说，现在有一个很紧急的Bug需要处理，  必须在两个小时内完成。我只好将本地的所有修改diff，并输出成为一个patch文件，然后回滚有关当前任务的所有代码，再开始修改Bug的任务，等到  修改好后，在将patch应用回来。前前后后要完成多个繁琐的步骤，这还不计中间代码发生冲突所要进行的工作量。可是如果使用Git，  我们只需要开一个分支或者转回到主分支上，就可以随时开始Bug修改的任务，完成之后，只要切换到原来的分支就可以优雅的继续以前的任务。只要你愿意，每  一个新的任务都可以开一个分支，完成后，再将它合并到主分支上，轻松而优雅。</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;分 布式对于Git而言，你可以本地提交代码，所以在上面的图中，Git有利于将一个大任务分解，进行本地的多次提交，而SVN只能在本地进行大量的一  次性更改，导致将来合并到主干上造成巨大的风险。Git的代码日志是在本地的，可以随时查看。SVN的日志在服务器上的，每次查看日志需要先从服务器上下   载下来。我工作的小组，代码服务器在美国，每次查看小组几年前所做的工作时，日志下载就需要十分钟，这不能不说是一个痛苦。后来我们迁移到Git上，利用   Git日志在本地的特性，我用Ruby编写了一个Rake脚本，可以查看某个具体任务的所有代码历史，每次只需要几秒钟，大大方便我的工作。当然分布式并  不是说用了Git就不需要一个代码中心服务器，如果你工作在一个团队里，还是需要一个服务器来保存所有的代码的。</p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;<strong>&nbsp;&nbsp;&nbsp;&nbsp;总结</strong></p> <p style="text-align:left;padding-bottom:0px;line-height:1.8em;background-color:#f8f8f8;margin-top:0px;font-family:Arial,Helvetica,sans-serif;margin-bottom:10px;color:#333333;font-size:14px;padding-top:0px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;本篇介绍了Git的基本概念、一些常用命令和原理，大家可以尝试动手体会一下，下一篇会重点介绍Git命令的使用技巧，Git附带的工具，最后会在Git Hub上创建一个开源项目。</p></div><div>原文：http://www.open-open.com/lib/view/open1332904495999.html</div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/407236.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2013-12-05 10:20 <a href="http://www.blogjava.net/jasmine214--love/archive/2013/12/05/407236.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Git资料</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/09/15/358696.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Thu, 15 Sep 2011 06:27:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/09/15/358696.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/358696.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/09/15/358696.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/358696.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/358696.html</trackback:ping><description><![CDATA[<div><div>http://www.linuxsir.org/main/doc/git/gittutorcn.htm</div><br />http://phoenixtoday.blogbus.com/logs/33458940.html</div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/358696.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-09-15 14:27 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/09/15/358696.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Git与SVN的区别</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353098.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 27 Jun 2011 13:29:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353098.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/353098.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353098.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/353098.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/353098.html</trackback:ping><description><![CDATA[<div><a href="http://www.zzbaike.com/wiki/SVN" title="SVN">SVN</a>是当前使用最多的版本控制工具。与它相比较，Git最大的优势在于两点：<strong>易于本地增加分支和分布式的特性</strong>。 <p>下面两幅图可以形象的展示Git与SVN的不同之处 </p> <div><a href="http://www.zzbaike.com/wiki/Image:Git1.png" title="Git1.png"><img alt="" src="http://www.zzbaike.com/wiki/images/thumb/5/5e/Git1.png/700px-Git1.png" width="700" border="0" height="342" /></a></div> <div><a href="http://www.zzbaike.com/wiki/Image:Git2.png" title="Git2.png"><img alt="" src="http://www.zzbaike.com/wiki/images/thumb/c/c4/Git2.png/700px-Git2.png" width="700" border="0" height="342" /></a></div>  <p>对于易于本地增加分支，图中Git本地和服务器端结构都很灵活，所有版本都存储在一个目录中，你只需要进行分支的切换即可达到在某个分支工作的效 果。而SVN则完全不同，如果你需要在本地试验一些自己的代码，只能本地维护多个不同的拷贝，每个拷贝对应一个SVN服务器地址。举一个实际的例子，以前 我所在的小组使用SVN作为版本控制工具，当我正在试图增强一个模块，工作做到一半，由于会改变原模块的行为导致代码服务器上许多测试的失败，所以并没有 提交代码。这时候上级对我说，现在有一个很紧急的Bug需要处理，  必须在两个小时内完成。我只好将本地的所有修改diff，并输出成为一个patch文件，然后回滚有关当前任务的所有代码，再开始修改<a href="http://www.zzbaike.com/wiki/Bug" title="Bug">Bug</a>的 任务，等到修改好后，在将patch应用回来。前前后后要完成多个繁琐的步骤，这还不计中间代码发生冲突所要进行的工作量。可是如果使用Git，  我们只需要开一个分支或者转回到主分支上，就可以随时开始Bug修改的任务，完成之后，只要切换到原来的分支就可以优雅的继续以前的任务。只要你愿意，每 一个新的任务都可以开一个分支，完成后，再将它合并到主分支上，轻松而优雅。 </p><p>分布式对于Git而言，你可以本地提交代码，所以在上面的图中，Git有利于将一个大任务分解，进行本地的多次提交，而SVN只能在本地进 行大量的一次性更改，导致将来合并到主干上造成巨大的风险。Git的代码日志是在本地的，可以随时查看。SVN的日志在服务器上的，每次查看日志需要先从 服务器上下载下来。我工作的小组，代码服务器在美国，每次查看小组几年前所做的工作时，日志下载就需要十分钟，这不能不说是一个痛苦。后来我们迁移到 Git上，利用Git日志在本地的特性，我用<a href="http://www.zzbaike.com/wiki/Ruby" title="Ruby">Ruby</a>编写了一个Rake脚本，可以查看某个具体任务的所有代码历史，每次只需要几秒钟，大大方便我的工作。当然分布式并不是说用了Git就不需要一个代码中心服务器，如果你工作在一个团队里，还是需要一个服务器来保存所有的代码的。 </p></div>原文；http://www.zzbaike.com/wiki/Git%E4%B8%8ESVN%E9%97%B4%E7%9A%84%E6%AF%94%E8%BE%83<div>http://www.zzbaike.com/wiki/Git%E4%B8%8ESVN%E9%97%B4%E7%9A%84%E6%AF%94%E8%BE%83</div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/353098.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-06-27 21:29 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353098.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Git 中文手册</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353095.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 27 Jun 2011 12:25:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353095.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/353095.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353095.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/353095.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/353095.html</trackback:ping><description><![CDATA[http://gitbook.liuhui998.com/index.html<br /><div>http://progit.org/book/zh/ch1-3.html<br /><div>http://roclinux.cn/?p=914</div></div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/353095.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-06-27 20:25 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353095.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>为什么GIT比其他好</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353094.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Mon, 27 Jun 2011 12:17:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353094.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/353094.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353094.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/353094.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/353094.html</trackback:ping><description><![CDATA[<div><table width="100%"><tbody><tr><td><h1>X</h1> 					</td><td align="right"> 						<div id="menu"> 							<span hg="">hg</span> 							<span bzr="">bzr</span> 							<span svn="">svn</span> 							<span perforce="">perforce</span> 						</div> 						<img style="float: right;" alt="where &quot;x&quot; is one of" src="http://zh-cn.whygitisbetterthanx.com/images/wherex.gif" /> 					</td></tr> 					</tbody></table> 	      	    <div> 					<div intro=""> 						最近我花费了大量时间为 Gitsters 辩护以对抗那些 fanboyism， bandwagonism 以及 koolaid-thirst 的指责。 						为此我建设了此网站来说明大家为什么要从 X 转换至 Git，以及为何你也应该这么做。点击任何一个原因展开以查看详情。 					</div> 					 					<div> 					  <a href="http://zh-cn.whygitisbetterthanx.com/#">全部展开</a> | 					  <a href="http://zh-cn.whygitisbetterthanx.com/#">全部折叠</a> 					</div> 	    </div>  	    <div section=""> 					<div> 						<span hg="">hg</span> 						<span bzr="">bzr</span> 						<span svn="">svn</span> 						<span perforce="">perforce</span> 					</div>  	        <h2>           <a name="cheap-local-branching" href="http://zh-cn.whygitisbetterthanx.com/#cheap-local-branching">便宜的本地分支</a> 	        </h2> 					<div> 						 						<div> 							使 Git 从几乎所有 SCM 中脱颖而出并出并且最吸引人的特色，恐怕非它的分支模型莫属。 							它完全不同于我在此用于比较的所有其他模型，那些模型所推荐的最佳分支方式仅仅是将库 (repository) 复制到一个新的目录而已。 						</div> 						 						<div> 							Git 不那么做。 Git 允许你拥有多个完全独立的本地分支，创建、合并和删除这些分支仅需要几秒钟的时间。 						</div> 						 						 						<div> 							这意味着你可以这样做： 							<ul><li>创建一个新分支尝试新的想法，提交几次，切换回原先的分支，应用一个 patch，然后再切换至刚才实验中的新分支，将其合并。 								</li><li>一个分支用来存放将要发布的版本，另一个测试分支专门合并开发中的工作，其他数个小分支存放日常开发工作。 								</li><li>为每一个开发中的新功能建立相应分支，这样便可以在这些分支中无缝切换，并在某个功能开发完毕合并进主分支后删除相应分支。 								</li><li>创建一个分支来做实验，若发现行不通则直接删掉该分支；放弃这个分支，别人甚至不知道它存在过（即使这期间你已经 push 了其他分支）。 								</li></ul> 						</div> 						 						<img src="http://zh-cn.whygitisbetterthanx.com/images/branches.png" alt="branches flowchart" /> 						 						<div> 							重要的是，当你向一个远程库 push 时，你<em>无需</em> push 所有分支。你可以只共享一个分支而不是全部。 这会推动大家尝试新想法而不用操心如何、何时合并或与他人共享。 						</div> 						 						<div> 							使用其他系统，你也<em>可以</em>找到一些方法来做同样的事，但会困难的多而且极易出错。 							Git 让这个过程异常简单，而且当大部分开发者学习 Git 时，他们同时改变了他们的工作方式。 						</div> 						 						 						  						<div> 							<img alt="jamis twitter" src="http://twictur.es/i/1022811017.gif" width="300" /> 							<img alt="trevorturk twitter" src="http://twictur.es/i/1022886570.gif" width="300" /> 							<img alt="thillerson twitter" src="http://twictur.es/i/1022842917.gif" width="300" /> 							<img alt="boblmartens twitter" src="http://twictur.es/i/1022818467.gif" width="300" /> 							<img alt="mathie twitter" src="http://twictur.es/i/1022816942.gif" width="300" /> 						</div> 					</div> 	    </div> 				 	    <div section=""> 					<div> 						<span svn="">svn</span> 						<span perforce="">perforce</span> 					</div> 	        <h2>           <a name="everything-is-local" href="http://zh-cn.whygitisbetterthanx.com/#everything-is-local">所有内容都在本地</a> 	        </h2> 					<div>	  						<div> 							虽然所有分布式 SCM 都有这特点，但根据我的经验 Git 做的更好。除了 'fetch'， 'pull' 和 'push'， 							你很少会用到其他需要跟你的硬盘以外的东西打交道的命令。 						</div>  						<div> 							这不仅使大部分操作比你已经习惯的要快的多，而且让你可以离线工作。 							这听起来不怎么样，不过我经常为自己需要离线完成那么多工作感到惊讶。 							当你在飞机或火车上还可以建立分支、合并、提交以及浏览项目历史时，你的工作生产力会非常高。 						</div> 						 						<div><img style="width: 500px;" src="http://zh-cn.whygitisbetterthanx.com/images/local-remote.png" alt="local repo to remote repo flowchart" /></div>  						<div> 							即使是使用 Mercurial，诸如 'incoming' 和 'outgoing' 的常用命令也需要与服务器连接， 							而 Git 让你可以在离线前从服务器上 'fetch' 所有数据，然后对原本在你本地分支中并不存在的数据进行比较、合并或查看历史纪录。 						</div> 												 						<div> 							这意味着可以很容易的在你的 Git 库中同时保存你自己和与你协同工作的其他人的多个分支，而不会弄混任何内容。 						</div> 						 					</div> 	    </div> 		 		  <div section=""> 					<div> 						<span bzr="">bzr</span> 						<span svn="">svn</span> 						<span perforce="">perforce</span> 					</div> 			 	        <h2>           <a name="git-is-fast" href="http://zh-cn.whygitisbetterthanx.com/#git-is-fast">Git 很快</a> 	        </h2> 	 					<div> 						<div> 							Git 很快。 包括大部分其他系统的忠实用户在内的人都这么评价 Git。 							Git 所有操作都在本地进行的特性使它比 SVN 和 Perforce 要快，因为后两者的普通操作都要进行网络连接。 							即使与其他允许本地操作的分布式 SCM 相比，Git 也要快得多。 						</div> 					 						<div> 							部分原因可能是因为 Git 是被创造用来供 Linux 内核开发使用的，而那意味着从一开始它就需要高效处理大型库。 							此外，Git 是用 C 语言编写的，这减少了运行期与高层语言进行协作的开销。Git 这么快的另一个原因是它的主要开发者把这当成设计目标。 						</div>  						<div> 							我使用 Git，Mercurial 和 Bazaar 这三个不同的 SCM 各存放一份 Django 的源代码，进行了一些测试，下面是一些测试结果。 							我也用 SVN 进行了一些测试，不过相应我，它要更慢 &#8212; 基本上是 Bazaar 的测试结果加上网络延迟... 						</div>              <table>   						<tbody><tr><td> 							<img src="http://chart.apis.google.com/chart?cht=bvs&amp;chs=100x125&amp;chd=t:2,5,60&amp;chds=0,60&amp;chxt=x&amp;chco=4d89f9&amp;chl=git%7Chg%7Cbzr&amp;chtt=Init" alt="init benchmarks" />  							<img src="http://chart.apis.google.com/chart?cht=bvs&amp;chs=100x125&amp;chd=t:85,3,23&amp;chds=0,100&amp;chxt=x&amp;chco=4d89f9&amp;chl=git%7Chg%7Cbzr&amp;chtt=Add" alt="add benchmarks" />  							<img src="http://chart.apis.google.com/chart?cht=bvs&amp;chs=100x125&amp;chd=t:45,194,1474&amp;chds=0,1474&amp;chxt=x&amp;chco=4d89f9&amp;chl=git%7Chg%7Cbzr&amp;chtt=Status" alt="status benchmarks" /> 						 							<img src="http://chart.apis.google.com/chart?cht=bvs&amp;chs=100x125&amp;chd=t:5,21,142&amp;chds=0,142&amp;chxt=x&amp;chco=4d89f9&amp;chl=git%7Chg%7Cbzr&amp;chtt=Diff" alt="diff benchmarks" /> 						</td><td rowspan="2"> 							<img src="http://chart.apis.google.com/chart?cht=bvg&amp;chs=190x275&amp;chd=t:1,123,390%7C11,946,820&amp;chds=0,1210&amp;chxt=x&amp;chco=4d89f9,c6d9fd&amp;chl=git%7Chg%7Cbzr&amp;chtt=Branching" alt="branching benchmarks" /> 						</td></tr>             <tr><td> 							<img src="http://chart.apis.google.com/chart?cht=bvs&amp;chs=100x125&amp;chd=t:5,120,189&amp;chds=0,230&amp;chxt=x&amp;chco=4d89f9&amp;chl=git%7Chg%7Cbzr&amp;chtt=Tag" alt="tag benchmarks" />  							<img src="http://chart.apis.google.com/chart?cht=bvs&amp;chs=100x125&amp;chd=t:7,26,90&amp;chds=0,90&amp;chxt=x&amp;chco=4d89f9&amp;chl=git%7Chg%7Cbzr&amp;chtt=Log" alt="log benchmarks" />  							<img src="http://chart.apis.google.com/chart?cht=bvs&amp;chs=100x125&amp;chd=t:124,125,230&amp;chds=0,230&amp;chxt=x&amp;chco=4d89f9&amp;chl=git%7Chg%7Cbzr&amp;chtt=Commit+%28Lg%29" alt="large commit benchmarks" />  							<img src="http://chart.apis.google.com/chart?cht=bvs&amp;chs=100x125&amp;chd=t:8,51,113&amp;chds=0,113&amp;chxt=x&amp;chco=4d89f9&amp;chl=git%7Chg%7Cbzr&amp;chtt=Commit+%28Sm%29" alt="small commit benchmarks" /> 						</td></tr> 						</tbody></table> 						 						<div> 							测试结果表明除了增加新文件以外，所有的操作都是 Git 最快。（此外在一些非常大的提交操作测试中，Hg 基本上与 Git 一样快，不过我测试的那种提交操作实在太大， 							你不大可能会遇到那种情况 &#8212; Git 处理普通提交比其他 SCM 要快得多） 						</div> 						 						<table> 							<tbody><tr> 								<th><br /></th> 								<th>Git</th> 								<th>Hg</th> 								<th>Bzr</th> 							</tr> 							<tr> 								<th>Init</th> 								<td>0.024s</td> 								<td>0.059s</td> 								<td>0.600s</td> 							</tr> 							<tr> 								<th>Add</th> 								<td>8.535s</td> 								<td>0.368s</td> 								<td>2.381s</td> 							</tr> 							<tr> 								<th>Status</th> 								<td>0.451s</td> 								<td>1.946s</td> 								<td>14.744s</td> 							</tr> 							<tr> 								<th>Diff</th> 								<td>0.543s</td> 								<td>2.189s</td> 								<td>14.248s</td> 							</tr> 							<tr> 								<th>Tag</th> 								<td>0.056s</td> 								<td>1.201s</td> 								<td>1.892s</td> 							</tr> 							<tr> 								<th>Log</th> 								<td>0.711s</td> 								<td>2.650s</td> 								<td>9.055s</td> 							</tr> 							<tr> 								<th>Commit (Large)</th> 								<td>12.480s</td> 								<td>12.500s</td> 								<td>23.002s</td> 							</tr> 							<tr> 								<th>Commit (Small)</th> 								<td>0.086s</td> 								<td>0.517s</td> 								<td>1.139s</td> 							</tr> 							<tr> 								<th>Branch (Cold)</th> 								<td>1.161s</td> 								<td>94.681s</td> 								<td>82.249s</td> 							</tr> 							<tr> 								<th>Branch (Hot)</th> 								<td>0.070s</td> 								<td>12.300s</td> 								<td>39.411s</td> 							</tr> 						</tbody></table> 					 						<div> 							Cold 和 Hot 是第一次和第二次对一个库进行分支操作的结果数字 &#8212; 第二次分支使用了硬盘缓存。 						</div>  						<div> 							需要注意的是虽然 'add' 操作 Git 要慢很多，但这是在大量文件 &#8212; 超过 2000 个 &#8212; 上进行的新增操作。 							对于大部分人的日常工作来说，任意一个系统上的新增操作只会花费几分之一秒。其他测试到的操作（可能除了大提交）都与日常使用到的相近。 						</div> 					 					 					<div> 						这些测试结果并不难重现。只要用不同系统复制一份 Django 工程就可以比较出来了。 						<ul><li><code>git clone git://github.com/brosner/django.git dj-git</code></li><li><code>hg clone http://hg.dpaste.com/django/trunk dj-hg</code></li><li><code>bzr branch lp:django dj-bzr</code></li><li><code>svn checkout http://code.djangoproject.com/svn/django/trunk dj-svn</code></li></ul> 					</div> 					 				</div> 					 					 	    </div> 	 		  <div section=""> 					<div> 						<span svn="">svn</span> 					</div> 			 	        <h2>           <a name="git-is-small" href="http://zh-cn.whygitisbetterthanx.com/#git-is-small">Git 很小巧</a> 	        </h2> 	 					<div> 						<div> 							Git 真的非常善于节省磁盘空间。你的 Git 目录一般只会比一个 SVN checkout 大一点点 &#8212; 有时更小（显然 .svn 目录中的许多内容可以去掉）。 						</div> 					 						<div> 							从 Django 工程 的同一个历史纪录点取出的不同部分的 clone，提供给我们这些数据。 						</div> 					 						<table> 							<tbody><tr> 								<th><br /></th> 								<th>Git</th> 								<th>Hg</th> 								<th>Bzr</th> 								<th>Bzr*</th> 								<th>SVN</th> 							</tr> 							<tr> 								<td>Repo Alone</td> 								<td>24M</td> 								<td>34M</td> 								<td>45M</td> 								<td>89M</td> 								<td><br /></td> 							</tr> 							<tr> 								<td>Entire Directory</td> 								<td>43M</td> 								<td>53M</td> 								<td>64M</td> 								<td>108M</td> 								<td>61M</td> 							</tr> 						</tbody></table> 						 						<div><small> 							* 第二个 Bar 数字是我执行 'bzr pack' 后得到的，我本以为该命令会让它体积变小，但结果反而让它变得大得多。 						</small></div> 						 					</div> 	    </div>  	    <div section=""> 					<div> 						<span hg="">hg</span> 						<span bzr="">bzr</span> 						<span svn="">svn</span> 						<span perforce="">perforce</span> 					</div> 		 	        <h2>           <a name="the-staging-area" href="http://zh-cn.whygitisbetterthanx.com/#the-staging-area">暂存区域</a> 	        </h2> 					<div> 						<div> 							不同于其他系统，Git 有它称之为暂存区域（"staging area"）或 "index" 的东西。 							这是一个用来在提交前对提交内容进行设置的临时区域。 						</div> 						<div> 							暂存区域最酷、也是让 Git 不同于其他工具的地方，是在你完成一部分文件的修改后，可以方便地 stage 并提交它们，同时又不用提交工作目录中其他已修改的文件或在提交命令中列出那些文件。 						</div> 						<div><img src="http://zh-cn.whygitisbetterthanx.com/images/index1.png" alt="add commit workflow diagram" /></div> 						 						<div> 						  你还可以只 stage 已修改的一个文件的一部分内容。再也不会发生这样的事情了：对同一个文件中逻辑上并不相关的两部分进行修改后才发现没有对它们进行分别提交。 						  现在你可以先 stage 当前提交要包括的修改，然后 stage 下次提交要包括的修改。这一特性适用于你需要对文件进行的任意范围的修改。 						</div>  						<div> 							当然，如果你不想控制这么多，你也可以很轻松的忽略这些特性 &#8212; 只需在提交命令上加上 '-a' ，就可以把所有修改过的文件加入到暂存区域中去了。 						</div> 						 						<div><img src="http://zh-cn.whygitisbetterthanx.com/images/index2.png" alt="commit only workflow diagram" /></div> 					</div> 	    </div>  	    <div section=""> 					<div> 						<span svn="">svn</span> 						<span perforce="">perforce</span> 					</div>  	        <h2>           <a name="distributed" href="http://zh-cn.whygitisbetterthanx.com/#distributed">分布式</a> 	        </h2>  					<div>  					  <div> 						包括 Git 在内的所有分布式 SCM 的最佳特性之一是分布式。这意味着你不是 "checkout" 源代码的最新版，而是 "clone" 整个代码库。             </div>             <div> 				这意味着即使使用中央集中式的工作流，每一个用户都拥有一份主服务器的备份，每一份都可以在主服务器当机或损坏时用来替换它。使用 Git 便不存在单点故障了，除非只有一个点。             </div>              <div> 				同时这不会使操作变得太慢。平均来说，SVN checkout 只比任何一种分布式 SCM 快一点。在我测试过的分布式 SCM 中，Git 是最快的。 					  </div>  						<table> 							<tbody><tr><td> 								<img src="http://chart.apis.google.com/chart?cht=bvs&amp;chs=200x150&amp;chd=t:120,144,311,64&amp;chds=0,320&amp;chco=4d89f9&amp;chl=git%7Chg%7Cbzr%7Csvn&amp;chtt=Clone" alt="cloning benchmarks" /> 							</td><td style="width: 80%;"> 								<table> 									<tbody><tr> 										<th>Git</th> 										<td>1m 59s</td> 									</tr> 									<tr> 										<th>Hg</th> 										<td>2m 24s</td> 									</tr> 									<tr> 										<th>Bzr</th> 										<td>5m 11s</td> 									</tr> 									<tr> 										<th>SVN</th> 										<td>1m 4s</td> 									</tr> 								</tbody></table> 							</td></tr> 						</tbody></table> 						 					</div> 	    </div> 	 	 	    <div section=""> 				<div> 					<span svn="">svn</span> 					<span perforce="">perforce</span> 				</div> 		        	<h2>         <a name="any-workflow" href="http://zh-cn.whygitisbetterthanx.com/#any-workflow">适用于任何工作流</a>        	</h2>  				<div> 					 					<div> 						Git 令人惊叹的特性之一是，由于其天生的分布式特征及强大的分支系统，可以轻而易举的应用任何想的到的工作流。 					</div> 					 					<h3>Subversion 式的工作流</h3> 					  					<div> 						集中式工作流是一种很常见的工作流，这对于那些从集中式系统迁移过来的人来说尤其如此。如果你上次 fetch 过后，已经有其他人进行了 push 操作，那么 Git 将不允许你直接 push； 						所以这种所有开发者向同一台服务器 push 的集中式模型可以工作的很好。 					</div> 					 					<div><img src="http://zh-cn.whygitisbetterthanx.com/images/workflow-a.png" alt="subversion-style workflow" /></div><br /> 					 					<h3>集成管理员工作流</h3>  					<div> 						另一种常见工作流是有一名集成管理员专门负责向 'blessed' 库提交，其他开发者复制该库，push 到他们自己独立的库，随后请求集成管理员 pull 他们的修改。 						这是开源工程或 GitHub 库中很常见的一种开发模式。 					</div>  					<div><img src="http://zh-cn.whygitisbetterthanx.com/images/workflow-b.png" alt="integration manager workflow" /></div><br />  					<h3>司令官与副官工作流</h3>  					<div> 						对于规模更庞大的项目，你可以让开发者使用类似 Linux 内核开发的工作流，每一个子系统都有专人（副官）负责合并与该子系统相关的修改。 						另有一名整合者（司令官）只从副官那里 pull ，然后 push 到 'blessed' 库，其他所有人则再从 'blessed' 库复制。 					</div>  					<div><img src="http://zh-cn.whygitisbetterthanx.com/images/workflow-c.png" alt="dictator and lieutenants workflow" /></div><br /> 					 					<div> 						再次强调，对于工作流 Git 非常有弹性，你可以混合及选用任何适合你的工作流。           </div> 					 				</div> 	    </div> 	 	 	    <div section=""> 				<div> 					<span hg="">hg</span> 					<span bzr="">bzr</span> 					<span svn="">svn</span> 					<span perforce="">perforce</span> 				</div>          <h2>         <a name="github" href="http://zh-cn.whygitisbetterthanx.com/#github">GitHub</a>         </h2> 				 				<div>            <img style="float: right; padding: 10px;" src="http://zh-cn.whygitisbetterthanx.com/images/octocat.png" alt="octocat" />  					<div> 						我本人在 <a href="http://github.com/">GitHub</a> 工作，所以这 <em>可能</em> 显得有点偏颇， 						不过我还是加入了这一部分，因为很多人说正是 GitHub 让他们选择了 Git 。 					</div>  					<div>	 						GitHub 是很多人使用 Git 的原因，相比简单的托管网站，它更象一个社交网络。 						人们找到与他们在做的事相关（似）的其他开发人员或项目，然后轻松地 fork 和贡献，这样形成了一个以 Git 和 各种项目为中心的活跃社区。	 					</div> 					 					<div>	 						也有其他许多针对 Git 和其他 SCM 的服务，但很少有用户导向或社交导向的，更没有哪个是基于用户群的。 						GitHub 的社交性是杀手级特性，上述特性使得 Git 和 GitHub 成为快速开发开源项目的最佳组合。 					</div>  					<div>	 						其他任何一种 SCM 都不提供这样的社区。           </div> 					 					<div> 						<img alt="puls twitter" src="http://twictur.es/i/1022858126.gif" width="300" /> 						<img alt="twitter" src="http://twictur.es/i/1022857633.gif" width="300" /> 					</div> 				</div> 	    </div> 	 	 			  	 			 	 	    <div section=""> 				<div> 					<span perforce="">perforce</span> 				</div> 				         <h2>         <a name="easy-to-learn" href="http://zh-cn.whygitisbetterthanx.com/#easy-to-learn">容易学习</a>         </h2>          				<div> 					<div> 						本来并非如此 &#8212; 早期的 Git 并不是真正意义上的 SCM，而更象一套让你可以用分布式的方式进行版本控制的工具。 						但是现在 Git 命令集和学习曲线已经和其他 SCM 类似，甚至比其中一些更好。 					</div>  					<div> 						不作针对性的研究很难证明这一点，在此我仅仅演示一下 Mercurial 和 Git 命令中的默认帮助菜单的区别。这两个系统中相同（或相近）的命令将被高亮显示。 						（在 Hg 中，如果你输入 'hg help'，你会得到一份 40 多个命令的清单。）	 					</div> 				 					<table> 						<tbody><tr><td valign="top"> 							 <h3>Mercurial Help</h3> <pre>add        add the specified files ...<br />annotate   show changeset informati...<br />clone      make a copy of an existi...<br />commit     commit the specified fil...<br />diff       diff repository (or sele...<br />export     dump the header and diff...<br />init       create a new repository ...<br />log        show revision history of...<br />merge      merge working directory ...<br />parents    show the parents of the ...<br />pull       pull changes from the sp...<br />push       push changes to the spec...<br />remove     remove the specified fil...<br />serve      export the repository vi...<br />status     show changed files in th...<br />update     update working directory<br /></pre>  					</td><td valign="top"> 						 <h3>Git Help</h3> <pre>add        Add file contents to the index<br />bisect     Find the change that introduce...<br />branch     List, create, or delete branches<br />checkout   Checkout a branch or paths to ...<br />clone      Clone a repository into a new ...<br />commit     Record changes to the repository<br />diff       Show changes between commits, ...<br />fetch      Download objects and refs from...<br />grep       Print lines matching a pattern<br />init       Create an empty git repository<br />log        Show commit logs<br />merge      Join two or more development h...<br />mv         Move or rename a file, a direc...<br />pull       Fetch from and merge with anot...<br />push       Update remote refs along with ...<br />rebase     Forward-port local commits to ...<br />reset      Reset current HEAD to the spec...<br />rm         Remove files from the working ...<br />show       Show various types of objects<br />status     Show the working tree status<br />tag        Create, list, delete or verify...<br /></pre>	 				</td></tr> 				</tbody></table> 				 				<div>	 					在 Git 1.6 之前，所有 Git 命令都存放在可执行路径下，这让使用者非常迷惑。  					现在虽然 Git 仍能识别所有这些命令，但存放在可执行路径下的只有 'git' 这一命令。 					如果你比较 Mercurial 和 Git 会发现，Git 的命令集与帮助系统与 Mercurial 几乎完全一样 &#8212; 从初学者的 UI 角度来说两者几乎没有区别。								 				</div> 				 				<div> 					现在已经很难说 Mercurial 或 Bazaar 比 Git 更易学了。 				</div> 				 				</div> 				 	    </div></div>原文：http://zh-cn.whygitisbetterthanx.com/<div>http://zh-cn.whygitisbetterthanx.com/</div><img src ="http://www.blogjava.net/jasmine214--love/aggbug/353094.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-06-27 20:17 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/06/27/353094.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Git历险记（四）——索引与提交的幕后故事</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/05/11/350012.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Wed, 11 May 2011 06:58:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/05/11/350012.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/350012.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/05/11/350012.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/350012.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/350012.html</trackback:ping><description><![CDATA[<h2>不一样的索引</h2>
<p>我想如果看过<a href="http://www.infoq.com/cn/git-adventures">《Git历险记》的前面三篇文章</a>的朋友可能已经知道怎么用<a href="http://www.kernel.org/pub/software/scm/git/docs/git-add.html">git add</a>，<a href="http://www.kernel.org/pub/software/scm/git/docs/git-commit.html">git commit</a>这两个命令了；知道它们一个是把文件暂存到索引中为下一次提交做准备，一个创建新的提交（commit）。但是它们台前幕后的一些有趣的细节大家不一定知晓，请允许我一一道来。</p>
<p>Git 索引是一个在你的工作目录（working tree）和项目仓库间的暂存区域(staging area)。有了它,
你可以把许多内容的修改一起提交(commit)。 如果你创建了一个提交(commit)，那么提交的一般是暂存区里的内容,
而不是工作目录中的内容。</p>
<p>一个Git项目中文件的状态大概分成下面的两大类，而第二大类又分为三小类：</p>
<ol>
    <li>未被跟踪的文件（untracked file）</li>
    <li>已被跟踪的文件（tracked file）
    <ol>
        <li>被修改但未被暂存的文件（changed but not updated或modified）</li>
        <li>已暂存可以被提交的文件（changes to be committed 或staged）</li>
        <li>自上次提交以来，未修改的文件(clean 或 unmodified)</li>
    </ol>
    </li>
</ol>
<p>看到上面的这么多的规则，大家早就头大了吧。老办法，我们建一个Git测试项目来试验一下：</p>
<p>我们先来建一个空的项目：</p>
<pre>$rm -rf stage_proj<br />
$mkdir stage_proj<br />
$cd stage_proj<br />
$git init<br />
Initialized empty Git repository in /home/test/work/test_stage_proj/.git/<br />
</pre>
<p>我们还创建一个内容是&#8220;hello, world&#8221;的文件：</p>
<pre>$echo "hello,world" &gt; readme.txt</pre>
<p>现在来看一下当前工作目录的状态，大家可以看到&#8220;readme.txt&#8221;处于未被跟踪的状态（untracked file）：</p>
<pre>$git status<br />
# On branch master<br />
#<br />
# Initial commit<br />
#<br />
# Untracked files:<br />
#&nbsp;&nbsp; (use "git add &lt;file&gt;..." to include in what will be committed)<br />
#<br />
#&nbsp;&nbsp; readme.txt<br />
nothing added to commit but untracked files present (use "git add" to track)<br />
</pre>
<p>把&#8220;readme.txt"加到暂存区： $git add readme.txt</p>
<p>现在再看一下当前工作目录的状态：</p>
<pre>$git status<br />
# On branch master<br />
#<br />
# Initial commit<br />
#<br />
# Changes to be committed:<br />
#&nbsp;&nbsp; (use "git rm --cached &lt;file&gt;..." to unstage)<br />
#<br />
#&nbsp;&nbsp; new file:&nbsp;&nbsp; readme.txt<br />
#<br />
</pre>
<p>可以看到现在"readme.txt"的状态变成了已暂存可以被提交（changes to be committed），这意味着我们下一步可以直接执行&#8220;git commit&#8220;把这个文件提交到本地的仓库里去了。</p>
<p>暂存区（staging
area）一般存放在&#8220;git目录&#8220;下的index文件（.git/index）中，所以我们把暂存区有时也叫作索引（index）。索引是一个二进制格
式的文件，里面存放了与当前暂存内容相关的信息，包括暂存的文件名、文件内容的SHA1哈希串值和文件访问权限，整个索引文件的内容以暂存的文件名进行排
序保存的。</p>
<p>但是我不想马上就把文件提交，我想看一下暂存区（staging area）里的内容，我们执行<a href="http://www.kernel.org/pub/software/scm/git/docs/git-ls-files.html">git ls-files</a>命令看一下：</p>
<pre>$git ls-files --stage<br />
100644 2d832d9044c698081e59c322d5a2a459da546469 0&nbsp;&nbsp; readme.txt<br />
</pre>
<p>我们如果有看过<a href="http://www.infoq.com/cn/news/2011/02/git-adventures-local-repository">上一篇文章</a>里
的"庖丁解牛",
你会发现&#8220;git目录&#8220;里多出了&#8221;.git/objects/2d/832d9044c698081e59c322d5a2a459da546469&#8221;这
么一个文件，再执行&#8220;git cat-file -p 2d832d&#8221;
的话，就可以看到里面的内容正是&#8220;hello,world"。Git在把一个文件添加暂存区时，不但把它在索引文件(.git/index)里挂了号，而
且把它的内容先保存到了&#8220;git目录&#8220;里面去了。</p>
<p>如果我们执行&#8221;git add&#8220;命令时不小心把不需要的文件也加入到暂存区中话，可以执行&#8220;git rm --cached filename" 来把误添加的文件从暂存区中移除。</p>
<p>现在我们先在"readme.txt"文件上做一些修改后：</p>
<pre>$echo "hello,world2" &gt;&gt; readme.txt</pre>
<p>再来看一下暂存区的变化:</p>
<pre>$git status<br />
# On branch master<br />
#<br />
# Initial commit<br />
#<br />
# Changes to be committed:<br />
#&nbsp;&nbsp; (use "git rm --cached &lt;file&gt;..." to unstage)<br />
#<br />
#&nbsp;&nbsp; new file:&nbsp;&nbsp; readme.txt<br />
#<br />
# Changed but not updated:<br />
#&nbsp;&nbsp; (use "git add &lt;file&gt;..." to update what will be committed)<br />
#&nbsp;&nbsp; (use "git checkout -- &lt;file&gt;..." to discard changes in working directory)<br />
#<br />
#&nbsp;&nbsp; modified:&nbsp;&nbsp; readme.txt<br />
#</pre>
<p>大家可以看到命令输出里多了一块内容：&#8220;changed but not updated ...... modified:
readme.txt&#8221;。大家可能会觉得很奇怪，我前面不是把"readme.txt"这个文件给添加到暂存区里去了吗，这里怎么又提示我未添加到暂存区
（changed but not updated）呢，是不是Git搞错了呀。</p>
<p>Git 没有错，每次执行&#8220;git
add&#8221;添加文件到暂存区时，它都会把文件内容进行SHA1哈希运算，在索引文件中新加一项，再把文件内容存放到本地的&#8220;git目录&#8220;里。如果在上次执行
&#8220;git add&#8221;之后再对文件的内容进行了修改，那么在执行&#8220;git
status&#8221;命令时，Git会对文件内容进行SHA1哈希运算就会发现文件又被修改了，这时&#8220;readme.txt&#8220;就同时呈现了两个状态：被修改但未
被暂存的文件（changed but not updated），已暂存可以被提交的文件（changes to be
committed）。如果我们这时提交的话，就是只会提交第一次&#8220;git add"所以暂存的文件内容。</p>
<p>我现在对于&#8220;hello,world2"的这个修改不是很满意，想要撤消这个修改，可以执行<a href="http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html">git checkout</a>这个命令：</p>
<pre>$git checkout -- readme.txt</pre>
<p>现在再来看一下仓库里工作目录的状态：</p>
<pre>$git status<br />
# On branch master<br />
#<br />
# Initial commit<br />
#<br />
# Changes to be committed:<br />
#&nbsp;&nbsp; (use "git rm --cached &lt;file&gt;..." to unstage)<br />
#<br />
#&nbsp;&nbsp; new file:&nbsp;&nbsp; readme.txt<br />
#</pre>
<p>好的，现在项目恢复到我想要的状态了，下面我就用<a href="http://www.kernel.org/pub/software/scm/git/docs/git-commit.html">git commit</a> 命令把这个修改提交了吧：</p>
<pre>$git commit -m "project init"<br />
[master (root-commit) 6cdae57] project init&nbsp;&nbsp; 1 files changed, 1 insertions(+), 0 deletions(-)&nbsp;&nbsp;&nbsp; create mode 100644 readme.txt<br />
</pre>
<p>现在我们再来看一下工作目录的状态：</p>
<pre>$git status<br />
# On branch master<br />
nothing to commit (working directory clean)</pre>
<p>大家可以看到&#8220;nothing to commit (working directory clean)&#8221;；如果一个工作树（working
tree）中所有的修改都已提交到了当前分支里（current head），那么就说它是干净的（clean），反之它就是脏的(dirty)。</p>
<h2>SHA1值内容寻址</h2>
<p>正如<a href="http://www.advogato.org/person/apenwarr/diary/371.html">Git is the next Unix</a>
一文中所说的一样，Git是一种全新的使用数据的方式（Git is a totally new way to operate on
data）。Git把它所管理的所有对象（blob，tree，commit，tag&#8230;&#8230;），全部根据它们的内容生成SHA1哈希串值作为对象名；根据目
前的数学知识，如果两块数据的SHA1哈希串值相等，那么我们就可以认为这两块数据是相同 的。这样会带来的几个好处：</p>
<ol>
    <li>Git只要比较对象名，就可以很快的判断两个对象的内容是否相同。</li>
    <li>因为在每个仓库（repository）的&#8220;对象名&#8221;的计算方法都完全一样，如果同样的内容存在两个不同的仓库中，就会存在相同的&#8220;对象名&#8221;。</li>
    <li>Git还可以通过检查对象内容的SHA1的哈希值和&#8220;对象名&#8221;是否匹配，来判断对象内容是否正确。</li>
</ol>
<p>我们通过下面的例子，来验证上面所说的是否属实。现在创建一个和&#8220;readme.txt&#8220;内容完全相同的文件&#8221;readme2.txt&#8220;，然后再把它提交到本地仓库中：</p>
<pre>$echo "hello,world" &gt; readme2.txt<br />
$git add readme2.txt<br />
$git commit -m "add new file: readme2.txt"<br />
[master 6200c2c] add new file: readme2.txt<br />
1 files changed, 1 insertions(+), 0 deletions(-)<br />
create mode 100644 readme2.txt<br />
</pre>
<p>下面的这条很复杂的命令是查看当前的提交（HEAD）所包含的blob对象：</p>
<pre>$git cat-file -p HEAD | head -n 1 | cut -b6-15 | xargs git cat-file -p<br />
100644 blob 2d832d9044c698081e59c322d5a2a459da546469&nbsp;&nbsp;&nbsp; readme.txt<br />
100644 blob 2d832d9044c698081e59c322d5a2a459da546469&nbsp;&nbsp;&nbsp; readme2.txt</pre>
<p>我们再来看看上一次提交（HEAD^）所包含的blob对象：</p>
<pre>$git cat-file -p HEAD^ | head -n 1 | cut -b6-15 | xargs git cat-file -p<br />
100644 blob 2d832d9044c698081e59c322d5a2a459da546469&nbsp;&nbsp;&nbsp; readme.txt</pre>
<p>很明显大家看到尽管当前的提交比前一次多了一个文件，但是它们之间却是在共用同一个blob对象：&#8220;2d832d9&#8221;。</p>
<h2>No delta, just snapshot</h2>
<p>Git 与大部分你熟悉的版本控制系统，如Subversion、CVS、Perforce 之间的差别是很大的。传统系统使用的是：
&#8220;增量文件系统&#8221; （Delta Storage
systems），它们存储是每次提交之间的差异。而Git正好与之相反，它是保存的是每次提交的完整内容（snapshot）；它会在提交前根据要提交
的内容求SHA1哈希串值作为对象名，看仓库内是否有相同的对象，如果没有就将在&#8220;.git/objects"目录创建对应的对象，如果有就会重用已有的
对象，以节约空间。</p>
<p>下面我们来试验一下Git是否真的是以&#8220;snapshot&#8221;方式保存提交的内容。</p>
<p>先修改一下"readme.txt"，给里面加点内容，再把它暂存，最后提交到本地仓库中：</p>
<pre>$echo "hello,world2" &gt;&gt; readme.txt<br />
$git add readme.txt<br />
$git commit -m "add new content for readme.txt"<br />
[master c26c2e7] add new content for readme.txt&nbsp;&nbsp; 1 files changed, 1 insertions(+), 0 deletions(-)</pre>
<p>我们现在看看当前版本所包含的blob对象有哪些：</p>
<pre>$git cat-file -p HEAD | head -n 1 | cut -b6-15 | xargs git cat-file -p<br />
100644 blob 2e4e85a61968db0c9ac294f76de70575a62822e1&nbsp;&nbsp;&nbsp; readme.txt<br />
100644 blob 2d832d9044c698081e59c322d5a2a459da546469&nbsp;&nbsp;&nbsp; readme2.txt</pre>
<p>从上面的命令输出，我们可以看到"readme.txt"已经对应了一个新的blob对象：&#8220;2e4e85a&#8221;，而之前版本的"readme.txt&#8220;对应的blob对象是：&#8220;2d832d9&#8221;。下面我们再来看一看这两个&#8221;blob&#8220;里面的内容和我们的预期是否相同：</p>
<pre>$git cat-file -p 2e4e85a<br />
hello,world<br />
hello,world2<br />
$git cat-file -p 2d832d9<br />
hello,world</pre>
<p>大家可以看到，每一次提交的文件内容还是全部保存的（snapshot）。</p>
<h2>小结</h2>
<p>Git内在机制和其它传统的版本控制系统（VCS）间存在本质的差异，所以Git的里"add"操作的含义和其它VCS存在差别也不足为奇，&#8220;git add&#8220;不但能把未跟踪的文件（untracked file）添加到版本控制之下，也可以把修改了的文章暂存到索引中。</p>
<p>同时，由于采用&#8220;SHA1哈希串值内容寻值&#8220;和&#8221;快照存储（snapshot）&#8220;，让Git成为一个速度非常非常快的版本控制系统（VCS）。</p>
<h2>参考</h2>
<ul>
    <li><a href="http://book.git-scm.com/">GitCommunityBook</a><a href="http://gitbook.liuhui998.com/"> 中文版</a></li>
    <li><a href="http://progit.org/book/">ProGit</a><a href="http://progit.chunzi.me/zh"> 中文版</a></li>
</ul>
<h2>致谢</h2>
<p>感谢上帝对我的眷顾，让我可以有写作专栏的这样一个机会。</p>
<p>感谢朋友们在写作过程的无私帮助：<a href="http://www.infoq.com/cn/author/%E5%BC%A0%E5%87%AF%E5%B3%B0">张凯峰</a>，<a href="http://blog.liuw.name/">刘炜</a>，<a href="http://www.juvenxu.com/">许晓斌</a>，<a href="http://www.dbanotes.net/">Fenng&#8230;&#8230;</a></p>
<p>特别要感謝家人默默支持：）</p>
<p>原文：http://www.infoq.com/cn/news/2011/03/git-adventures-index-commit<br />
</p><img src ="http://www.blogjava.net/jasmine214--love/aggbug/350012.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-05-11 14:58 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/05/11/350012.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Git 历险记（三）——创建一个自己的本地仓库</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/05/11/349999.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Wed, 11 May 2011 02:56:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/05/11/349999.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/349999.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/05/11/349999.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/349999.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/349999.html</trackback:ping><description><![CDATA[<!--[if !mso]>

v":* {behavior:url(#default#VML);}
o":* {behavior:url(#default#VML);}
w":* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}

<![endif]--><!--[if gte mso 9]><xml>
Normal
0
7.8 磅
0
2
false
false
false
MicrosoftInternetExplorer4
</xml><![endif]--><!--[if gte mso 9]><![endif]--><!--[if !mso]>

st1":*{behavior:url(#ieooui) }

<![endif]--><!--[if gte mso 10]>

/* Style Definitions */
table.MsoNormalTable
{
mso-style-parent:"";
font-size:10.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:"Times New Roman";}

<![endif]-->
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">如果我们要把一个项目加入到Git的版本管理中，可以在项目所在的目录用<span><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.kernel.org%2Fpub%2Fsoftware%2Fscm%2Fgit%2Fdocs%2Fgit-init.html&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNFDjD0EMwGOr9fmxxqsJuBxIn1gbQ">git
init</a></span>命令建立一个空的本地仓库，然后再用<span><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.kernel.org%2Fpub%2Fsoftware%2Fscm%2Fgit%2Fdocs%2Fgit-add.html&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNHqz555w3br1EOt9FY9ev-ktCsr1Q">git
add</a></span>命令把它们都加入到Git本地仓库的暂存区（<span>stage
or index</span>）中，最后再用<span><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.kernel.org%2Fpub%2Fsoftware%2Fscm%2Fgit%2Fdocs%2Fgit-commit.html&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNFIooWs08Q2yIFcgtDrUgD9Sa6ooQ">git
commit</a></span>命令提交到本地仓库里。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">创建一个新的项目目录，并生成一些简单的文件内容：</span></p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 12pt; font-family: 宋体;">$ mkdir test_proj</span></strong></p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 12pt; font-family: 宋体;">$ cd test_proj</span></strong></p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 12pt; font-family: 宋体;">$ echo &#8220;hello,world&#8221; &gt; readme.txt</span></strong></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">在项目目录创建新的本地仓库，并把项目里的所有文件全部添加、提交到本地仓库中去：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">$ git init #</span><span style="font-size: 12pt; font-family: 宋体;">在当前的目录下创建一个新的空的本地仓库</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Initialized empty Git repository in
/home/user/test_proj/.git/</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">$ git add . #</span><span style="font-size: 12pt; font-family: 宋体;">把前目录下的所有文件全部添加到暂存区</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">$ git commit -m 'project init' #</span><span style="font-size: 12pt; font-family: 宋体;">创建提交</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">[master (root-commit) b36a785] project init</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">1 files changed, 1 insertions(+), 0 deletions(-)</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">create mode 100644 readme.txt</span></p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 18pt; font-family: 宋体;">Git</span></strong><strong><span style="font-size: 18pt; font-family: 宋体;">目录的结构</span></strong></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;"><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.kernel.org%2Fpub%2Fsoftware%2Fscm%2Fgit%2Fdocs%2Fgit-init.html&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNFDjD0EMwGOr9fmxxqsJuBxIn1gbQ">git
init</a></span><span style="font-size: 12pt; font-family: 宋体;">命令在项目的顶层目录中建了一个名为：&#8220;.git&#8221;的目录，它的别名是 &#8220;Git目录&#8221;（<span>Git
directory</span>）。这时&#8221;Git目录&#8221;中虽然有一些文件，但是没有任何提交（commit）在里面，所以我们叫它是空仓库（empty Git repository）。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">和<span>
SVN</span>不同，一个Git项目一般只在项目的根目录下建一个&#8220;.git&#8221;目录，而SVN则会在项目的每一个目录下建一个&#8221;.svn&#8221;目录；这也我喜欢Git的原因之一：）</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Git</span><span style="font-size: 12pt; font-family: 宋体;">把所有的历史提交信息全部存储在&#8220;Git目录&#8221;里，它就是一个Git项目的仓库；你对本地的源代码进行编辑修改后创建的提交也都会先保存在这
里面，然后再推送到远端的服务器。当我们我把项目目录和&#8220;Git目录&#8221;一起拷到其它电脑里，它能马上正常的工作（所有的提交信息全都保存在Git目录 里）；甚至可以只把&#8220;Git目录&#8221;拷走也行，但是要再签出（checkout）一次。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Git</span><span style="font-size: 12pt; font-family: 宋体;">为了 调试的方便，它可以指定项目的Git目录的位置。有两种办法：一是设置&#8220;GIT_DIR&#8221;环境变量，二是在命令行里设定&#8220;--git-dir--git-dir&#8221;参数指定它的位置，大家可以看一下这里<span>(<a href="http://www.google.com/url?q=http%3A%2F%2Fwww.kernel.org%2Fpub%2Fsoftware%2Fscm%2Fgit%2Fdocs%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNHWf-A8f_I0yQb_aiFQZrXvWN-fbw">git(1)
Manual Page</a>)</span>。</span></p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 18pt; font-family: 宋体;">庖丁解牛</span></strong></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">前面的这些东东我在<a href="http://www.google.com/url?q=http%3A%2F%2Fwww.infoq.com%2Fcn%2Fnews%2F2011%2F01%2Fgit-adventures-1&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNEyNOhf4K7Bojpy-USGG665F0BBsw">第一篇</a>里也大概的讲过一些，但是今天我们想不但要开动这辆叫&#8220;Git&#8221;的跑车，还想看看它里面有些什么样的零件，是怎么构成的。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">OK</span><span style="font-size: 12pt; font-family: 宋体;">，我们来看看&#8220;test_proj&#8221;项目里的&#8220;Git目录&#8221;的结构：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">$cd test_proj/.git </span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">$ ls | more </span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">branches/ # </span><span style="font-size: 12pt; font-family: 宋体;">新版的Git已经不再使用这个目录，所以大家看到它 #一般会是空的</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">COMMIT_EDITMSG # </span><span style="font-size: 12pt; font-family: 宋体;">保存着上一次提交时的注释信息</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">config # </span><span style="font-size: 12pt; font-family: 宋体;">项目的配置信息</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">description # </span><span style="font-size: 12pt; font-family: 宋体;">项目的描述信息</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">HEAD # </span><span style="font-size: 12pt; font-family: 宋体;">项目当前在哪个分支的信息</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">hooks/ # </span><span style="font-size: 12pt; font-family: 宋体;">默认的&#8220;hooks&#8221; 脚本文件</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">index # </span><span style="font-size: 12pt; font-family: 宋体;">索引文件，git add 后把要添加的项暂存到这里</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">info/ # </span><span style="font-size: 12pt; font-family: 宋体;">里面有一个exclude文件，指定本项目要忽略的文件 #，看一下这里</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">logs/ # </span><span style="font-size: 12pt; font-family: 宋体;">各个refs的历史信息</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">objects/ # </span><span style="font-size: 12pt; font-family: 宋体;">这个目录非常重要，里面存储都是Git的数据对象</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;"># </span><span style="font-size: 12pt; font-family: 宋体;">包括：提交(commits), 树对象(trees)，二进制对象 #（blobs）,标签对象（tags）。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">#</span><span style="font-size: 12pt; font-family: 宋体;">不明白没有关系，后面会讲的。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">refs/ # </span><span style="font-size: 12pt; font-family: 宋体;">标识着你的每个分支指向哪个提交（commit）。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">我先用<span><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.kernel.org%2Fpub%2Fsoftware%2Fscm%2Fgit%2Fdocs%2Fgit-log.html&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNHGOF0PbZgg56SCNAUc6b8YcZ0HCw">git
log命令</a></span>来看一下这个Git项目里有哪些提交：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">$ git log</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">commit 58b53cfe12a9625865159b6fcf2738b2f6774844</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Author: liuhui998 &lt;liuhui998@nospam.com&gt;</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Date: Sat Feb 19 18:10:08 2011 +0800</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">project init</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">大家可以看到目前只有一个提交（commit）对象，而它的名字就 是：&#8221;58b53cfe12a9625865159b6fcf2738b2f6774844&#8221;。这个名字就是对象内容的一个SHA签名串值，只要对象里面
的内容不同，那么我们就可以认为对象的名字不会相同，反之也成立。我在使用时一般不用把这个40个字符输全，只要把前面的5~8个字符输完就可以（前提是 和其它的对象名不冲突）。为了方便表示，在不影响表达的情况下，我会只写SHA串值的前6个字符。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">我们可以用<span><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.kernel.org%2Fpub%2Fsoftware%2Fscm%2Fgit%2Fdocs%2Fgit-cat-file.html&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNEoC8gCO_c4b7cZ6sYxcs4tNQ2EEQ">git
cat-file</a></span>来看一下这个提交里的内容是什么:</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">$ git cat-file -p 58b53c </span></p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 12pt; font-family: 宋体;">tree 2bb9f0c9dc5caa1fb10f9e0ccbb3a7003c8a0e13</span></strong></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">author liuhui998 &lt;liuhui998@nospam.com&gt; 1298110208
+0800</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">committer liuhui998 &lt;liuhui998@nospam.com&gt;
1298110208 +0800</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">project init</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">大家可以看到：提交&#8220;58b53c&#8221; 是引用一个名为&#8220;2bb9f0&#8221;的树对象（tree）。一个树对象（tree）可以引用一个或多个二进制对象（blob）, 每个二进制对象都对应一个文件。 更进一步, 树对象也可以引用其他的树对象，从而构成一个目录层次结构。我们再看一下这个树对象（tree）里面有什么东东：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">$ git cat-file -p 2bb9f0</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">100644 <strong>blob 2d832d9044c698081e59c322d5a2a459da546469
readme.txt</strong></span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">不难看出，2bb9f0&#8221;这个树对象（tree）包括了了一个二进制对象（blob），对应于我们在前面创建的那个叫 &#8221;readme.txt&#8221;的文件。现在我们来看看这个&#8221;blob&#8221;里的数据是不是和前面的提交的内容一致：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">$ git cat-file -p 2d832d</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">hello,world</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">哈哈，熟悉的&#8220;hello,world&#8221;又回来了。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">想不想看看提交对象、树对象和二进制对象是怎么在&#8221;Git目录&#8220;中存储的；没有问题，执行下面的命令，看看&#8221;.git/objects&#8221;目录里的内容：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">$ find .git/objects</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">.git/objects</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">.git/objects/2b</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">.git/objects/<strong>2b/b9f0c9dc5caa1fb10f9e0ccbb3a7003c8a0e13</strong></span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">.git/objects/2d</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">.git/objects<strong>/2d/832d9044c698081e59c322d5a2a459da546469</strong></span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">.git/objects/58</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">.git/objects/<strong>58/b53cfe12a9625865159b6fcf2738b2f6774844</strong></span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">.git/objects/info</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">.git/objects/pack</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">如果大家仔细看上面命令执行结果中的粗体字，所有的对象都使用SHA签名串值作为索引存储在&#8221;.git/objects&#8221;目录之下；SHA串的前两个字符作为目录名，后面的38个字符作为文件名。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">这些文件的内容其实是压缩的数据外加一个标注类型和长度的头。类型可以是提交对象（commit）、二进制对象（blob）、 树对象（tree）或者标签对象（tag）。</span></p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 18pt; font-family: 宋体;">如何clone一个远程项目</span></strong></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">我身边的很多朋友是因为要得到某个开源项目的代码，所以才开始学习使用Git。而获取一个项目的代码的一般的做法就是用<span><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.kernel.org%2Fpub%2Fsoftware%2Fscm%2Fgit%2Fdocs%2Fgit-clone.html&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNH6iEjeR36XCbWHKGgsAFet6EA_og">git
clone</a></span>命令进行直接复制。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">例如，有些朋友可能想看一下最新的<a href="http://www.google.com/url?q=http%3A%2F%2Fgit.kernel.org%2F%3Fp%3Dlinux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git%3Ba%3Dsummary&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNFH3yns1QmLp-eP2iG75j_IfOnR5Q">linux内核源代码</a>，当我们打开它的<a href="http://www.google.com/url?q=http%3A%2F%2Fgit.kernel.org%2F%3Fp%3Dlinux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git%3Ba%3Dsummary&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNFH3yns1QmLp-eP2iG75j_IfOnR5Q">网站</a>时，发现有如下面的一段提示：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">URL</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">URL</span><span style="font-size: 12pt; font-family: 宋体;">下面的三行字符串表示三个地址，我们可以通过这三个地址得到同样的一份Linux内核源代码。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">也就是说下面这三条命令最终得到的是同一份源代码：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">git clone
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">git cone
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">我们先来看一下URL，git://、http://、https://这些代表是传输git仓库的协议形式，而&#8220;<a href="http://www.google.com/url?q=http%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNHMKd3sqQYTqxWfWCYHzntVAuXQCA">git.kernel.org</a>&#8220;则代表了Git仓库存储的服务器名字（域名），<span>&#8220;<a href="http://www.google.com/url?q=https%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNF2MiBP8HaUZ0irlRK3_Ka-5XQ-eQ">/pub/scm/linux/kernel/git/torvalds/linux-2.6.git&#8221;</a>
</span>则代表了Git仓库在服务器上位置。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Git </span><span style="font-size: 12pt; font-family: 宋体;">仓库除了可以通过上面的</span><span style="font-size: 12pt; font-family: 宋体;">git</span><span style="font-size: 12pt; font-family: 宋体;">、</span><span style="font-size: 12pt; font-family: 宋体;">http</span><span style="font-size: 12pt; font-family: 宋体;">、</span><span style="font-size: 12pt; font-family: 宋体;">https</span><span style="font-size: 12pt; font-family: 宋体;">协议传输外还可以通过</span><span style="font-size: 12pt; font-family: 宋体;">ssh</span><span style="font-size: 12pt; font-family: 宋体;">、</span><span style="font-size: 12pt; font-family: 宋体;">ftp(s)</span><span style="font-size: 12pt; font-family: 宋体;">、</span><span style="font-size: 12pt; font-family: 宋体;">rsync</span><span style="font-size: 12pt; font-family: 宋体;">等协议来传输。<span><a href="http://www.google.com/url?q=http%3A%2F%2Fwww.kernel.org%2Fpub%2Fsoftware%2Fscm%2Fgit%2Fdocs%2Fgit-clone.html&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNH6iEjeR36XCbWHKGgsAFet6EA_og">git
clone</a></span>的本质就是把&#8220;Git目录&#8221;里面的内容拷贝过来，大家想想看，一般的&#8220;Git目录&#8221;里有成千上万的各种对象（提交对象，树对象，二进制对象......)，如果逐一复制的话，其效率就可想而知。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">如果通过git、ssh协议传输，服务器端会在传输前把需要传输的各种对象先打好包再进行传输；而http（s）协议则会反复请求要传输的不同对 象。如果仓库里面的提交不多的话，前者和后者的效率相差不多；但是若仓库里有很多提交的话，git、ssh协议进行传输则会更有效率。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">不过现在Git对http（s）协议传输Git仓库做了一定的优化，http（s）传输现在也能达到ssh协议的效率，有兴趣的朋友可以看一下这里（<span><a href="http://www.google.com/url?q=http%3A%2F%2Fprogit.org%2F2010%2F03%2F04%2Fsmart-http.html&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNH3nDvNOr6JXlew6_A3otOmOTRfXw">Smart
HTTP Transport</a></span>）。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">好的，现在我们执行了下面这条命令，把linux-2.6的最新版源代码clone下来：</span></p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 12pt; font-family: 宋体;">$cd ~/</span></strong></p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 12pt; font-family: 宋体;">$mkdir temp</span></strong></p>
<p style="text-align: left;" align="left"><strong><span style="font-size: 12pt; font-family: 宋体;">$git clone
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git</span></strong></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Initialized empty Git repository in
/home/liuhui/temp/linux-2.6/.git/</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">remote: Counting objects: 1889189, done.</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">remote: Compressing objects: 100% (303141/303141), done.</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Receiving objects: 100% (1889189/1889189), 385.03 MiB |
1.64 MiB/s, done.</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">remote: Total 1889189 (delta 1570491), reused 1887756
(delta 1569178)</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Resolving deltas: 100% (1570491/1570491), done.</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Checking out files: 100% (35867/35867), done.</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">当我们执行了<span>&#8220;git clone
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git&#8221;</span>这条命令后大家可以看到这条输出：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Initialized empty Git repository in
/home/user/temp/linux-2.6/.git/</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">这就是意味着我们在本地先建了一个&#8220;linux-2.6&#8221;目录，然后在这个目录建了一个空的Git本地仓库（Git目录）；里面将会存储从网上拉下来的历史提交。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">下面两条输入代表服务器现在调用<span><a href="http://www.google.com/url?q=http%3A%2F%2Fgit-pack-objects%2F&amp;sa=D&amp;sntz=1&amp;usg=AFQjCNFejHf4TiO1wTav6c-SWWSSTWLhNQ">
git-pack-objects</a> </span>对它的仓库进行打包和压缩：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">remote: Counting objects: 1888686, done.</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">remote: Compressing objects: 100% (302932/302932), done.</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">然后客户端接收服务器端发过送过来的数据：</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">Receiving objects: 100% (1889189/1889189), 385.03 MiB |
1.64 MiB/s, done.</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">在我们执行完上面的clone linux-2.6代码的的操作后，Git会从&#8220;Git目录&#8221;里把最新的代码到签出（checkout）到&#8220;linux-2.6&#8221;这个目录里面。我们一般
把本地的&#8220;linux-2.6&#8221;这个目录叫做&#8221;工作目录&#8220;（<span>work
directory</span>），它里面保存着你从其它地方clone（<span>or
checkout</span>）过来的代码。当你在项目的不同分支间切换时，&#8220;工作目录&#8221;中的文件可能会被替换或者删除；&#8220;工作目录&#8221;只是保存着当前的工作，你可以修 改里面文件的内容直到下次提交为止。</span></p>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">大家还记得前面的&#8220;庖丁解牛&#8221;吗，是不是觉得只杀一头叫&#8220;hello,world&#8221;的小牛太不过瘾了。没有问题，拿起前面的那把小刀，来剖析一下现在躺在你硬盘里这头叫&#8220;linux-2.6&#8221;大牛看看，我想一定很好玩。</span></p>
<div style="text-align: center;" align="center"><span style="font-size: 12pt; font-family: 宋体;">
<hr width="100%" align="center" size="2" />
</span></div>
<p style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">在写篇文章的过程中，我要感谢在那些关心我并提出真诚意见的朋友，如果没有你们真诚的意见，我也许没有这么强烈的紧迫感，也不会深深的感到自己的不足。我是第一次写专栏，<a href="http://www.infoq.com/cn/bycategory.action?authorName=%E5%BC%A0%E5%87%AF%E9%94%8B">张凯锋</a>同学给了我很大的帮助。最后还是要感谢我的家人，是他们让我有时间来进行写作：）</span></p>
<p style="text-align: left;" align="left">原文：http://www.infoq.com/cn/news/2011/02/git-adventures-local-repository<br />
</p><img src ="http://www.blogjava.net/jasmine214--love/aggbug/349999.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-05-11 10:56 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/05/11/349999.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Git历险记（二）——Git的安装和配置（转）</title><link>http://www.blogjava.net/jasmine214--love/archive/2011/05/11/349992.html</link><dc:creator>幻海蓝梦</dc:creator><author>幻海蓝梦</author><pubDate>Wed, 11 May 2011 02:26:00 GMT</pubDate><guid>http://www.blogjava.net/jasmine214--love/archive/2011/05/11/349992.html</guid><wfw:comment>http://www.blogjava.net/jasmine214--love/comments/349992.html</wfw:comment><comments>http://www.blogjava.net/jasmine214--love/archive/2011/05/11/349992.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jasmine214--love/comments/commentRss/349992.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jasmine214--love/services/trackbacks/349992.html</trackback:ping><description><![CDATA[<p>各位同学，上回<a href="http://www.infoq.com/cn/news/2011/01/git-adventures-1">Git历险记（一）</a>讲了一个 &#8220;hello Git&#8221; 的小故事。有的同学可能是玩过了其它分布式版本控制系统（DVCS），看完之后就触类旁通对Git就了然于胸了；也有的同学可能还如我当初入手Git一样，对它还是摸不着头脑。</p>
<p>从这一篇开始，我就将比较&#8220;啰嗦&#8221;的和大家一起从零开始经历Git使用的每一步，当然对我而言这也是一个重新认识Git的过程。</p>
<p>使用Git的第一步肯定是安装Git，因为在多数平台上Git是没有预装的。我平时主要的工作环境是windows和Linux（ubuntu），我想看这篇文章的同学多半也是在这两个平台下工作；下面我讲一下如何在这两个平台下安装和配置Git。</p>
<p>BTW:如果是苹果平台的用户的安装可以参看一下这里(<a href="http://gitbook.liuhui998.com/2_1.html">1</a>,<a href="http://progit.chunzi.me/zh/ch1-4.html">2</a>)，配置和命令行的使用与windows、Linux（*nix）平台差别不大。</p>
<h3><strong>Linux (*nix) 平台</strong></h3>
<p>Linus开发Git的最初目的就是为了开发Linux内核服务的，自然它对Linux的平台支持也是最棒的。在Linux下安装Git大约有几种方法：</p>
<p><strong>从源代码开始(这种方法也适合于多数*nix平台)</strong></p>
<p>从<a href="http://git-scm.com/">Git官网</a>的<a href="http://git-scm.com/download">下载页面</a>下载它最新稳定版的<a href="http://kernel.org/pub/software/scm/git/git-1.7.3.5.tar.bz2">源代码</a>，就可以从源代码开始编译、安装：</p>
<pre>$ wget http://kernel.org/pub/software/scm/git/git-1.7.3.5.tar.bz2<br />
$ tar -xjvf git-1.7.3.5.tar.bz2<br />
$ cd git-1.7.3.5<br />
$ make prefix=/usr all ;# prefix设置你的Git安装目录<br />
$ sudo make prefix=/usr install ;# 以root权限运行<br />
</pre>
<p>为了编译Git的源代码，我们还需要一些库: <a href="http://expat.sourceforge.net/">expat</a>、<a href="http://curl.linux-mirror.org/">curl</a>、 <a href="http://www.zlib.net/">zlib</a> 和 <a href="http://www.openssl.org/">openssl</a>； 除了expat 外，其它的库可能在你的机器上都安装了。</p>
<p><strong>使用安装包管理器（apt 或 yum）</strong></p>
<p>在 fedora 等系统下用<a href="http://fedoraproject.org/wiki/Tools/yum">yum</a> ：</p>
<pre>$ yum install git-core </pre>
<p>在debian, ubuntu等系统下用<a href="http://en.wikipedia.org/wiki/Advanced_Packaging_Tool">apt</a> ：</p>
<pre>$ apt-get install git-core</pre>
<p>有时候，你系统里的安装包管理器出现了问题，或是要安装Git的机器不能上网、没有编译器的话，你可以从下面的站点去下载 &#8220;.deb&#8221; 或 &#8220;.rpm&#8221;的安装包：</p>
<ul>
    <li><a href="http://kernel.org/pub/software/scm/git/RPMS/">RPM Packages</a></li>
    <li><a href="http://www.backports.org/debian/pool/main/g/git-core/">Stable Debs</a></li>
</ul>
<h3><strong>Windows平台</strong></h3>
<p>windows平台有两个模拟*nix like运行环境的工具：<a href="http://www.cygwin.com/">cygwin</a>，<a href="http://www.mingw.org/wiki/MSYS">msys</a>；Git在<a href="http://www.cygwin.com/">cygwin</a>，<a href="http://www.mingw.org/wiki/MSYS">msys</a>下都有相应的移植版本。我个人觉得msys平台下的<a href="http://code.google.com/p/msysgit/">msysGit</a>最好用，现在我在windows下也是用的这个版本。</p>
<p>很多同学可能要问，现在windows下有那多Git用户，为什么Git不直接出一个windows native版。俺当年翻看了一下<a href="http://www.kernel.org/pub/software/scm/git/git-0.01.tar.bz2">Git的源代码</a>，它里面使用了大量的*nix平台的native api，而这些api在windows下是没有的，所以必须要用cygwin、msys这样的一个中间层来满足软件移植的要求。</p>
<p>下面我&#8220;啰嗦&#8221;一下如何在windows下安装msysGit。</p>
<h3><strong>下载</strong></h3>
<p>到它的<a href="http://code.google.com/p/msysgit/downloads/list">下载页面</a>去下载一个最新的完整安装包，笔者在撰写本文时下载的是<a href="http://msysgit.googlecode.com/files/Git-1.7.3.1-preview20101002.exe">这个</a>。</p>
<h3><strong>安装</strong></h3>
<p>安装的过程没有什么好说的，一般是开始安装后，一路的点击&#8220;下一步&#8221;。由于windows平台的换行符（CRLF）和Linux(*nix)平台的换行符（LF）不同，那么在windows下开发其它平台软件的朋友有一个地方要注意（见下图)：</p>
<p><img _p="true" alt="" _href="img://image1.jpg" src="http://www.infoq.com/resource/news/2011/01/git-adventures-install-config/zh/resources/image1.JPG" border="0" /></p>
<p>在这里一最好选&#8220;Checkout as-is, commit as-is&#8221;这个选项，这样，Git就不会修改你代码的换行符风格。</p>
<p>以前有个朋友因为选错了这个选项，以致他在windows平台下的一签出（checkout）其它平台的代码，就会显示&#8221;已修改&#8220;（modified），不过后来可能msysGit也认识到这个问题了，就把默认选项改成了这个选项。</p>
<p>BTW: 其实前面两项也是有用的，如果对windows和Linux(*nix)平台<a href="http://en.wikipedia.org/wiki/Newline">如何处理换行符</a>很熟悉的话，也可以尝试一下前面两个选项：）</p>
<h2><strong>配置Git</strong></h2>
<p>在Linux下和windows下配置Git的方法差不多，只是在Linux下，可以在命令行里直接使用<a href="http://www.kernel.org/pub/software/scm/git/docs/git-config.html">git config</a>进行配置, 而在windows下则要先打开&#8220;Git Bash&#8221;，进入msysGit命令行界面，再用<a href="http://www.kernel.org/pub/software/scm/git/docs/git-config.html">git config</a>命令进行相应的配置操作。</p>
<p>好了，前面安装好了Git，现在我们开始配置：</p>
<p>第一个需要配置的就是用户的用户名和email，因为这些内容会出现在你的每一个提交（commit）里面的，像下面这样：</p>
<pre>$ git log #我们用git log查看当前仓库的提交（commit）日志<br />
commit 71948005382ff8e02dd8d5e8d2b4834428eece24<br />
Author: author &lt;author@corpmail.com&gt;<br />
Date: Thu Jan 20 12:58:05 2011 +0800<br />
Project init<br />
</pre>
<p>下面的这两行命令就是设置用户名和email：</p>
<pre>$ git config <strong>--global </strong>user.name author #将用户名设为author<br />
$ git config <strong>--global </strong>user.email author@corpmail.com #将用户邮箱设为author@corpmail.com<br />
</pre>
<p>Git的配置信息分为全局和项目两种，上面命令中带了&#8220;--global"参数，这就意味是在进行全局配置，它会影响本机上的每个一个Git项目。</p>
<p>大家看到，上面我们用的是@corpmail（公司邮箱）；但是有时候我们可能也参与了一些开源项目，那么就需要新的用户名和自己的私人邮箱，Git 可以为每个项目设定不同的配置信息。</p>
<p>在命令行环境，进入Git项目所在目录，执行下面的命令：</p>
<pre>$ git config　user.name nickname#将用户名设为nickname<br />
$ git config　user.email nickname@gmail.com #将用户邮箱设为nickname@gmail.com<br />
</pre>
<p>Git的设计哲学和Linux（*nix）一样，尽量的使用<a href="http://www.faqs.org/docs/artu/textualitychapter.html">&#8220;文本化&#8221;（Textuality）</a>；它里面尽量用文本化的形式存储信息，对于配置信息也更是如此，用户的这些配置信息全部是存储在文本文件中。Git的全局配置文件是存放在"~/.gitconfig"（用户目录下的.gitconfig）文件中：</p>
<p>我们用cat、head命令查看全局配置信息文件，并假设相关配置信息存储在文件的前3行（当然也有可能不在前3行，这里只是为了方便表示）</p>
<pre>$ cat ~/.gitconfig | head -3 <br />
[user]<br />
name = author<br />
email = author@corpmail.com<br />
</pre>
<p>而项目配置文件是存放在Git项目所在目录的".git/config"文件中，这里也像上面一样用cat、head命令查看一下：</p>
<pre>$ cat .git/config | head -3<br />
[user]<br />
name = nickname<br />
<br />
</pre>
<p>如果大家对于Git熟悉后，可以直修改&#8221;~/.gitconfig&#8221;,&#8221;.git/config&#8221;这两个文件进行配置。</p>
<p>Git里还有很多可以配置的地方，大家可以参考一下<a href="http://www.kernel.org/pub/software/scm/git/docs/git-config.html">git config</a> 和 <a href="http://gitbook.liuhui998.com/5_7.html">定制git</a>。</p>
<hr />
<p>这一篇写起来有点平淡无奇，但这是一个Git用户迈出的第一步。后面我还会有一系列的文章出来，都是我个人使用过程中的感悟。</p>
<p>有朋友问我：&#8220;为什么把文章叫作：&#8216;Git历险记&#8217;&#8221;。这是因为在使用Git的历程中，我碰到过N多的问题；同时也觉得它有点小复杂。但是当这些问题解开后，就有时不得不赞叹它设计的巧妙之处。</p>
<p>如果大家对于我的文章有什么问题和建议，欢迎给我写邮件：<img _p="true" alt="" _href="img://image1.jpg" src="http://www.infoq.com/resource/news/2011/01/git-adventures-install-config/zh/resources/image2.JPG" border="0" /></p>
<p>之前我建立了一个 <a href="https://groups.google.com/group/git123">git中文用户组</a> ，如果大家在使用Git的过程中碰到什么麻烦事，欢迎你在这个用户组里提问。</p>
<p>参考资料：</p>
<ul>
    <li><a href="http://book.git-scm.com/">GitCommunityBook</a> <a href="http://gitbook.liuhui998.com/">中文版</a></li>
    <li><a href="http://progit.chunzi.me/zh">ProGit</a> <a href="http://progit.chunzi.me/zh">中文版</a></li>
    <li><a href="http://www.kernel.org/pub/software/scm/git/docs/git-config.html">git config</a></li>
</ul>
<p>感谢<a href="http://www.infoq.com/cn/bycategory.action?authorName=%E5%BC%A0%E5%87%AF%E5%B3%B0">张凯峰</a>对本文的策划及无比耐心的审校。</p>
<p>感谢家人在我的写作过程中的默默支持。</p>
<pre>原文：http://www.infoq.com/cn/news/2011/01/git-adventures-install-config<br />
email = nickname@gmail.com</pre><img src ="http://www.blogjava.net/jasmine214--love/aggbug/349992.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jasmine214--love/" target="_blank">幻海蓝梦</a> 2011-05-11 10:26 <a href="http://www.blogjava.net/jasmine214--love/archive/2011/05/11/349992.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>