-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
1825 lines (1382 loc) · 106 KB
/
atom.xml
File metadata and controls
1825 lines (1382 loc) · 106 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[DY.Feng's Blog 叶毅锋的博客]]></title>
<link href="http://www.dyfeng.org/atom.xml" rel="self"/>
<link href="http://www.dyfeng.org/"/>
<updated>2012-09-01T10:18:53+08:00</updated>
<id>http://www.dyfeng.org/</id>
<author>
<name><![CDATA[(≧▼≦) 喵喵]]></name>
<email><![CDATA[yyfeng88625@gmail.com]]></email>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[在Linux下做一个简单的秒表]]></title>
<link href="http://www.dyfeng.org/2012/09/01/stopwatch-in-linux/"/>
<updated>2012-09-01T10:00:00+08:00</updated>
<id>http://www.dyfeng.org/2012/09/01/stopwatch-in-linux</id>
<content type="html"><![CDATA[<p>因为要比较<code>clang</code>和<code>gcc</code>哪个编译效率更高,我把我的一个项目分别用这两种编译器编译,还比较了添加<code>-j4</code>后的编译时间。可我的<code>apt-get</code>仓库下没发现有什么好的<code>秒表</code>或者<code>计时器</code>,有的计时器是用来定时执行任务的。不过山人自有妙计,我用一行命令也做了一个秒表,Linux下没有不可能的事情。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>$ time read -n1</span></code></pre></td></tr></table></div></figure>
<p>结束后按回车,就能看到运行时间了,而且还精确到0.002秒哦亲。话说回来,clang比gcc没快多少,差不多的样子而已。加了<code>j4</code>,效率也没有提高4倍,加之前36秒,加之后25秒的样子,当然这个还得具体看项目的依赖关系。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[关于nginx的一些配置]]></title>
<link href="http://www.dyfeng.org/2012/08/24/something-about-nginx-configuration/"/>
<updated>2012-08-24T01:10:00+08:00</updated>
<id>http://www.dyfeng.org/2012/08/24/something-about-nginx-configuration</id>
<content type="html"><![CDATA[<p>今天帮人配置了下nginx,主要是二级域名以对应文件夹为根目录。主要的问题是在<code>Windows</code>环境下配置的,而小生一直都是在<code>Linux</code>环境下工作的,对<code>Windows</code>不大了解,记录下今天学到的小技巧。</p>
<!-- more -->
<h1>使用lvh.me做域名调试</h1>
<p>因为我要配置二级域名,而我手头又没有域名,所以配置写起来很麻烦。其中一个方法是改<code>host</code>文件,可在我的XP里却死活不行,host文件改了跟没改一样,又没有开什么杀毒软件之类的,对Windows甚为不解。</p>
<p>好在有人免费提供了一些指向<code>127.0.0.1</code>的域名,<code>lvh.me</code>就是其中的一个。用他来调试nginx域名配置就最好不过了。</p>
<h1>nginx配置的</h1>
<ul>
<li>nginx的<code>IF</code>语句没有ELSE,判断语句里面没有&&和||,你别想多了,他就是一个<code>IF</code>而已。</li>
</ul>
<p>如果要用到多个逻辑判断怎么办?没有&&又没有||。我们来设置一个标记<code>$flag</code></p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>set $flag 'test';
</span><span class='line'>
</span><span class='line'>if ( 条件一 ){
</span><span class='line'>set $flag '';
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>if ( 条件二 ){
</span><span class='line'>set $flag '';
</span><span class='line'>}
</span><span class='line'>
</span><span class='line'>if ( $flag = 'test' ){
</span><span class='line'>做点什么;
</span><span class='line'>}</span></code></pre></td></tr></table></div></figure>
<p>等价于</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>if ( !条件一 && !条件二 ){
</span><span class='line'>做点什么
</span><span class='line'>}</span></code></pre></td></tr></table></div></figure>
<p>所有的逻辑语句都可以用这种标记法来实现。</p>
<ul>
<li><p>文件和目录判断,linux下好像-f也能判断目录,我今天就栽在这个上了。</p>
<ul>
<li>-f和!-f判断是否存在文件</li>
<li>-d和!-d判断是否存在目录</li>
<li>-e和!-e判断是否存在文件或目录</li>
<li>-x和!-x判断文件是否可执行</li>
</ul>
</li>
<li><p>nginx配置文件的字符串比较。要注意一点,nginx的字符串都是按正则使用的。</p>
<ul>
<li>匹配
<ul>
<li>区分大小写 <code>~</code></li>
<li>不区分大小写 <code>~*</code></li>
<li>精确匹配 <code>=</code></li>
</ul>
</li>
<li>不匹配。前面加<code>!</code>
<ul>
<li>区分大小写 <code>!~</code></li>
<li>不区分大小写 <code>!~*</code></li>
<li>精确匹配 <code>!=</code></li>
</ul>
</li>
</ul>
</li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[解决Firefox菜单不弹出和右键失效的问题]]></title>
<link href="http://www.dyfeng.org/2012/08/23/menu-does-not-popup-and-right-click-does-not-work-in-firefox/"/>
<updated>2012-08-23T13:19:00+08:00</updated>
<id>http://www.dyfeng.org/2012/08/23/menu-does-not-popup-and-right-click-does-not-work-in-firefox</id>
<content type="html"><![CDATA[<p>最近一次kubuntu升级后,我发现一个很奇怪的现象,我的Firefox某些时候菜单栏不能弹出,右键也失灵了。准确来说,是弹出了,又很快地焦点转移,导致他又关闭了。Google下发现遇到这个问题的童鞋还真不少,而且解决的方法各有不同,看来这个问题是Firefox一直存在的。</p>
<!-- more -->
<p>网上的解决方法:</p>
<ul>
<li>升级你的Firefox到14+。</li>
<li>重装你的Firefox</li>
<li>插件冲突</li>
</ul>
<p>后来我发现他有个规律,一开始Firefox是好的,后来我在里面搜索打中文的时候,灵异的事情发生了,右键和菜单又能用了。这时候我才发现是我的输入法<code>fcitx</code>的问题。</p>
<p>解决的方法是安装<code>fcitx-frontend-gtk2</code>和<code>fcitx-frontend-gtk3</code>,因为<code>fcitx-frontend-qt4</code>我是一直有装的,所以就不重复了。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">sudo</span> apt-get install fcitx-frontend-gtk2 fcitx-frontend-gtk3
</span></code></pre></td></tr></table></div></figure>
<p>想起我这个ubuntu是先装了<code>Unity</code>界面,后来我卸载了<code>Unity</code>,重新回到我<code>KDE</code>的怀抱。可能就是在清理软件的时候,多手删了,善哉善哉。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[修改octopress的pygment语法]]></title>
<link href="http://www.dyfeng.org/2012/08/18/change-the-pygment-lexer-of-octopress/"/>
<updated>2012-08-18T18:43:00+08:00</updated>
<id>http://www.dyfeng.org/2012/08/18/change-the-pygment-lexer-of-octopress</id>
<content type="html"><![CDATA[<p>最近我在写一篇关于Git使用的文章,里面贴了大量<code>bash</code>命令。我的语法高亮是用Octopress自带的<code>pygements.rb</code>,用起来总觉得不大爽,因为他高亮的地方实在是太少了,只有少量的命令有高亮。自己动手丰衣足食,下面记录我修改的过程:</p>
<!-- more -->
<h1>Octopress语法高亮原理</h1>
<p>我要修改Octopress的语法高亮,当然得搞清楚他的来龙去脉。</p>
<p>首先在<code>plugins</code>目录下你会看到<code>pygments_code.rb</code>插件,这个插件的功能就是调用<code>pygements.rb</code>库,把代码转换成html,还在你项目的<code>.pygements-cache</code>目录下缓存代码块。代码样式他其实是通过css调节的,他生成的只是一个堆html标签。</p>
<p><code>pygements.rb</code>库其实是ruby封装了python的<code>pygements</code>库,而且<code>pygements.rb</code>里面已经自带了一个<code>pygements</code>库(这真不是一个好主意,系统讲究的应该是低耦合)。</p>
<p>就这样…</p>
<ol>
<li>Octopress调用pygments_code.rb插件。</li>
<li>pygments_code.rb插件调用pygements.rb库。</li>
<li>pygements.rb库调用python的pygements库。</li>
</ol>
<p>完成了对代码的语法高亮。</p>
<h1>修改Octopress语法高亮规则</h1>
<p>你先要确保你的电脑上其他地方没有安装python的<code>pygements</code>。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">sudo</span> apt-get remove python-pygments
</span></code></pre></td></tr></table></div></figure>
<p>,我们先找出你<code>pygments.rb</code>的安装目录:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">bundle</span> show pygments.rb
</span><span class='line'>/var/lib/gems/1.9.1/gems/pygments.rb-0.2.13
</span></code></pre></td></tr></table></div></figure>
<p>修改<code>pygements.rb</code>自带python<code>pygments</code>库的语法文件。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">cd</span> YOUR_PYGEMENTS.RB_PATH/vendor/pygments-main/
</span><span class='line'><span class="nv">$ </span><span class="nb">vim</span> pygments/lexers/shell.py
</span></code></pre></td></tr></table></div></figure>
<p>找到<code>BashLexer</code>下<code>tokens</code>字典,<code>basic</code>下,大概修改成这个样子。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="c"># (r'\b(alias|bg|bind|break|find|builtin|caller|cd|command|compgen|'</span>
</span><span class='line'><span class="c"># r'complete|declare|dirs|disown|echo|cat|enable|eval|exec|exit|'</span>
</span><span class='line'><span class="c"># r'export|false|fc|fg|getopts|hash|help|history|jobs|kill|let|'</span>
</span><span class='line'><span class="c"># r'local|logout|popd|printf|pushd|pwd|read|readonly|set|shift|'</span>
</span><span class='line'><span class="c"># r'shopt|source|suspend|test|time|times|trap|true|type|typeset|'</span>
</span><span class='line'><span class="c"># r'ulimit|umask|unalias|unset|wait'</span>
</span><span class='line'><span class="c"># r')\s*\b(?!\.)',</span>
</span><span class='line'><span class="c"># Name.Builtin),</span>
</span><span class='line'><span class="p">(</span><span class="s">r'(?<=\$\s)\b\w+'</span><span class="p">,</span><span class="n">Name</span><span class="o">.</span><span class="n">Builtin</span><span class="p">),</span>
</span></code></pre></td></tr></table></div></figure>
<p>一开始我是想遍历<code>PATH</code>下所有目录,把里面的命令都动态加上,但python的正则抗议太多选项了,所以我就唯有手动改规则了。现在的规则是以<code>$</code>开头的一个单词定义为命令。</p>
<p>最后一步千万不要漏了,清除<code>pygments_code.rb</code>插件的缓存,重新生成页面</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">rm</span> -rf .pygments-cache/*
</span><span class='line'><span class="nv">$ </span><span class="nb">rake</span> generate
</span><span class='line'><span class="nv">$ </span><span class="nb">rake</span> preview
</span></code></pre></td></tr></table></div></figure>
<p>现在你应该看到bash的语法高亮<code>亮</code>多了吧。</p>
<h1>参考文献</h1>
<ol>
<li><a href="http://pygments.org/docs/lexerdevelopment/">如何编写pygements的语法规则</a>,来自pygements官网</li>
<li><a href="http://docs.python.org/library/re.html">python正则表达式参考</a>,来自python官网</li>
</ol>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Git深入浅出学习]]></title>
<link href="http://www.dyfeng.org/2012/08/12/all-about-git/"/>
<updated>2012-08-12T00:38:00+08:00</updated>
<id>http://www.dyfeng.org/2012/08/12/all-about-git</id>
<content type="html"><![CDATA[<p>在看这篇文章之前…</p>
<ul>
<li><p>如果你只是在找Git的使用命令,而不是想深入学习Git,请绕道。</p>
<p>Git和Linux一样,不是学几个命令就能理解到他的精髓的。</p></li>
<li><p>什么?你在Windows下?那你一定懂Cygwin了。不知道Cygwin?那你看这篇文章就有点吃力了。还不会用命令行?那你可以绕道了,这篇文章对你来说是天书。</p></li>
<li><p>请先忘记你之前所了解关于Git的一切,因为网络上的文章有99%都是以纰传纰的!!</p></li>
<li><p>请先忘记你所有学的其他版本管理系统。</p>
<p>请统统忘记<code>Svn</code>、<code>Cvs</code>、<code>Mercury</code>等,因为Git的思想跟实现跟他们有天大的区别!!</p></li>
<li><p>请不要急于求成,网上99%速成的教程都是有速度没质量的。</p>
<p>我不是说他们写的质量差,而是因为很多东西他都给简化掉了,让人有个错觉:这个很简单。其实这是不利于学习的。</p></li>
<li><p>请先从<code>最基础</code>的学起,而不是直接看操作命令,否则你只会只其然而不知其所以然,最后看到一头雾水。</p></li>
<li><p>我一开始将不会讲解任何关于使用Git的命令,而是先讲解Git的<code>底层原理</code>,如果你耐不住性子的请不要看。但我相信,这会是最快入门Git的方法之一。</p></li>
<li><p>你大概需要几天时间来消化和试验,所以不用急,慢慢看。反正你都误用了这么长时间了,花点时间来正确认识Git还是值得的。</p></li>
</ul>
<!-- 因为囊括的东西比较多,所以我这篇文章比较。对于一个作者来说,罗列知识点很容易,但你要把知识点组织起来,让人思路清晰,脉络通畅,那就是难点了。 -->
<!-- -->
<!-- 建议阅读方法: -->
<!-- -->
<!-- 0. 你可以先大概浏览一下`Local本地使用`和`Remote远程相关使用`这两章,感受一下Git的大概使用,这两章是讲述Git的在各种使用场景下的命令,不必精读。如果只是想查找命令的童鞋,看这章就可以了。 -->
<!-- 1. 再看看第一章`Git基础讲解`,最基本的概念和Git的运作方式会在这里讲述。 -->
<!-- 2. 当你遇到有不明白的术语或者词汇,不妨到`相关术语以及本文翻译`那章找找。 -->
<!-- 3. 再回来`Local本地使用`和`Remote远程相关使用`这两章。相信这个时候你应该能通过这命令,而知道他们底层究竟是做了什么操作。 -->
<!-- 4. 有空的时候可以看看`小技巧` -->
<!-- 5. 如果对Git的使用还有什么疑问,可以留言。本人也是初学Git,可以共同探讨学习。 -->
<!--more-->
<h1>Git基础讲解</h1>
<h2>Git是什么?</h2>
<p><del>Git是一个版本控制软件…</del>(地球人都知道的就不废话了,省略几百字)Git就是</p>
<ul>
<li>一个带有<code>二次元平衡世界</code>、<code>时光倒流</code>功能的<code>文件管理系统</code>。</li>
<li>一个<code>键值对</code>的数据库,<code>键</code>是<code>值</code>的SHA1值。<code>tree .git/objects</code>你就能看到他们了。</li>
<li>一个一切皆对象的系统</li>
</ul>
<!-- 为什么说他是文件管理系统呢?那跟我电脑本地的文件管理系统有什么区别?这个就得从Git的`文件模型`--基础对象模型说起了。 -->
<p>Git说白了就是一个文件储存系统,只是他储存不单单是我们普通意义上的<code>文件</code>,他还储存了<code>tree(树)</code>,<code>commit(快照)</code>,<code>tag(标签)</code>。Git能够储存的东西我们叫做<code>基础对象</code>(Git Objects)。</p>
<p>其实我们用Git做的<em>一切</em>都是围绕着这些<code>基础对象</code>而展开的,所以先学懂这个比先去学习几句命令要重要得多。</p>
<h2>Git的基本对象类型(Git Objects)</h2>
<p> 在Git系统里面有四种基本对象类型,分别是<code>blob</code>,<code>tree(树)</code>,<code>commit(快照)</code>,<code>tag(标签)</code>。几乎所有的Git都建立在管理操纵四个简单的数据结构之上,即它是建立在机器文件系统之上的一种自己的小型文件系统。</p>
<p><code>commit</code>在其他的版本控制软件很多时候都是翻译成<code>提交</code>,但在Git上他不能翻译成<code>提交</code>。他在Git上是一个<code>对象</code>,一个<code>名词</code>,一个<code>noun</code>,一个快照。这一点在很多网络文章里面都是以纰传纰的。</p>
<h3>blob对象</h3>
<p>blob对象储存了我们平常接触的文件,但他只储存了这个文件的<code>内容</code>,而没有包含修改日期、拥有者、<em>文件名</em>、目录路径之类的信息。下面我们来做个实验:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'> <span class="nv">$ </span><span class="nb">echo</span> <span class="s1">'Hello,Git!'</span> > test.txt
</span><span class='line'> <span class="nv">$ </span><span class="nb">git</span> hash-object test.txt
</span><span class='line'> 63008ae88b4446dfc43b47f18aee5b427203b255
</span></code></pre></td></tr></table></div></figure>
<p>你可看到他生成了一个40位的<code>SHA1</code>值,这SHA1值就是通过<code>文件内容</code>计算出来的,所以说同一个文件只有一个SHA1值。如果你在你的电脑上做同样内容的一个文件,即使文件名不一样,计算出来的结果都是一样的。</p>
<p>现在我们把<code>test.txt</code>纳入我们Git的引索(index)里面:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> add test.txt
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> commit -m <span class="s2">"add test.txt"</span> <span class="c">#这句不是必须的,git add之后就已经纳入到Git的引索里面去了</span>
</span></code></pre></td></tr></table></div></figure>
<p>提交之后,<code>test.txt</code>的内容已经放进了我们Git的blob树了,我们可以根据SHA1值来看看文件的内容:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file blob 63008ae88b4446dfc43b47f18aee5b427203b255
</span><span class='line'>Hello,Git!
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file blob 63008a <span class="c">#其实用前六位或者七位就可以了</span>
</span><span class='line'>Hello,Git!
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file t 63008a <span class="c">#查看对象类型</span>
</span><span class='line'>blob
</span></code></pre></td></tr></table></div></figure>
<p>blob只记录文件的内容的好处:
- Git可以快速的仅仅通过对象名称决定两个对象是否相同
- 由于对象名称在每一个库(repository)中都由相同的方式计算得到,相同的内容存储到不同的库中将总被存储到相同的名称下,减少需要的硬盘空间。</p>
<h3>commit对象</h3>
<p>如果你有小用过Git,那对commit一定很熟悉,不就是提交嘛,其实不然。在这里的commit表示<code>快照</code>,是名词。跟blob一样,也是Git的<code>基础对象</code>之一。</p>
<p>查看一个快照(commit)对象,可以看到快照里记录了根目录树,作者,还有提交的信息。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file commit d5cb71
</span><span class='line'>tree e84b991fd55acf5eb290a11c0ae4149ce4ffc8dd
</span><span class='line'>author DY.Feng <yyfeng88625@gmail.com> 1345233032 +0800
</span><span class='line'>committer DY.Feng <yyfeng88625@gmail.com> 1345233032 +0800
</span><span class='line'>
</span><span class='line'>add a.txt
</span></code></pre></td></tr></table></div></figure>
<p>在下一小节<code>tree对象</code>里,我们将会学到如何创建一个快照对象,因为快照必须需要一个<code>树(tree)对象</code>。</p>
<h3>tree对象</h3>
<p>树(tree)对象跟我们本地的目录树很相似,下面我们来试验:</p>
<p>准备试验用文件</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">mkdir</span> bb <span class="o">&&</span> touch bb/a.txt <span class="c">#新建一个文件夹并放置一个空文件在里面</span>
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> add bb/a.txt <span class="o">&&</span> git commit -m <span class="s2">"add bb/a.txt"</span> <span class="c">#提交</span>
</span></code></pre></td></tr></table></div></figure>
<p>查看HEAD(这里的HEAD其实不是树对象,而是快照对象),你会看到只有两个文件,一个是<code>test.txt</code>,另外一个是<code>树bb</code>,那还有一个文件<code>a.txt</code>呢?</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> ls-tree HEAD
</span><span class='line'>040000 tree 65a457425a679cbe9adf0d2741785d3ceabb44a7 bb
</span><span class='line'>100644 blob 63008ae88b4446dfc43b47f18aee5b427203b255 test.txt
</span></code></pre></td></tr></table></div></figure>
<p>文件<code>a.txt</code>在<code>bb树</code>里面。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$git</span> ls-tree 65a457425a679cbe9adf0d2741785d3ceabb44a7
</span><span class='line'>100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a.txt
</span></code></pre></td></tr></table></div></figure>
<p>树也是Git的<code>基本对象</code>,所以准确来说:blob对象<em>不是</em>储存在树对象里面,而是树对象里面写有blob对象的<code>SHA1值</code>,所以tree对象可以查找到blob对象。</p>
<p>不知道你看到这里有没有发现,我们上面的树(tree)对象,我们并没有手动添加,在<code>git add</code>的时候也没有新增,而是在<code>git commit</code>之后增加的。究竟树对象是怎么新建的呢?下面我们来试验手动添加树对象:</p>
<p>重置我们的工作目录。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">rm</span> -rf * .git/
</span><span class='line'><span class="nv">$ </span><span class="nb">echo</span> <span class="s1">'Good bye'</span> > a.txt
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> init
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> add a.txt
</span></code></pre></td></tr></table></div></figure>
<p>现在引索(stage)里有我们的a.txt了。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> ls-files --stage
</span><span class='line'>100644 c0ee9ab00ab41be0d401f00f7a4aaf2e478f9f1e 0 a.txt
</span><span class='line'><span class="nv">$ </span><span class="nb">find</span> .git/objects -type f | sort
</span><span class='line'>.git/objects/c0/ee9ab00ab41be0d401f00f7a4aaf2e478f9f1e
</span></code></pre></td></tr></table></div></figure>
<p>我们来创造一棵树吧,在你的电脑上应该会得到同样的一串SHA1值,因为这棵树里面的文件(文件名和文件SHA1值)我们是一样的。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>git write-tree
</span><span class='line'>e84b991fd55acf5eb290a11c0ae4149ce4ffc8dd
</span></code></pre></td></tr></table></div></figure>
<p>有了一棵树,我们就能创造出一个快照(commit)了。记得前面说过,一个快照(commit)里面包含了一个树对象的SHA1值,所以你如果要创造一个快照(commit),就必须有一棵树。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">echo</span> <span class="s2">"add a.txt"</span> |git commit-tree e84b99 <span class="c">#新建一个快照,并把树e84b99添加到里面</span>
</span><span class='line'>d5cb71ea0e9c6a2c6b198bd5e44b80bd72aac806
</span><span class='line'><span class="nv">$ </span><span class="nb">find</span> .git/objects -type f | sort <span class="c">#我们现在有了一个文件,一棵树,还有一个快照</span>
</span><span class='line'>.git/objects/c0/ee9ab00ab41be0d401f00f7a4aaf2e478f9f1e
</span><span class='line'>.git/objects/d5/cb71ea0e9c6a2c6b198bd5e44b80bd72aac806
</span><span class='line'>.git/objects/e8/4b991fd55acf5eb290a11c0ae4149ce4ffc8dd
</span></code></pre></td></tr></table></div></figure>
<p>如果这个快照是有parent的,也就是说在这个快照之前,已经创建过一个快照,他们在同一条分支(branch)上。那你可以指定<code>-p 选项</code>来指定parent。</p>
<p>我们把<code>master分支头(the head of master branch)</code>指向到<code>目前的快照(current commit)</code>。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">echo</span> d5cb71ea0e9c6a2c6b198bd5e44b80bd72aac806 > .git/refs/heads/master
</span></code></pre></td></tr></table></div></figure>
<p>或者用更加安全的方法。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> update-ref ref/heads/master d5cb71
</span></code></pre></td></tr></table></div></figure>
<p>我们再把<code>HEAD</code>指向到master分支头(这一步在我的电脑上,<code>git init</code>的时候他已经帮我完成了)。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> symbolic-ref HEAD refs/heads/master
</span></code></pre></td></tr></table></div></figure>
<p>到目前为止,我们已经成功手动完成了一次<code>git commit</code>。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> log
</span><span class='line'>commit d5cb71ea0e9c6a2c6b198bd5e44b80bd72aac806
</span><span class='line'>Author: DY.Feng <yyfeng88625@gmail.com>
</span><span class='line'>Date: Sat Aug 18 03:50:32 2012 +0800
</span><span class='line'>
</span><span class='line'> add a.txt
</span></code></pre></td></tr></table></div></figure>
<p>如果我们没有把master分支头指向到<code>目前的快照</code>,或者快照沒有成为别人的parent,简单一句就是<code>孤立的快照</code>,不能被正常访问到的。那么他就有可能被Git的垃圾回收程序(<code>git gc</code>,他不仅回收垃圾,貌似还会压缩)删除。</p>
<h3>tag对象</h3>
<p>标签(tag)跟我们平时的标签贴纸用途非常相似,你可以把一个标签贴到一个对象上(例如commit对象,甚至是tag对象),用来标记这个对象的用途。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">rm</span> -rf .git <span class="c">#我们把现有的.git删除,重新建立一个干净的git</span>
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> init
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> add test.txt
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> ls-files --stage
</span><span class='line'>100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 test.txt
</span><span class='line'>
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> tag <span class="s1">'my_file_test.txt'</span> e69de29 <span class="c">#给文件test.txt打个标签,标签名称不能有空格</span>
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> tag
</span><span class='line'>my_file_test.txt
</span><span class='line'><span class="nv">$ </span><span class="nb">cat</span> .git/refs/tags/my_file_test.txt <span class="c">#可以看到.git/refs/tags/目录下储存了一个标签,标签内容就是文件的SHA1值</span>
</span><span class='line'>e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
</span><span class='line'><span class="nv">$ </span><span class="nb">find</span> .git/objects -type f |sort <span class="c">#这个时候tag没有储存到objects目录下,也就是说他现在不是对象</span>
</span><span class='line'>.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="c">#我们再新建一个文件</span>
</span><span class='line'><span class="nv">$ </span><span class="nb">echo</span> <span class="s2">"Today,I have many many homework"</span> > homework.txt
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> add homework.txt
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> ls-files --stage
</span><span class='line'>100644 36821547a08783ec0779dfa89d9f714196402dc6 0 homework.txt
</span><span class='line'>100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 test.txt
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> tag -m <span class="s2">"This is my homework"</span> v1.0 3682154 <span class="c">#homework.txt贴上标签,这次加上标签描述</span>
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> tag
</span><span class='line'>my_file_test.txt
</span><span class='line'>v1.0
</span><span class='line'><span class="nv">$ </span><span class="nb">cat</span> .git/refs/tags/v1.0 <span class="c">#这次看到他指向的并不是homework.txt文件</span>
</span><span class='line'>d1e1a5c0a8c01ac604c87e51d583131d7f9a3ebf
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file -t d1e1a5c <span class="c">#原来这次指向的是一个标签(tag)</span>
</span><span class='line'>tag
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file tag d1e1a5c <span class="c">#让我们来看看标签里面究竟装了什么</span>
</span><span class='line'>object 36821547a08783ec0779dfa89d9f714196402dc6
</span><span class='line'>type blob
</span><span class='line'>tag v1.0
</span><span class='line'>tagger DY.Feng <yyfeng88625@gmail.com> 1345259919 +0800
</span><span class='line'>
</span><span class='line'>This is my homework
</span><span class='line'><span class="nv">$ </span><span class="nb">find</span> .git/objects -type f |sort <span class="c">#这里可以看到这时候的标签(tag)是一个对象了</span>
</span><span class='line'>.git/objects/36/821547a08783ec0779dfa89d9f714196402dc6
</span><span class='line'>.git/objects/d1/e1a5c0a8c01ac604c87e51d583131d7f9a3ebf
</span><span class='line'>.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
</span><span class='line'>
</span><span class='line'><span class="c">#从上面的试验可以看到,tag不一定是基本对象。</span>
</span><span class='line'>
</span><span class='line'><span class="c">#tag也可以贴到tag对象上</span>
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> tag -m <span class="s2">"This is the tag of tag"</span> v2.0 d1e1a5
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> tag
</span><span class='line'>my_file_test.txt
</span><span class='line'>v1.0
</span><span class='line'>v2.0
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file -t v2.0
</span><span class='line'>tag
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file tag v2.0 <span class="c">#不一定要用SHA1值,用引用就可以了。</span>
</span><span class='line'>object d1e1a5c0a8c01ac604c87e51d583131d7f9a3ebf
</span><span class='line'>type tag
</span><span class='line'>tag v2.0
</span><span class='line'>tagger DY.Feng <yyfeng88625@gmail.com> 1345260572 +0800
</span><span class='line'>
</span><span class='line'>This is the tag of tag
</span></code></pre></td></tr></table></div></figure>
<h3>总结</h3>
<p>究竟我们上面的所有动作,Git都是怎么储存的?让我们看看他都储存了什么文件吧:</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">rm</span> -rf .git <span class="c">#我们把现有的.git删除,重新建立一个干净的git</span>
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> init
</span><span class='line'><span class="nv">$ </span><span class="nb">tree</span> .
</span><span class='line'>.
</span><span class='line'>├── bb
</span><span class='line'>│ └── a.txt
</span><span class='line'>└── test.txt
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> commit -m <span class="s2">"add all"</span> -a <span class="c">#添加并提交所有的文件到git</span>
</span><span class='line'><span class="nv">$ </span><span class="nb">find</span> .git/objects -type f | sort
</span><span class='line'>.git/objects/45/893175c9b60bdd4727c2a51ced8bae8a9c213f
</span><span class='line'>.git/objects/5b/e1b8923c561189f1fcfc5bcf2d2fe0b7684e76
</span><span class='line'>.git/objects/63/008ae88b4446dfc43b47f18aee5b427203b255
</span><span class='line'>.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7
</span><span class='line'>.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
</span></code></pre></td></tr></table></div></figure>
<p>从上面我们可以看到,现在有两个文件,两个目录(根目录和bb目录),一个快照(commit)。</p>
<p>这个就是我们的快照(commit),可以看到快照里记录了根目录树。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file -t 45893175c9b60bdd4727c2a51ced8bae8a9c213f
</span><span class='line'>commit
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file commit 45893175c9b60bdd4727c2a51ced8bae8a9c213f
</span><span class='line'>tree 5be1b8923c561189f1fcfc5bcf2d2fe0b7684e76
</span><span class='line'>author DY.Feng <yyfeng88625@gmail.com> 1345226467 +0800
</span><span class='line'>committer DY.Feng <yyfeng88625@gmail.com> 1345226467 +0800
</span><span class='line'>
</span><span class='line'>add all
</span></code></pre></td></tr></table></div></figure>
<p>查看根目录树,可以看到他里面包含了<code>test.txt文件</code>和<code>bb目录</code>的SHA1值,就像一个指针一样指向他们。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file -t 5be1b8923c561189f1fcfc5bcf2d2fe0b7684e76
</span><span class='line'>tree
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> ls-tree 5be1b8923c561189f1fcfc5bcf2d2fe0b7684e76
</span><span class='line'>040000 tree 65a457425a679cbe9adf0d2741785d3ceabb44a7 bb
</span><span class='line'>100644 blob 63008ae88b4446dfc43b47f18aee5b427203b255 test.txt
</span></code></pre></td></tr></table></div></figure>
<p>查看<code>test.txt</code></p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file -t 63008ae88b4446dfc43b47f18aee5b427203b255
</span><span class='line'>blob
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file blob 63008ae88b4446dfc43b47f18aee5b427203b255
</span><span class='line'>Hello,Git!
</span></code></pre></td></tr></table></div></figure>
<p>这个是<code>bb目录</code>树,里面只有一个文件<code>a.txt</code>。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file -t 65a457425a679cbe9adf0d2741785d3ceabb44a7
</span><span class='line'>tree
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> ls-tree 65a457425a679cbe9adf0d2741785d3ceabb44a7
</span><span class='line'>100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a.txt
</span></code></pre></td></tr></table></div></figure>
<p>这个是<code>bb目录</code>里面的<code>a.txt</code>。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> cat-file -t e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
</span><span class='line'>blob
</span></code></pre></td></tr></table></div></figure>
<p>一共增加了5个文件。</p>
<p>这个时候我们改改<code>bb/a.txt</code>文件。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">echo</span> <span class="s1">'Good'</span> >bb/a.txt
</span></code></pre></td></tr></table></div></figure>
<p>让Git跟踪<code>bb/a.txt</code>文件。你会看到里面会新增了一个文件,他就是新修改的<code>bb/a.txt</code>文件。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> add .
</span><span class='line'><span class="nv">$ </span><span class="nb">find</span> .git/objects -type f | sort
</span><span class='line'>.git/objects/45/893175c9b60bdd4727c2a51ced8bae8a9c213f
</span><span class='line'>.git/objects/5b/e1b8923c561189f1fcfc5bcf2d2fe0b7684e76
</span><span class='line'>.git/objects/63/008ae88b4446dfc43b47f18aee5b427203b255
</span><span class='line'>.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7
</span><span class='line'>.git/objects/cd/9dd73b78cf79e797c97b8fd5d8b92e28d4437f
</span><span class='line'>.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
</span></code></pre></td></tr></table></div></figure>
<p>即使我们现在用<code>git checkout</code>和<code>git reset</code>,新增加的那个文件也不会消失,虽然我们现在无法通过正常的途径来获取他。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> checkout HEAD
</span><span class='line'>M bb/a.txt <span class="nv">$ </span><span class="nb">find</span> .git/objects -type f | sort
</span><span class='line'>.git/objects/45/893175c9b60bdd4727c2a51ced8bae8a9c213f
</span><span class='line'>.git/objects/5b/e1b8923c561189f1fcfc5bcf2d2fe0b7684e76
</span><span class='line'>.git/objects/63/008ae88b4446dfc43b47f18aee5b427203b255
</span><span class='line'>.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7
</span><span class='line'>.git/objects/cd/9dd73b78cf79e797c97b8fd5d8b92e28d4437f
</span><span class='line'>.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
</span><span class='line'><span class="nv">$ </span><span class="nb">git</span> reset --hard HEAD
</span><span class='line'>HEAD is now at 4589317 add all
</span><span class='line'><span class="nv">$ </span><span class="nb">find</span> .git/objects -type f | sort
</span><span class='line'>.git/objects/45/893175c9b60bdd4727c2a51ced8bae8a9c213f
</span><span class='line'>.git/objects/5b/e1b8923c561189f1fcfc5bcf2d2fe0b7684e76
</span><span class='line'>.git/objects/63/008ae88b4446dfc43b47f18aee5b427203b255
</span><span class='line'>.git/objects/65/a457425a679cbe9adf0d2741785d3ceabb44a7
</span><span class='line'>.git/objects/cd/9dd73b78cf79e797c97b8fd5d8b92e28d4437f
</span><span class='line'>.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
</span></code></pre></td></tr></table></div></figure>
<p>从这里我们就可以看出Git与其他的版本管理系统有什么区别。最大的区别就是Git记录的其实是每个文件的快照,但他不管这个快照是什么时候在什么目录被什么人建立的,因为这些他都可以通过<code>tree对象</code>和<code>commit对象</code>来推算出来。</p>
<h2>引用(ref)</h2>
<p>其实上面我们已经看过了很多个引用,或者叫指向。像HEAD,master,tag这些都是引用。所有的引用都放在<code>.git/refs/</code>里。通过引用,我们可以很方便地调用Git的基本对象。</p>
<h2>关于分支(branch)</h2>
<p>在Git系统里面,分支(branch)並不是基本类型,而是某个<code>快照(commit)</code>的引用。这个非常容易理解,要知道,我们的<code>快照(commit)</code>是一个链式结构,从最新的那个快照起,我们可以完整地追溯到他的所有父快照。</p>
<h1>Local本地使用</h1>
<p>这章的题目叫<code>Local本地</code>,是因为这一章的操作你都不需要连接互联网就能完成。这也是分布式版本管理的一个特点,每个人都是一个<code>完整</code>的版本(相对自己而言),你可以在你的本机上检出,提交,删除…</p>
<h2>初始化</h2>
<h3>设置全局变量</h3>
<p>名字和Email会作为Github显示的依据。你不设置,没问题,只是Github的提交里显示不出你的用户名而已。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>git config --global user.name <span class="s2">"DY.Feng"</span>
</span><span class='line'>git config --global user.email <span class="s2">"yyfeng88625"</span>
</span><span class='line'>git config --global color.ui <span class="s2">"always"</span>
</span></code></pre></td></tr></table></div></figure>
<h3>初始化新版本库</h3>
<p>初始化,只会在根目录下创建一个<code>.git</code>的文件夹。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>git init
</span></code></pre></td></tr></table></div></figure>
<p>初始化后的目录结构</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">tree</span> .git/
</span><span class='line'>.git/
</span><span class='line'>├── branches
</span><span class='line'>├── config
</span><span class='line'>├── description
</span><span class='line'>├── HEAD
</span><span class='line'>├── hooks
</span><span class='line'>│ ├── applypatch-msg.sample
</span><span class='line'>│ ├── commit-msg.sample
</span><span class='line'>│ ├── post-update.sample
</span><span class='line'>│ ├── pre-applypatch.sample
</span><span class='line'>│ ├── pre-commit.sample
</span><span class='line'>│ ├── prepare-commit-msg.sample
</span><span class='line'>│ ├── pre-rebase.sample
</span><span class='line'>│ └── update.sample
</span><span class='line'>├── info
</span><span class='line'>│ └── exclude
</span><span class='line'>├── objects
</span><span class='line'>│ ├── info
</span><span class='line'>│ └── pack
</span><span class='line'>└── refs
</span><span class='line'> ├── heads
</span><span class='line'> └── tags
</span></code></pre></td></tr></table></div></figure>
<h3>设置忽略文件</h3>
<ul>
<li>新建<code>.gitignore</code>文件并提交。</li>
<li>修改<code>.git/info/exclude</code>文件,支持正则表达式,例如<code>*.[oa]</code>等价于 <code>*.o</code> 和 <code>*.a</code>。这个方法只适用于你个人。</li>
</ul>
<h2>日常操作</h2>
<h3>添加文件到缓存区</h3>
<ul>
<li>添加个别文件。<code>git add somefile1 somefile2</code></li>
<li>添加本目录所有txt文件。<code>git add *.txt</code></li>
<li><code>递归</code>添加所有文件,不包括空目录。<code>git add .</code></li>
</ul>
<h3>从缓存区删除文件</h3>
<p>用法跟rm一样,<code>git rm --cached</code>。</p>
<ul>
<li>删除单个文件。<code>git rm --cached somefile</code></li>
<li>递归删除。<code>git rm --cached -r .</code></li>
</ul>
<h3>查看当前缓存区的情况</h3>
<p>当前缓存区的情况是<code>注释</code>掉的,这也正常嘛,还没正式提交。<code>git status</code>是查看当前缓存区(index)和HEAD之间的差异。</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> status
</span></code></pre></td></tr></table></div></figure>
<p>例如下面的例子就是说明:当前缓存区比HEAD要多一个文件<code>c.txt</code></p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span><span class="nb">git</span> status
</span><span class='line'><span class="c"># On branch master</span>
</span><span class='line'><span class="c"># Changes to be committed:</span>
</span><span class='line'><span class="c"># (use "git reset HEAD <file>..." to unstage)</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># new file: c.txt</span>
</span><span class='line'><span class="c">#</span>
</span></code></pre></td></tr></table></div></figure>
<h3>从HEAD签出文件</h3>