forked from progit-ja/progit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
progit.ja.html
8146 lines (5570 loc) · 699 KB
/
progit.ja.html
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
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Pro Git - professional version control</title></head><body><h1>使い始める</h1>
<p>この章は、Gitを使い始めることに関してになります。まずはバージョン管理システムの背景に触れ、その後にGitをあなたのシステムで動かす方法、そしてGitで作業を始めるための設定方法について説明します。この章を読み終えるころには、なぜGitが広まっているか、なぜGitを使うべきなのか、それをするための準備が全て整っているだろうということを、あなたはきっと理解しているでしょう。</p>
<h2>バージョン管理に関して</h2>
<p>バージョン管理とは何でしょうか、また、なぜそれを気にする必要があるのでしょうか?
バージョン管理とは、変更を一つのファイル、もしくは時間を通じたファイルの集合に記録するシステムで、そのため後で特定バージョンを呼び出すことができます。現実にはコンピューター上のほとんどあらゆるファイルのタイプでバージョン管理を行なう事ができますが、本書の中の例では、バージョン管理されるファイルとして、ソフトウェアのソースコードを利用します。</p>
<p>もしあなたが、グラフィックス・デザイナー、もしくはウェブ・デザイナーであって、(あなたが最も確実に望んでいるであろう)画像もしくはレイアウトの全てのバージョンを管理したいのであれば、バージョン管理システム(VCS)はとても賢く利用できるものです。VCSを使ってできることとしては、ファイルを以前の状態まで戻したり、プロジェクト丸ごとを以前の状態に戻したり、過去の変更を見直したり、誰が最後に問題を引き起こすだろう何かを修正したか、誰が、何時、課題を導入したかを確認したりといった様々なことがあります。VCSを使うということはまた、一般的に、何かをもみくちゃにするか、ファイルを失うとしても、簡単に復活させることができることを意味します。加えて、とても僅かな諸経費で、それら全てを得ることができます。</p>
<h3>ローカル・バージョン管理システム</h3>
<p>多くの人々の選り抜きのバージョン管理手法は、他のディレクトリ(もし彼らが賢いのであれば、恐らく日時が書かれたディレクトリ)にファイルをコピーするというものです。このアプローチは、とても単純なためにすごく一般的ですが、信じられない間違い傾向もあります。どのディレクトリにいるのか忘れやすいですし、偶然に間違ったファイルに書き込んだり、意図しないファイルに上書きしたりします。</p>
<p>この問題を扱うため、大昔にプログラマは、バージョン管理下で全ての変更をファイルに保持するシンプルなデータベースを持つ、ローカルなバージョン管理システムを開発しました(図1-1参照)。</p>
<p><img src="figures/1.1.png" title="1.1 ローカル・バージョン管理図解" alt="1.1 ローカル・バージョン管理図解" /></p>
<p>もっとも有名なVCSツールの一つが、RCSと呼ばれるシステムでした。今日でも依然として多くのコンピューターに入っています。人気のMac OS Xオペレーティング・システムさえも、開発者ツールをインストールしたときは、rcsコマンドを含みます。このツールは基本的に、ディスク上に特殊フォーマットで、一つのリビジョンからもう一つのリビジョンへのパッチ(これはファイル間の差分です)の集合を保持することで稼動します。そういうわけで、全てのパッチを積み上げることで、いつかは、あらゆる時点の、あらゆるファイルのように見えるものを再生成する事ができます。</p>
<h3>集中バージョン管理システム</h3>
<p>次に人々が遭遇した大きな問題は、他のシステムの開発者と共同制作をする必要があることです。この問題に対処するために、集中バージョン管理システム(CVCSs)が開発されました。CVSやSubversion、Perforceのような、これらのシステムは、全てのバージョン管理されたファイルと、その中央の場所からファイルをチェック・アウトする多数のクライアントを含む単一のサーバーを持ちます。長年の間、これはバージョン管理の標準となって来ました(図1-2参照)。</p>
<p><img src="figures/1.2.png" title="1.2 集中バージョン管理図解" alt="1.2 集中バージョン管理図解" /></p>
<p>この構成は、特にローカルVCSと比較して、多くの利点を提供します。例えば、全ての人は、プロジェクトのその他の全ての人々が何をしているのか、一定の程度は知っています。管理者は、誰が何をできるのかについて、きめ細かい統制手段を持ちます。このため、一つのCVCSを管理するということは、全てのクライアントのローカル・データベースを取り扱うより、はるかに容易です。</p>
<p>しかしながら、この構成はまた、深刻な不利益も持ちます。もっとも明白なのは、中央サーバーで発生する単一障害点です。もし、そのサーバーが1時間の間停止すると、その1時間の間は誰も全く、共同作業や、彼らが作業を進めている全てに対してバージョン変更の保存をすることができなくなります。もし中央データベースがのっているハードディスクが破損し、適切なバックアップが保持されていないとすると、人々が偶然にローカル・マシンに持っていた幾らかの単一スナップショット(訳者注:ある時点のファイル、ディレクトリなどの編集対象の状態)を除いた、プロジェクト全体の履歴を失うことになります。ローカルVCSシステムも、これと同じ問題に悩まされます。つまり、単一の場所にプロジェクトの全体の履歴を持っているときはいつでも、全てを失う事を覚悟することになります。</p>
<h3>分散バージョン管理システム</h3>
<p>ここから分散バージョン管理システム(DVCSs)に入ります。DVCS(Git、Mercurial、Bazaar、Darcsのようなもの)では、クライアントはファイルの最新スナップショットをチェックアウト(訳者注:バージョン管理システムから、作業ディレクトリにファイルやディレクトリをコピーすること)するだけではありません。リポジトリ(訳者注:バージョン管理の対象になるファイル、ディレクトリ、更新履歴などの一群)全体をミラーリングします。故にどのサーバーが故障したとして、故障したサーバーを介してそれらのDVCSが共同作業をしていたとしても、あらゆるクライアント・リポジトリは修復のためにサーバーにコピーして戻す事ができます。そのサーバーを介してコラボレーションしていたシステムは, どれか一つのクライアントのリポジトリからサーバー復旧の為バックアップをコピーすることができます. 全てのチェックアウトは、実は全データの完全バックアップなのです(図1-3を参照)。</p>
<p><img src="figures/1.3.png" title="1.3 分散バージョン管理システムの図解" alt="1.3 分散バージョン管理システムの図解" /></p>
<p>そのうえ、これらのDVCSの多くは、 連携する複数のリモート・リポジトリを扱いながら大変よく機能するため、同一のプロジェクト内において、同時に異なった方法で、異なる人々のグループと共同作業が可能です。このことは、集中システムでは不可能であった階層モデルのような、幾つかの様式のワークフローを始めることを許します。</p>
<h2>Git略史</h2>
<p>人生における多くの素晴らしい出来事のように、Gitはわずかな創造的破壊と熱烈な論争から始まりました。Linuxカーネルは、非常に巨大な範囲のオープンソース・ソフトウェア・プロジェクトの一つです。Linuxカーネル保守の大部分の期間(1991-2002)の間は、このソフトウェアに対する変更は、パッチとアーカイブしたファイルとして次々にまわされていました。2002年に、Linuxカーネル・プロジェクトはプロプライエタリのDVCSであるBitKeeperを使い始めました。</p>
<p>2005年に、Linuxカーネルを開発していたコミュニティと、BitKeeperを開発していた営利企業との間の協力関係が崩壊して、課金無しの状態が取り消されました。これは、Linux開発コミュニティ(と、特にLinuxの作者のLinus Torvalds)に、BitKeeperを利用している間に学んだ幾つかの教訓を元に、彼ら独自のツールの開発を促しました。新しいシステムの目標の幾つかは、次の通りでした:</p>
<ul>
<li>スピード</li>
<li>シンプルな設計</li>
<li>ノンリニア開発(数千の並列ブランチ)への強力なサポート</li>
<li>完全な分散</li>
<li>Linux カーネルのような大規模プロジェクトを(スピードとデータサイズで)効率的に取り扱い可能</li>
</ul>
<p>2005年のその誕生から、Gitは使いやすく発展・成熟してきており、さらにその初期の品質を維持しています。とても高速で、巨大プロジェクトではとても効率的で、ノンリニア開発のためのすごい分岐システム(branching system)を備えています(第3章参照)。</p>
<h2>Gitの基本</h2>
<p>では、要するにGitとは何なのでしょうか。これは、Gitを吸収するには重要な節です。なぜならば、もしGitが何かを理解し、Gitがどうやって稼動しているかの根本を理解できれば、Gitを効果的に使う事が恐らくとても容易になるからです。
Gitを学ぶときは、SubversionやPerforceのような他のVCSsに関してあなたが恐らく知っていることは、意識しないでください。このツールを使うときに、ちょっとした混乱を回避することに役立ちます。Gitは、ユーザー・インターフェイスがとてもよく似ているのにも関わらず、それら他のシステムとは大きく異なって、情報を格納して取り扱います(訳者注:「取り扱う」の部分はthinksなので、「見なします」と訳す方が原語に近い)。これらの相違を理解する事は、Gitを扱っている間の混乱を、防いでくれるでしょう。</p>
<h3>スナップショットで、差分ではない</h3>
<p>Gitと他のVCS (Subversionとその類を含む)の主要な相違は、Gitのデータについての考え方です。概念的には、他のシステムのほとんどは、情報をファイルを基本とした変更のリストとして格納します。これらのシステム(CVS、Subversion、Perforce、Bazaar等々)は、図1-4に描かれているように、システムが保持しているファイルの集合と、時間を通じてそれぞれのファイルに加えられた変更の情報を考えます。</p>
<p><img src="figures/1.4.png" title="1.4 他のシステムは、データをそれぞれのファイルの基本バージョンへの変更として格納する傾向があります。" alt="1.4 他のシステムは、データをそれぞれのファイルの基本バージョンへの変更として格納する傾向があります。" /></p>
<p>Gitは、この方法ではデータを考えたり、格納しません。代わりに、Gitはデータをミニ・ファイルシステムのスナップショットの集合のように考えます。Gitで全てのコミット(訳注:commitとは変更を記録・保存するGitの操作。詳細は後の章を参照)をするとき、もしくはプロジェクトの状態を保存するとき、Gitは基本的に、その時の全てのファイルの状態のスナップショットを撮り(訳者注:意訳)、そのスナップショットへの参照を格納するのです。効率化のため、ファイルに変更が無い場合は、Gitはファイルを再格納せず、既に格納してある、以前の同一のファイルへのリンクを格納します。Gitは、むしろデータを図1-5のように考えます。</p>
<p><img src="figures/1.5.png" title="1.5 Gitは時間を通じたプロジェクトのスナップショットとしてデータを格納します。" alt="1.5 Gitは時間を通じたプロジェクトのスナップショットとしてデータを格納します。" /></p>
<p>これが、Gitと類似の全ての他のVCSsとの間の重要な違いです。ほとんどの他のシステムが以前の世代から真似してきた、ほとんど全てのバージョン管理のやり方(訳者注:aspectを意訳)を、Gitに見直させます。これは、Gitを、単純にVCSと言うより、その上に組み込まれた幾つかの途方も無くパワフルなツールを備えたミニ・ファイルシステムにしています。このやり方でデータを考えることで得られる利益の幾つかを、第3章のGit branchingを扱ったときに探求します。</p>
<h3>ほとんど全ての操作がローカル</h3>
<p>Gitのほとんどの操作は、ローカル・ファイルと操作する資源だけ必要とします。大体はネットワークの他のコンピューターからの情報は必要ではありません。ほとんどの操作がネットワーク遅延損失を伴うCVCSに慣れているのであれば、もっさりとしたCVCSに慣れているのであれば、このGitの速度は神業のように感じるでしょう(訳者注:直訳は「このGitの側面はスピードの神様がこの世のものとは思えない力でGitを祝福したと考えさせるでしょう」)。プロジェクトの履歴は丸ごとすぐそこのローカル・ディスクに保持しているので、大概の操作はほぼ瞬時のように見えます。</p>
<p>例えば、プロジェクトの履歴を閲覧するために、Gitはサーバーに履歴を取得しに行って表示する必要がありません。直接にローカル・データベースからそれを読むだけです。これは、プロジェクトの履歴をほとんど即座に知るということです。もし、あるファイルの現在のバージョンと、そのファイルの1ヶ月前の間に導入された変更点を知りたいのであれば、Gitは、遠隔のサーバーに差分を計算するように問い合わせたり、ローカルで差分を計算するために遠隔サーバーからファイルの古いバージョンを持ってくる代わりに、1か月前のファイルを調べてローカルで差分の計算を行なえます。</p>
<p>これはまた、オフラインであるか、VPNから切り離されていたとしても、出来ない事は非常に少ないことを意味します。もし、飛行機もしくは列車に乗ってちょっとした仕事をしたいとしても、アップロードするためにネットワーク接続し始めるまで、楽しくコミットできます。もし、帰宅してVPNクライアントを適切に作動させられないとしても、さらに作業ができます。多くの他のシステムでは、それらを行なう事は、不可能であるか苦痛です。例えばPerforceにおいては、サーバーに接続できないときは、多くの事が行なえません。SubversionとCVSにおいては、ファイルの編集はできますが、データベースに変更をコミットできません(なぜならば、データベースがオフラインだからです)。このことは巨大な問題に思えないでしょうが、実に大きな違いを生じうることに驚くでしょう。</p>
<h3>Gitは完全性を持つ</h3>
<p>Gitの全てのものは、格納される前にチェックサムが取られ、その後、そのチェックサムで照合されます。これは、Gitがそれに関して感知することなしに、あらゆるファイルの内容を変更することが不可能であることを意味します。この機能は、Gitの最下層に組み込まれ、またGitの哲学に不可欠です。Gitがそれを感知できない状態で、転送中に情報を失う、もしくは壊れたファイルを取得することはありません。</p>
<p>Gitがチェックサム生成に用いる機構は、SHA-1ハッシュと呼ばれます。これは、16進数の文字(0-9とa-f)で構成された40文字の文字列で、ファイルの内容もしくはGit内のディレクトリ構造を元に計算されます。SHA-1ハッシュは、このようなもののように見えます:</p>
<pre><code>24b9da6552252987aa493b52f8696cd6d3b00373
</code></pre>
<p>Gitはハッシュ値を大変よく利用するので、Gitのいたるところで、これらのハッシュ値を見ることでしょう。事実、Gitはファイル名ではなく、ファイル内容のハッシュ値によってアドレスが呼び出されるGitデータベースの中に全てを格納しています。</p>
<h3>Gitは通常はデータを追加するだけ</h3>
<p>Gitで行動するとき、ほとんど全てはGitデータベースにデータを追加するだけです。システムにいかなる方法でも、UNDO不可能なこと、もしくはデータを消させることをさせるのは、大変難しいです。あらゆるVCSと同様に、まだコミットしていない変更は失ったり、台無しにできたりします。しかし、スナップショットをGitにコミットした後は、特にもし定期的にデータベースを他のリポジトリにプッシュ(訳注:pushはGitで管理するあるリポジトリのデータを、他のリポジトリに転送する操作。詳細は後の章を参照)していれば、変更を失うことは大変難しくなります。</p>
<p>激しく物事をもみくちゃにする危険なしに試行錯誤を行なえるため、これはGitの利用を喜びに変えます。Gitがデータをどのように格納しているのかと失われたように思えるデータをどうやって回復できるのかについての、より詳細な解説に関しては、第9章を参照してください。</p>
<h3>三つの状態</h3>
<p>今、注意してください。もし学習プロセスの残りをスムーズに進めたいのであれば、これはGitに関して覚えておく主要な事です。Gitは、ファイルが帰属する、コミット済、修正済、ステージ済の、三つの主要な状態を持ちます。コミット済は、ローカル・データベースにデータが安全に格納されていることを意味します。修正済は、ファイルに変更を加えていますが、データベースにそれがまだコミットされていないことを意味します。ステージ済は、次のスナップショットのコミットに加えるために、現在のバージョンの修正されたファイルに印をつけている状態を意味します。</p>
<p>このことは、Gitプロジェクト(訳者注:ディレクトリ内)の、Gitディレクトリ、作業ディレクトリ、ステージング・エリアの三つの主要な部分(訳者注:の理解)に導きます。</p>
<p><img src="figures/1.6.png" title="1.6 作業ディレクトリ、ステージング・エリア、Gitディレクトリ" alt="1.6 作業ディレクトリ、ステージング・エリア、Gitディレクトリ" /></p>
<p>Gitディレクトリは、プロジェクトのためのメタデータ(訳者注:Gitが管理するファイルやディレクトリなどのオブジェクトの要約)とオブジェクトのデータベースがあるところです。これは、Gitの最も重要な部分で、他のコンピューターからリポジトリをクローン(訳者注:コピー元の情報を記録した状態で、Gitリポジトリをコピーすること)したときに、コピーされるものです。</p>
<p>作業ディレクトリは、プロジェクトの一つのバージョンの単一チェックアウトです。これらのファイルはGitディレクトリの圧縮されたデータベースから引き出されて、利用するか修正するためにディスクに配置されます。</p>
<p>ステージング・エリアは、普通はGitディレクトリに含まれる、次のコミットに何が含まれるかに関しての情報を蓄えた一つの単純なファイルです。ときどきインデックスのように引き合いにだされますが、ステージング・エリアとして呼ばれることが基本になりつつあります。</p>
<p>基本的なGitのワークフローは、このような風に進みます:</p>
<ol>
<li>作業ディレクトリのファイルを修正します。</li>
<li>修正されたファイルのスナップショットをステージング・エリアに追加して、ファイルをステージします。</li>
<li>コミットします。(訳者注:Gitでは)これは、ステージング・エリアにあるファイルを取得し、永久不変に保持するスナップショットとしてGitディレクトリに格納することです。</li>
</ol>
<p>もしファイルの特定のバージョンがGitディレクトリの中にあるとしたら、コミット済だと見なされます。もし修正されていて、ステージング・エリアに加えられていれば、ステージ済です。そして、チェックアウトされてから変更されましたが、ステージされていないとするなら、修正済です。第2章では、これらの状態と、どうやってこれらを利用をするか、もしくは完全にステージ化部分を省略するかに関してより詳しく学習します。</p>
<h2>Gitのインストール</h2>
<p>少しGitを使う事に入りましょう。何よりも最初に、Gitをインストールしなければなりません。幾つもの経路で入手することができ、主要な二つの方法のうちの一つはソースからインストールすることで、もう一つはプラットフォームに応じて存在するパッケージをインストールすることです。</p>
<h3>ソースからのインストール</h3>
<p>もし可能であれば、もっとも最新のバージョンを入手できるので、一般的にソースからGitをインストールするのが便利です。Gitのそれぞれのバージョンは、実用的なユーザー・インターフェイスの向上が含まれており、もしソースからソフトウェアをコンパイルすることに違和感を感じないのであれば、最新バージョンを入手することは、大抵は最も良い経路になります。また、多くのLinuxディストリビューションがとても古いパッケージを収録している事は良くあることであり、最新のディストリビューションを使っているか、バックポート(訳者注:最新のパッケージを古いディストリビューションで使えるようにする事)をしていない限りは、ソースからのインストールがベストな選択になるでしょう。</p>
<p>Gitをインストールするためには、Gitが依存するライブラリーである、curl、zlib、openssl、expat、libiconvを入手する必要があります。例えば、もし(Fedoraなどで)yumか(Debianベースのシステムなどで)apt-getが入ったシステムを使っているのであれば、これらのコマンドの一つを依存対象の全てをインストールするのに使う事ができます:</p>
<pre><code>$ yum install curl-devel expat-devel gettext-devel \
openssl-devel zlib-devel
$ apt-get install libcurl4-gnutls-dev libexpat1-dev gettext \
libz-dev libssl-dev
</code></pre>
<p>全ての必要な依存対象を持っているのであれば、先に進んでGitのウェブサイトから最新版のスナップショットを持ってくる事ができます:</p>
<pre><code>http://git-scm.com/download
</code></pre>
<p>そして、コンパイルしてインストールします:</p>
<pre><code>$ tar -zxf git-1.7.2.2.tar.gz
$ cd git-1.7.2.2
$ make prefix=/usr/local all
$ sudo make prefix=/usr/local install
</code></pre>
<p>また、Gitのインストール後、アップデートでGitを通して最新版のGitを得ることができます。</p>
<pre><code>$ git clone git://git.kernel.org/pub/scm/git/git.git
</code></pre>
<h3>Linuxにインストール</h3>
<p>バイナリのインストーラーを通じてLinux上にGitをインストールしたいのであれば、大抵はディストリビューションに付属する基本的なパッケージ・マネジメント・ツールを使って、それを行なう事ができます。もしFedoraを使っているのであれば、yumを使う事が出来ます:</p>
<pre><code>$ yum install git-core
</code></pre>
<p>もしくは、もしUbuntuのようなDebianベースのディストリュビューションを使っているのであれば、apt-getをやってみましょう:</p>
<pre><code>$ apt-get install git
</code></pre>
<h3>Macにインストール</h3>
<p>MacにGitをインストールするには2つの簡単な方法があります。もっとも簡単な方法は、グラフィカルなGitインストーラーを使うことで、このGitインストーラーはSourceForgeのページ(図1-7参照)からダウンロードすることができます:</p>
<pre><code>http://sourceforge.net/projects/git-osx-installer/
</code></pre>
<p><img src="figures/1.7.png" title="1.7 Git OS X installer" alt="1.7 Git OS X installer" /></p>
<p>もう一つの主要な方法は、MacPorts (<code>http://www.macports.org</code>) からGitをインストールすることです。MacPortsをインストールした状態であれば、Gitを以下のようにインストールできます。</p>
<pre><code>$ sudo port install git-core +svn +doc +bash_completion +gitweb
</code></pre>
<p>全てのvariantsを追加する必要はありませんが、SubversionのリポジトリでGitを使う必要がまだあるなら、恐らく+svnを含めないといけないでしょう(第8章参照)。</p>
<h3>Windowsにインストール</h3>
<p>WindowsにGitをインストールするのはとても簡単です。msysGitプロジェクトは、より簡単なインストール手続きの一つを備えています。GitHubのページから、単純にインストーラーのexeファイルをダウンロードをし、実行してください:</p>
<pre><code>http://msysgit.github.com/
</code></pre>
<p>インストール後、コマンドライン版(後で役に立つSSHクライアントを含む)とスタンダードGUI版の両方を使う事ができます。</p>
<p>Windows利用時の注意点: この本で紹介されている複雑なコマンドを使えるので、GitはmsysGit shell(Unixスタイル)で使うようにしましょう。Windowsのシェル/コマンドラインコンソールを使わざるを得ない場合、空白を含むパラメーターを囲むための記号はダブルクオーテーション(シングルクォーテーションは使えない)を使用する必要があります。同様に、サーカムフレックス記号(^)が行末に来る場合はダブルクオーテーションで囲まなければなりません。同記号はWindowsにおいて「次行に続く」を意味する記号だからです。</p>
<h2>最初のGitの構成</h2>
<p>今や、Gitがシステムにあります。Git環境をカスタマイズするためにしたい事が少しはあることでしょう。アップグレードの度についてまわるので、たった一度でそれらを終わらすべきでしょう。またそれらは、またコマンドを実行することによっていつでも変更することができます。</p>
<p>Gitには、<code>git config</code>と呼ばれるツールが付属します。これで、どのようにGitが見えて機能するかの全ての面を制御できる設定変数を取得し、設定することができます。これらの変数は三つの異なる場所に格納されうります:</p>
<ul>
<li><code>/etc/gitconfig</code> file: システム上の全てのユーザーと全てのリポジトリに対する設定値を保持します。もし<code>--system</code>オプションを<code>git config</code>に指定すると、明確にこのファイルに読み書きを行ないます。</li>
<li><code>~/.gitconfig</code> file: 特定のユーザーに対する設定値を保持します. <code>--global</code>オプションを指定することで、Gitに、明確にこのファイルに読み書きを行なわせることができます。</li>
<li>現在使っている、あらゆるリポジトリのGitディレクトリの設定ファイル(<code>.git/config</code>のことです): 特定の単一リポジトリに対する設定値を保持します。それぞれのレベルの値は以前のレベルの値を上書きするため、<code>.git/config</code>の中の設定値は<code>/etc/gitconfig</code>の設定値に優先されます。</li>
</ul>
<p>Windows環境下では、Gitは<code>$HOME</code>ディレクトリ(環境変数<code>USERPROFILE</code>で指定)の中の<code>.gitconfig</code>ファイルを検索に行きます。<code>$HOME</code>ディレクトリはほとんどの場合 <code>C:\Documents and Settings\$USER</code> か <code>C:\Users\$USER</code> のいずれかです($USERは環境変数<code>USERNAME</code>で指定)。また、インストーラー時にWindowsシステムにGitをインストールすると決めたところにある、MSysのルートとの相対位置であったとしても、 /etc/gitconfigも見に行きます。</p>
<h3>個人の識別情報</h3>
<p>Gitをインストールしたときに最初にすべきことは、ユーザー名とE-mailアドレスを設定することです。全てのGitのコミットはこの情報を用いるため、これは重要で、次々とまわすコミットに永続的に焼き付けられます:</p>
<pre><code>$ git config --global user.name "John Doe"
$ git config --global user.email [email protected]
</code></pre>
<p>また、もし<code>--global</code>オプションを指定するのであれば、Gitはその後、そのシステム上で行なう(訳者注:あるユーザーの)全ての操作に対して常にこの情報を使うようになるため、この操作を行なう必要はたった一度だけです。もし、違う名前とE-mailアドレスを特定のプロジェクトで上書きしたいのであれば、そのプロジェクトの(訳者注:Gitディレクトリの)中で、<code>--global</code>オプション無しでこのコマンドを実行することができます。</p>
<h3>エディター</h3>
<p>今や、個人の識別情報が設定され、Gitがメッセージのタイプをさせる必要があるときに使う、標準のテキストエディターを設定できます。標準では、Gitはシステムのデフォルト・エディターを使います。これは大抵の場合、ViかVimです。Emacsのような違うテキスト・エディターを使いたい場合は、次のようにします:</p>
<pre><code>$ git config --global core.editor emacs
</code></pre>
<h3>diffツール</h3>
<p>設定したいと思われる、その他の便利なオプションは、マージ(訳者注:複数のリポジトリを併合すること)時の衝突を解決するために使う、標準のdiffツールです。vimdiffを使いたいとします:</p>
<pre><code>$ git config --global merge.tool vimdiff
</code></pre>
<p>Gitはkdiff3、tkdiff、meld、xxdiff、emerge、vimdiff、gvimdiff、ecmerge、opendiffを確かなマージ・ツールとして扱えます。カスタム・ツールもまた設定できますが、これをする事に関しての詳細な情報は第7章を参照してください。</p>
<h3>設定の確認</h3>
<p>設定を確認したい場合は、その時点でGitが見つけられる全ての設定を一覧するコマンドである<code>git config --list</code>を使う事ができます:</p>
<pre><code>$ git config --list
user.name=Scott Chacon
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...
</code></pre>
<p>Gitは異なったファイル(例えば<code>/etc/gitconfig</code>と<code>~/.gitconfig</code>)から同一のキーを読み込むため、同一のキーを1度以上見ることになるでしょう。この場合、Gitは見つけたそれぞれ同一のキーに対して最後の値を用います。</p>
<p>また、Gitに設定されている特定のキーの値を、<code>git config {key}</code>をタイプすることで確認することができます:</p>
<pre><code>$ git config user.name
Scott Chacon
</code></pre>
<h2>ヘルプを見る</h2>
<p>もし、Gitを使っている間は助けがいつも必要なら、あらゆるGitコマンドのヘルプのマニュアル・ページ(manpage)を参照する3種類の方法があります。</p>
<pre><code>$ git help <verb>
$ git <verb> --help
$ man git-<verb>
</code></pre>
<p>例えば、configコマンドのヘルプのmanpageを次のコマンドを走らせることで見ることができます。</p>
<pre><code>$ git help config
</code></pre>
<p>これらのコマンドは、オフラインのときでさえ、どこでも見る事ができるので、すばらしいです。
もしmanpageとこの本が十分でなく、人の助けが必要であれば、フリーノードIRCサーバー(irc.freenode.net)の<code>#git</code>もしくは<code>#github</code>チャンネルにアクセスしてみてください。これらのチャンネルはいつも、全員がGitに関してとても知識があり、よく助けてくれようとする数百人の人々でいっぱいです。</p>
<h2>まとめ</h2>
<p>Gitとは何か、どのように今まで使われてきた他のCVCSと異なるのかについて、基本的な理解ができたはずです。また、今や個人情報の設定ができた、システムに稼動するバージョンのGitがあるはずです。今や、本格的にGitの基本を学習するときです。</p>
<h1>Git の基本</h1>
<p>Git を使い始めるにあたってどれかひとつの章だけしか読めないとしたら、読むべきは本章です。この章では、あなたが実際に Git を使う際に必要となる基本コマンドをすべて取り上げています。本章を最後まで読めば、リポジトリの設定や初期化、ファイルの追跡、そして変更内容のステージやコミットなどができるようになるでしょう。また、Git で特定のファイル (あるいは特定のファイルパターン) を無視させる方法やミスを簡単に取り消す方法、プロジェクトの歴史や各コミットの変更内容を見る方法、リモートリポジトリとの間でのプッシュやプルを行う方法についても説明します。</p>
<h2>Git リポジトリの取得</h2>
<p>Git プロジェクトを取得するには、大きく二通りの方法があります。ひとつは既存のプロジェクトやディレクトリを Git にインポートする方法、そしてもうひとつは既存の Git リポジトリを別のサーバーからクローンする方法です。</p>
<h3>既存のディレクトリでのリポジトリの初期化</h3>
<p>既存のプロジェクトを Git で管理し始めるときは、そのプロジェクトのディレクトリに移動して次のように打ち込みます。</p>
<pre><code>$ git init
</code></pre>
<p>これを実行すると <code>.git</code> という名前の新しいサブディレクトリが作られ、リポジトリに必要なすべてのファイル (Git リポジトリのスケルトン) がその中に格納されます。この時点では、まだプロジェクト内のファイルは一切管理対象になっていません (今作った <code>.git</code> ディレクトリに実際のところどんなファイルが含まれているのかについての詳細な情報は、<em>第 9 章</em> を参照ください)。</p>
<p>空のディレクトリではなくすでに存在するファイルのバージョン管理を始めたい場合は、まずそのファイルを監視対象に追加してから最初のコミットをすることになります。この場合は、追加したいファイルについて <code>git add</code> コマンドを実行したあとでコミットを行います。</p>
<pre><code>$ git add *.c
$ git add README
$ git commit -m 'initial project version'
</code></pre>
<p>これが実際のところどういう意味なのかについては後で説明します。ひとまずこの時点で、監視対象のファイルを持つ Git リポジトリができあがり最初のコミットまで済んだことになります。</p>
<h3>既存のリポジトリのクローン</h3>
<p>既存の Git リポジトリ (何か協力したいと思っているプロジェクトなど) のコピーを取得したい場合に使うコマンドが、<code>git clone</code> です。Subversion などの他の VCS を使っている人なら「<code>checkout</code> じゃなくて <code>clone</code> なのか」と気になることでしょう。これは重要な違いです。Git は、サーバーが保持しているデータをほぼすべてコピーするのです。そのプロジェクトのすべてのファイルのすべての歴史が、<code>git clone</code> で手元にやってきます。実際、もし仮にサーバーのディスクが壊れてしまったとしても、どこかのクライアントに残っているクローンをサーバーに戻せばクローンした時点まで復元することができます (サーバーサイドのフックなど一部の情報は失われてしまいますが、これまでのバージョン管理履歴はすべてそこに残っています。<em>第 4 章</em> で詳しく説明します)。</p>
<p>リポジトリをクローンするには <code>git clone [url]</code> とします。たとえば、Ruby の Git ライブラリである Grit をクローンする場合は次のようになります。</p>
<pre><code>$ git clone git://github.com/schacon/grit.git
</code></pre>
<p>これは、まず <code>grit</code> というディレクトリを作成してその中で <code>.git</code> ディレクトリを初期化し、リポジトリのすべてのデータを引き出し、そして最新バージョンの作業コピーをチェックアウトします。新しくできた <code>grit</code> ディレクトリに入ると、プロジェクトのファイルをごらんいただけます。もし grit ではない別の名前のディレクトリにクローンしたいのなら、コマンドラインオプションでディレクトリ名を指定します。</p>
<pre><code>$ git clone git://github.com/schacon/grit.git mygrit
</code></pre>
<p>このコマンドは先ほどと同じ処理をしますが、ディレクトリ名は <code>mygrit</code> となります。</p>
<p>Git では、さまざまな転送プロトコルを使用することができます。先ほどの例では <code>git://</code> プロトコルを使用しましたが、<code>http(s)://</code> や <code>user@server:/path.git</code> といった形式を使うこともできます。これらは SSH プロトコルを使用します。<em>第 4 章</em> で、サーバー側で準備できるすべてのアクセス方式についての利点と欠点を説明します。</p>
<h2>変更内容のリポジトリへの記録</h2>
<p>これで、れっきとした Git リポジトリを準備して、そのプロジェクト内のファイルの作業コピーを取得することができました。次は、そのコピーに対して何らかの変更を行い、適当な時点で変更内容のスナップショットをリポジトリにコミットすることになります。</p>
<p>作業コピー内の各ファイルには <em>追跡されている(tracked)</em> ものと <em>追跡されてない(untracked)</em> ものの二通りがあることを知っておきましょう。<em>追跡されている</em> ファイルとは、直近のスナップショットに存在したファイルのことです。これらのファイルについては変更されていない(unmodified)」「変更されている(modified)」「ステージされている(staged)」の三つの状態があります。追跡されていないファイルは、そのどれでもありません。直近のスナップショットには存在せず、ステージングエリアにも存在しないファイルのことです。最初にプロジェクトをクローンした時点では、すべてのファイルは「追跡されている」かつ「変更されていない」状態となります。チェックアウトしただけで何も編集していない状態だからです。</p>
<p>ファイルを編集すると、Git はそれを「変更された」とみなします。直近のコミットの後で変更が加えられたからです。変更されたファイルを <em>ステージ</em> し、それをコミットする。この繰り返しです。ここまでの流れを図 2-1 にまとめました。</p>
<p><img src="figures/2.1.png" title="2.1 ファイルの状態の流れ" alt="2.1 ファイルの状態の流れ" /></p>
<h3>ファイルの状態の確認</h3>
<p>どのファイルがどの状態にあるのかを知るために主に使うツールが <code>git status</code> コマンドです。このコマンドをクローン直後に実行すると、このような結果となるでしょう。</p>
<pre><code>$ git status
On branch master
nothing to commit, working directory clean
</code></pre>
<p>これは、クリーンな作業コピーである (つまり、追跡されているファイルの中に変更されているものがない) ことを意味します。また、追跡されていないファイルも存在しません (もし追跡されていないファイルがあれば、Git はそれを表示します)。最後に、このコマンドを実行するとあなたが今どのブランチにいるのかを知ることができます。現時点では常に <code>master</code> となります。これはデフォルトであり、ここでは特に気にする必要はありません。ブランチについては次の章で詳しく説明します。</p>
<p>ではここで、新しいファイルをプロジェクトに追加してみましょう。シンプルに、<code>README</code> ファイルを追加してみます。それ以前に README ファイルがなかった場合、<code>git status</code> を実行すると次のように表示されます。</p>
<pre><code>$ vim README
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
README
nothing added to commit but untracked files present (use "git add" to track)
</code></pre>
<p>出力結果の “Untracked files” 欄に <code>README</code> ファイルがあることから、このファイルが追跡されていないということがわかります。これは、Git が「前回のスナップショット (コミット) にはこのファイルが存在しなかった」とみなしたということです。明示的に指示しない限り、Git はコミット時にこのファイルを含めることはありません。自動生成されたバイナリファイルなど、コミットしたくないファイルを間違えてコミットしてしまう心配はないということです。今回は README をコミットに含めたいわけですから、まずファイルを追跡対象に含めるようにしましょう。</p>
<h3>新しいファイルの追跡</h3>
<p>新しいファイルの追跡を開始するには <code>git add</code> コマンドを使用します。<code>README</code> ファイルの追跡を開始する場合はこのようになります。</p>
<pre><code>$ git add README
</code></pre>
<p>再び status コマンドを実行すると、<code>README</code> ファイルが追跡対象となり、ステージされていることがわかるでしょう。</p>
<pre><code>$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
</code></pre>
<p>ステージされていると判断できるのは、“Changes to be committed” 欄に表示されているからです。ここでコミットを行うと、<code>git add</code> した時点の状態のファイルがスナップショットとして歴史に書き込まれます。先ほど <code>git init</code> をしたときに、ディレクトリ内のファイルを追跡するためにその後 <code>git add (ファイル)</code> としたことを思い出すことでしょう。<code>git add</code> コマンドには、ファイルあるいはディレクトリのパスを指定します。ディレクトリを指定した場合は、そのディレクトリ以下にあるすべてのファイルを再帰的に追加します。</p>
<h3>変更したファイルのステージング</h3>
<p>すでに追跡対象となっているファイルを変更してみましょう。たとえば、すでに追跡対象となっているファイル <code>benchmarks.rb</code> を変更して <code>status</code> コマンドを実行すると、結果はこのようになります。</p>
<pre><code>$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: benchmarks.rb
</code></pre>
<p><code>benchmarks.rb</code> ファイルは “Changes not staged for commit” という欄に表示されます。これは、追跡対象のファイルが作業ディレクトリ内で変更されたけれどもまだステージされていないという意味です。ステージするには <code>git add</code> コマンドを実行します (このコマンドにはいろんな意味合いがあり、新しいファイルの追跡開始・ファイルのステージング・マージ時に衝突が発生したファイルに対する「解決済み」マーク付けなどで使用します)。では、<code>git add</code> で <code>benchmarks.rb</code> をステージしてもういちど <code>git status</code> を実行してみましょう。</p>
<pre><code>$ git add benchmarks.rb
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
modified: benchmarks.rb
</code></pre>
<p>両方のファイルがステージされました。これで、次回のコミットに両方のファイルが含まれるようになります。ここで、さらに <code>benchmarks.rb</code> にちょっとした変更を加えてからコミットしたくなったとしましょう。ファイルを開いて変更を終え、コミットの準備が整いました。しかし、<code>git status</code> を実行してみると何か変です。</p>
<pre><code>$ vim benchmarks.rb
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
modified: benchmarks.rb
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: benchmarks.rb
</code></pre>
<p>これはどういうことでしょう? <code>benchmarks.rb</code> が、ステージされているほうにもステージされていないほうにも登場しています。こんなことってありえるんでしょうか? 要するに、Git は「<code>git add</code> コマンドを実行した時点の状態のファイル」をステージするということです。ここでコミットをすると、実際にコミットされるのは <code>git add</code> を実行した時点の <code>benchmarks.rb</code> であり、<code>git commit</code> した時点の作業ディレクトリにある内容とは違うものになります。<code>git add</code> した後にファイルを変更した場合に、最新版のファイルをステージしなおすにはもう一度 <code>git add</code> を実行します。</p>
<pre><code>$ git add benchmarks.rb
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
modified: benchmarks.rb
</code></pre>
<h3>ファイルの無視</h3>
<p>ある種のファイルについては、Git で自動的に追加してほしくないしそもそも「追跡されていない」と表示されるのも気になる。そんなことがよくあります。たとえば、ログファイルやビルドシステムが生成するファイルなどの自動生成されるファイルがそれにあたるでしょう。そんな場合は、無視させたいファイルのパターンを並べた <code>.gitignore</code> というファイルを作成します。<code>.gitignore</code> ファイルは、たとえばこのようになります。</p>
<pre><code>$ cat .gitignore
*.[oa]
*~
</code></pre>
<p>最初の行は <code>.o</code> あるいは <code>.a</code> で終わる名前のファイル (コードをビルドする際にできるであろうオブジェクトファイルとアーカイブファイル) を無視するよう Git に伝えています。次の行で Git に無視させているのは、チルダ (<code>~</code>) で終わる名前のファイルです。Emacs をはじめとする多くのエディタが、この形式の一時ファイルを作成します。これ以外には、たとえば <code>log</code>、<code>tmp</code>、<code>pid</code> といった名前のディレクトリや自動生成されるドキュメントなどもここに含めることになるでしょう。実際に作業を始める前に <code>.gitignore</code> ファイルを準備しておくことをお勧めします。そうすれば、予期せぬファイルを間違って Git リポジトリにコミットしてしまう事故を防げます。</p>
<p><code>.gitignore</code> ファイルに記述するパターンの規則は、次のようになります。</p>
<ul>
<li>空行あるいは <code>#</code> で始まる行は無視される</li>
<li>標準の glob パターンを使用可能</li>
<li>ディレクトリを指定するには、パターンの最後にスラッシュ (<code>/</code>) をつける</li>
<li>パターンを逆転させるには、最初に感嘆符 (<code>!</code>) をつける</li>
</ul>
<p>glob パターンとは、シェルで用いる簡易正規表現のようなものです。アスタリスク (<code>*</code>) は、ゼロ個以上の文字にマッチします。<code>[abc]</code> は、角括弧内の任意の文字 (この場合は <code>a</code>、<code>b</code> あるいは <code>c</code>) にマッチします。疑問符 (<code>?</code>) は一文字にマッチします。また、ハイフン区切りの文字を角括弧で囲んだ形式 (<code>[0-9]</code>) は、ふたつの文字の間の任意の文字 (この場合は 0 から 9 までの間の文字) にマッチします。</p>
<p>では、<code>.gitignore</code> ファイルの例をもうひとつ見てみましょう。</p>
<pre><code># コメント。これは無視されます
# .a ファイルは無視
*.a
# しかし、lib.a ファイルだけは .a であっても追跡対象とします
!lib.a
# ルートディレクトリの TODO ファイルだけを無視し、サブディレクトリの TODO は無視しません
/TODO
# build/ ディレクトリのすべてのファイルを無視します
build/
# doc/notes.txt は無視しますが、doc/server/arch.txt は無視しません
doc/*.txt
# doc/ ディレクトリの .txt ファイル全てを無視します
doc/**/*.txt
</code></pre>
<p><code>**/</code> 形式は 1.8.2 以降のGitで利用可能です。</p>
<h3>ステージされている変更 / されていない変更の閲覧</h3>
<p><code>git status</code> コマンドだけではよくわからない (どのファイルが変更されたのかだけではなく、実際にどのように変わったのかが知りたい) という場合は <code>git diff</code> コマンドを使用します。<code>git diff</code> コマンドについては後で詳しく解説します。おそらく、最もよく使う場面としては次の二つの問いに答えるときになるでしょう。「変更したけどまだステージしていない変更は?」「コミット対象としてステージした変更は?」もちろん <code>git status</code> でもこれらの質問に対するおおまかな答えは得られますが、<code>git diff</code> の場合は追加したり削除したりした正確な行をパッチ形式で表示します。</p>
<p>先ほどの続きで、ふたたび <code>README</code> ファイルを編集してステージし、一方 <code>benchmarks.rb</code> ファイルは編集だけしてステージしない状態にあると仮定しましょう。ここで <code>status</code> コマンドを実行すると、次のような結果となります。</p>
<pre><code>$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: benchmarks.rb
</code></pre>
<p>変更したけれどもまだステージしていない内容を見るには、引数なしで <code>git diff</code> を実行します。</p>
<pre><code>$ git diff
diff --git a/benchmarks.rb b/benchmarks.rb
index 3cb747f..da65585 100644
--- a/benchmarks.rb
+++ b/benchmarks.rb
@@ -36,6 +36,10 @@ def main
@commit.parents[0].parents[0].parents[0]
end
+ run_code(x, 'commits 1') do
+ git.commits.size
+ end
+
run_code(x, 'commits 2') do
log = git.commits('master', 15)
log.size
</code></pre>
<p>このコマンドは、作業ディレクトリの内容とステージングエリアの内容を比較します。この結果を見れば、あなたが変更した内容のうちまだステージされていないものを知ることができます。</p>
<p>次のコミットに含めるべくステージされた内容を知りたい場合は、<code>git diff --cached</code> を使用します (Git バージョン 1.6.1 以降では <code>git diff --staged</code> も使えます。こちらのほうが覚えやすいでしょう)。このコマンドは、ステージされている変更と直近のコミットの内容を比較します。</p>
<pre><code>$ git diff --cached
diff --git a/README b/README
new file mode 100644
index 0000000..03902a1
--- /dev/null
+++ b/README2
@@ -0,0 +1,5 @@
+grit
+ by Tom Preston-Werner, Chris Wanstrath
+ http://github.com/mojombo/grit
+
+Grit is a Ruby library for extracting information from a Git repository
</code></pre>
<p><code>git diff</code> 自体は、直近のコミット以降のすべての変更を表示するわけではないことに注意しましょう。あくまでもステージされていない変更だけの表示となります。これにはすこし戸惑うかもしれません。変更内容をすべてステージしてしまえば <code>git diff</code> は何も出力しなくなるわけですから。</p>
<p>もうひとつの例を見てみましょう。benchmarks.rb ファイルをいったんステージした後に編集してみましょう。<code>git diff</code> を使用すると、ステージされたファイルの変更とまだステージされていないファイルの変更を見ることができます。</p>
<pre><code>$ git add benchmarks.rb
$ echo '# test line' >> benchmarks.rb
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: benchmarks.rb
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: benchmarks.rb
</code></pre>
<p>ここで <code>git diff</code> を使うと、まだステージされていない内容を知ることができます。</p>
<pre><code>$ git diff
diff --git a/benchmarks.rb b/benchmarks.rb
index e445e28..86b2f7c 100644
--- a/benchmarks.rb
+++ b/benchmarks.rb
@@ -127,3 +127,4 @@ end
main()
##pp Grit::GitRuby.cache_client.stats
+# test line
</code></pre>
<p>そして <code>git diff --cached</code> を使うと、これまでにステージした内容を知ることができます。</p>
<pre><code>$ git diff --cached
diff --git a/benchmarks.rb b/benchmarks.rb
index 3cb747f..e445e28 100644
--- a/benchmarks.rb
+++ b/benchmarks.rb
@@ -36,6 +36,10 @@ def main
@commit.parents[0].parents[0].parents[0]
end
+ run_code(x, 'commits 1') do
+ git.commits.size
+ end
+
run_code(x, 'commits 2') do
log = git.commits('master', 15)
log.size
</code></pre>
<h3>変更のコミット</h3>
<p>ステージングエリアの準備ができたら、変更内容をコミットすることができます。コミットの対象となるのはステージされたものだけ、つまり追加したり変更したりしただけでまだ <code>git add</code> を実行していないファイルはコミットされないことを覚えておきましょう。そういったファイルは、変更されたままの状態でディスク上に残ります。今回の場合は、最後に <code>git status</code> を実行したときにすべてがステージされていることを確認しています。つまり、変更をコミットする準備ができた状態です。コミットするための最もシンプルな方法は <code>git commit</code> と打ち込むことです。</p>
<pre><code>$ git commit
</code></pre>
<p>これを実行すると、指定したエディタが立ち上がります (シェルの <code>$EDITOR</code> 環境変数で設定されているエディタ。通常は vim あるいは emacs でしょう。しかし、それ以外にも <em>第 1 章</em> で説明した <code>git config --global core.editor</code> コマンドでお好みのエディタを指定することもできます)。</p>
<p>エディタには次のようなテキストが表示されています (これは Vim の画面の例です)。</p>
<pre><code># Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# new file: README
# modified: benchmarks.rb
#
~
~
~
".git/COMMIT_EDITMSG" 10L, 283C
</code></pre>
<p>デフォルトのコミットメッセージとして、直近の <code>git status</code> コマンドの結果がコメントアウトして表示され、先頭に空行があることがわかるでしょう。このコメントを消して自分でコミットメッセージを書き入れていくこともできますし、何をコミットしようとしているのかの確認のためにそのまま残しておいてもかまいません (何を変更したのかをより明確に知りたい場合は、<code>git commit</code> に <code>-v</code> オプションを指定します。そうすると、diff の内容がエディタに表示されるので何を行ったのかが正確にわかるようになります)。エディタを終了させると、Git はそのメッセージつきのコミットを作成します (コメントおよび diff は削除されます)。</p>
<p>あるいは、コミットメッセージをインラインで記述することもできます。その場合は、<code>commit</code> コマンドの後で <code>-m</code> フラグに続けて次のように記述します。</p>
<pre><code>$ git commit -m "Story 182: Fix benchmarks for speed"
[master 463dc4f] Story 182: Fix benchmarks for speed
2 files changed, 3 insertions(+)
create mode 100644 README
</code></pre>
<p>これではじめてのコミットができました! 今回のコミットについて、「どのブランチにコミットしたのか (<code>master</code>)」「そのコミットの SHA-1 チェックサム (<code>463dc4f</code>)」「変更されたファイルの数」「そのコミットで追加されたり削除されたりした行数」といった情報が表示されているのがわかるでしょう。</p>
<p>コミットが記録するのは、ステージングエリアのスナップショットであることを覚えておきましょう。ステージしていない情報については変更された状態のまま残っています。別のコミットで歴史にそれを書き加えるには、改めて add する必要があります。コミットするたびにプロジェクトのスナップショットが記録され、あとからそれを取り消したり参照したりできるようになります。</p>
<h3>ステージングエリアの省略</h3>
<p>コミットの内容を思い通りに作り上げることができるという点でステージングエリアは非常に便利なのですが、普段の作業においては必要以上に複雑に感じられることもあるでしょう。ステージングエリアを省略したい場合のために、Git ではシンプルなショートカットを用意しています。<code>git commit</code> コマンドに <code>-a</code> オプションを指定すると、追跡対象となっているファイルを自動的にステージしてからコミットを行います。つまり <code>git add</code> を省略できるというわけです。</p>
<pre><code>$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: benchmarks.rb
no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m 'added new benchmarks'
[master 83e38c7] added new benchmarks
1 files changed, 5 insertions(+)
</code></pre>
<p>この場合、コミットする前に <code>benchmarks.rb</code> を <code>git add</code> する必要がないことに注意しましょう。</p>
<h3>ファイルの削除</h3>
<p>ファイルを Git から削除するには、追跡対象からはずし (より正確に言うとステージングエリアから削除し)、そしてコミットします。<code>git rm</code> コマンドは、この作業を行い、そして作業ディレクトリからファイルを削除します。つまり、追跡されていないファイルとして残り続けることはありません。</p>
<p>単に作業ディレクトリからファイルを削除しただけの場合は、<code>git status</code> の出力の中では “Changes not staged for commit” (つまり <em>ステージされていない</em>) 欄に表示されます。</p>
<pre><code>$ rm grit.gemspec
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: grit.gemspec
no changes added to commit (use "git add" and/or "git commit -a")
</code></pre>
<p><code>git rm</code> を実行すると、ファイルの削除がステージされます。</p>
<pre><code>$ git rm grit.gemspec
rm 'grit.gemspec'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: grit.gemspec
</code></pre>
<p>次にコミットするときにファイルが削除され、追跡対象外となります。変更したファイルをすでにステージしている場合は、<code>-f</code> オプションで強制的に削除しなければなりません。まだスナップショットに記録されていないファイルを誤って削除してしまうと Git で復旧することができなくなってしまうので、それを防ぐための安全装置です。</p>
<p>ほかに「こんなことできたらいいな」と思われるであろう機能として、ファイル自体は作業ツリーに残しつつステージングエリアからの削除だけを行うこともできます。つまり、ハードディスク上にはファイルを残しておきたいけれど、もう Git では追跡させたくないというような場合のことです。これが特に便利なのは、<code>.gitignore</code> ファイルに書き足すのを忘れたために巨大なログファイルや大量の <code>.a</code> ファイルがステージされてしまったなどというときです。そんな場合は <code>--cached</code> オプションを使用します。</p>
<pre><code>$ git rm --cached readme.txt
</code></pre>
<p>ファイル名やディレクトリ名、そしてファイル glob パターンを <code>git rm</code> コマンドに渡すことができます。つまり、このようなこともできるということです。</p>
<pre><code>$ git rm log/\*.log
</code></pre>
<p><code>*</code> の前にバックスラッシュ (<code>\</code>) があることに注意しましょう。これが必要なのは、シェルによるファイル名の展開だけでなく Git が自前でファイル名の展開を行うからです。ただしWindowsのコマンドプロンプトの場合は、バックスラッシュは取り除かなければなりません。このコマンドは、<code>log/</code> ディレクトリにある拡張子 <code>.log</code> のファイルをすべて削除します。あるいは、このような書き方もできます。</p>
<pre><code>$ git rm \*~
</code></pre>
<p>このコマンドは、<code>~</code> で終わるファイル名のファイルをすべて削除します。</p>
<h3>ファイルの移動</h3>
<p>他の多くの VCS とは異なり、Git はファイルの移動を明示的に追跡することはありません。Git の中でファイル名を変更しても、「ファイル名を変更した」というメタデータは Git には保存されないのです。しかし Git は賢いので、ファイル名が変わったことを知ることができます。ファイルの移動を検出する仕組みについては後ほど説明します。</p>
<p>しかし Git には <code>mv</code> コマンドがあります。ちょっと混乱するかもしれませんね。Git の中でファイル名を変更したい場合は次のようなコマンドを実行します。</p>
<pre><code>$ git mv file_from file_to
</code></pre>
<p>このようなコマンドを実行してから status を確認すると、Git はそれをファイル名が変更されたと解釈していることがわかるでしょう。</p>
<pre><code>$ git mv README.txt README
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.txt -> README
</code></pre>
<p>しかし、実際のところこれは、次のようなコマンドを実行するのと同じ意味となります。</p>
<pre><code>$ mv README.txt README
$ git rm README.txt
$ git add README
</code></pre>
<p>Git はこれが暗黙的なファイル名の変更であると理解するので、この方法であろうが <code>mv</code> コマンドを使おうがどちらでもかまいません。唯一の違いは、この方法だと 3 つのコマンドが必要になるかわりに <code>mv</code> だとひとつのコマンドだけで実行できるという点です。より重要なのは、ファイル名の変更は何でもお好みのツールで行えるということです。あとでコミットする前に add/rm を指示してやればいいのです。</p>
<h2>コミット履歴の閲覧</h2>
<p>何度かコミットを繰り返すと、あるいはコミット履歴つきの既存のリポジトリをクローンすると、過去に何が起こったのかを振り返りたくなることでしょう。そのために使用するもっとも基本的かつパワフルな道具が <code>git log</code> コマンドです。</p>
<p>ここからの例では、<code>simplegit</code> という非常にシンプルなプロジェクトを使用します。これは、私が説明用によく用いているプロジェクトで、次のようにして取得できます。</p>
<pre><code>git clone git://github.com/schacon/simplegit-progit.git
</code></pre>
<p>このプロジェクトで <code>git log</code> を実行すると、このような結果が得られます。</p>
<pre><code>$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <[email protected]>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <[email protected]>
Date: Sat Mar 15 16:40:33 2008 -0700
removed unnecessary test code
commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <[email protected]>
Date: Sat Mar 15 10:31:28 2008 -0700
first commit
</code></pre>
<p>デフォルトで引数を何も指定しなければ、<code>git log</code> はそのリポジトリでのコミットを新しい順に表示します。つまり、直近のコミットが最初に登場するということです。ごらんのとおり、このコマンドは各コミットについて SHA-1 チェックサム・作者の名前とメールアドレス・コミット日時・コミットメッセージを一覧表示します。</p>
<p><code>git log</code> コマンドには数多くのバラエティに富んだオプションがあり、あなたが本当に見たいものを表示させることができます。ここでは、よく用いられるオプションのいくつかをご覧に入れましょう。</p>
<p>もっとも便利なオプションのひとつが <code>-p</code> で、これは各コミットの diff を表示します。また <code>-2</code> は、直近の 2 エントリだけを出力します。</p>
<pre><code>$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <[email protected]>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,5 +5,5 @@ require 'rake/gempackagetask'
spec = Gem::Specification.new do |s|
s.name = "simplegit"
- s.version = "0.1.0"
+ s.version = "0.1.1"
s.author = "Scott Chacon"
s.email = "[email protected]
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <[email protected]>
Date: Sat Mar 15 16:40:33 2008 -0700
removed unnecessary test code
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index a0a60ae..47c6340 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -18,8 +18,3 @@ class SimpleGit
end
end
-
-if $0 == __FILE__
- git = SimpleGit.new
- puts git.show
-end
\ No newline at end of file
</code></pre>
<p>このオプションは、先ほどと同じ情報を表示するとともに、各エントリの直後にその diff を表示します。これはコードレビューのときに非常に便利です。また、他のメンバーが一連のコミットで何を行ったのかをざっと眺めるのにも便利でしょう。</p>
<p>コードレビューの際、行単位ではなく単語単位でレビューするほうが容易な場合もあるでしょう。<code>git log -p</code> コマンドのオプション <code>--word-diff</code> を使えば、通常の行単位diffではなく、単語単位のdiffを表示させることができます。単語単位のdiffはソースコードのレビューに用いても役に立ちませんが、書籍や論文など、長文テキストファイルのレビューを行う際は便利です。こんな風に使用します。</p>
<pre><code>$ git log -U1 --word-diff
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <[email protected]>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -7,3 +7,3 @@ spec = Gem::Specification.new do |s|
s.name = "simplegit"
s.version = [-"0.1.0"-]{+"0.1.1"+}
s.author = "Scott Chacon"
</code></pre>
<p>ご覧のとおり、通常のdiffにある「追加行や削除行の表示」はありません。その代わりに、変更点はインラインで表示されることになります。追加された単語は <code>{+ +}</code> で、削除された単語は <code>[- -]</code> で囲まれます。また、着目すべき点が行ではなく単語なので、diffの出力を通常の「変更行前後3行ずつ」から「変更行前後1行ずつ」に減らしたほうがよいかもしれません。上記の例で使用した <code>-U1</code> オプションを使えば行数を減らせます。</p>
<p>また、<code>git log</code> では「まとめ」系のオプションを使うこともできます。たとえば、各コミットに関するちょっとした統計情報を見たい場合は <code>--stat</code> オプションを使用します。</p>
<pre><code>$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <[email protected]>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
Rakefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <[email protected]>
Date: Sat Mar 15 16:40:33 2008 -0700
removed unnecessary test code
lib/simplegit.rb | 5 -----
1 file changed, 5 deletions(-)
commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <[email protected]>
Date: Sat Mar 15 10:31:28 2008 -0700
first commit
README | 6 ++++++
Rakefile | 23 +++++++++++++++++++++++
lib/simplegit.rb | 25 +++++++++++++++++++++++++
3 files changed, 54 insertions(+)
</code></pre>
<p>ごらんの通り <code>--stat</code> オプションは、各コミットエントリに続けて変更されたファイルの一覧と変更されたファイルの数、追加・削除された行数が表示されます。また、それらの情報のまとめを最後に出力します。もうひとつの便利なオプションが <code>--pretty</code> です。これは、ログをデフォルトの書式以外で出力します。あらかじめ用意されているいくつかのオプションを指定することができます。<code>oneline</code> オプションは、各コミットを一行で出力します。これは、大量のコミットを見る場合に便利です。さらに <code>short</code> や <code>full</code> そして <code>fuller</code> といったオプションもあり、これは標準とほぼ同じ書式だけれども情報量がそれぞれ少なめあるいは多めになります。</p>
<pre><code>$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 changed the version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test code
a11bef06a3f659402fe7563abf99ad00de2209e6 first commit
</code></pre>
<p>もっとも興味深いオプションは <code>format</code> で、これは独自のログ出力フォーマットを指定することができます。これは、出力結果を機械にパースさせる際に非常に便利です。自分でフォーマットを指定しておけば、将来 Git をアップデートしても結果が変わらないようにできるからです。</p>
<pre><code>$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 11 months ago : changed the version number
085bb3b - Scott Chacon, 11 months ago : removed unnecessary test code
a11bef0 - Scott Chacon, 11 months ago : first commit
</code></pre>
<p>表 2-1 は、format で使用できる便利なオプションをまとめたものです。</p>
<!-- Attention to translators: this is a table declaration.
The lines must be formatted as follows
<TAB><First column text><TAB><Second column text>
-->
<pre><code>オプション 出力される内容
%H コミットのハッシュ
%h コミットのハッシュ (短縮版)
%T ツリーのハッシュ
%t ツリーのハッシュ (短縮版)
%P 親のハッシュ
%p 親のハッシュ (短縮版)
%an Author の名前
%ae Author のメールアドレス
%ad Author の日付 (--date= オプションに従った形式)
%ar Author の相対日付
%cn Committer の名前
%ce Committer のメールアドレス
%cd Committer の日付
%cr Committer の相対日付
%s 件名
</code></pre>
<p><em>author</em> と <em>committer</em> は何が違うのか気になる方もいるでしょう。<em>author</em> とはその作業をもともと行った人、<em>committer</em> とはその作業を適用した人のことを指します。あなたがとあるプロジェクトにパッチを送り、コアメンバーのだれかがそのパッチを適用したとしましょう。この場合、両方がクレジットされます (あなたが author、コアメンバーが committer です)。この区別については <em>第 5 章</em> でもう少し詳しく説明します。</p>
<p>oneline オプションおよび format オプションは、<code>log</code> のもうひとつのオプションである <code>--graph</code> と組み合わせるとさらに便利です。このオプションは、ちょっといい感じのアスキーグラフでブランチやマージの歴史を表示します。Grit プロジェクトのリポジトリならこのようになります。</p>
<pre><code>$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 ignore errors from SIGCHLD on trap
* 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
|\
| * 420eac9 Added a method for getting the current branch.
* | 30e367c timeout code and tests
* | 5a09431 add timeout protection to grit
* | e1193f8 support for heads with slashes in them
|/
* d6016bc require time for xmlschema
* 11d191e Merge branch 'defunkt' into local
</code></pre>
<p>これらは <code>git log</code> の出力フォーマット指定のほんの一部でしかありません。まだまだオプションはあります。表 2-2 に、今まで取り上げたオプションとそれ以外によく使われるオプション、そしてそれぞれが<code>log</code>の出力をどのように変えるのかをまとめました。</p>
<!-- Attention to translators: this is a table declaration.
The lines must be formatted as follows
<TAB><First column text><TAB><Second column text>
-->
<pre><code>オプション 説明
-p 各コミットのパッチを表示する
--word-diff 変更点を単語単位で表示する
--stat 各コミットで変更されたファイルの統計情報を表示する
--shortstat --stat コマンドのうち、変更/追加/削除 の行だけを表示する
--name-only コミット情報の後に変更されたファイルの一覧を表示する
--name-status 変更されたファイルと 追加/修正/削除 情報を表示する
--abbrev-commit SHA-1 チェックサムの全体 (40文字) ではなく最初の数文字のみを表示する
--relative-date 完全な日付フォーマットではなく、相対フォーマット (“2 weeks ago” など) で日付を表示する
--graph ブランチやマージの歴史を、ログ出力とともにアスキーグラフで表示する
--pretty コミットを別のフォーマットで表示する。オプションとして oneline, short, full, fuller そして format (独自フォーマットを設定する) を指定可能
--oneline `--pretty=oneline --abbrev-commit`と同じ意味の便利なオプション
</code></pre>
<h3>ログ出力の制限</h3>
<p>出力のフォーマット用オプションだけでなく、 <code>git log</code> にはログの制限用の便利なオプションもあります。コミットの一部だけを表示するようなオプションのことです。既にひとつだけ紹介していますね。<code>-2</code> オプション、これは直近のふたつのコミットだけを表示するものです。実は <code>-<n></code> の <code>n</code> には任意の整数値を指定することができ、直近の <code>n</code> 件のコミットだけを表示させることができます。ただ、実際のところはこれを使うことはあまりないでしょう。というのも、Git はデフォルトですべての出力をページャにパイプするので、ログを一度に 1 ページだけ見ることになるからです。</p>
<p>しかし <code>--since</code> や <code>--until</code> のような時間制限のオプションは非常に便利です。たとえばこのコマンドは、過去二週間のコミットの一覧を取得します。</p>
<pre><code>$ git log --since=2.weeks
</code></pre>
<p>このコマンドはさまざまな書式で動作します。特定の日を指定する (“2008-01-15”) こともできますし、相対日付を“2 years 1 day 3 minutes ago”のように指定することも可能です。</p>
<p>コミット一覧から検索条件にマッチするものだけを取り出すこともできます。<code>--author</code> オプションは特定の author のみを抜き出し、<code>--grep</code> オプションはコミットメッセージの中のキーワードを検索します (author と grep を両方指定すると、両方にマッチするものだけが対象になります)。</p>
<p>grep を複数指定したい場合は、<code>--all-match</code> を追加しないといけません。そうしないと、どちらか一方にだけマッチするものも対象になってしまいます。</p>
<p>最後に紹介する <code>git log</code> のフィルタリング用オプションは、パスです。ディレクトリ名あるいはファイル名を指定すると、それを変更したコミットのみが対象となります。このオプションは常に最後に指定し、一般にダブルダッシュ (<code>--</code>) の後に記述します。このダブルダッシュが他のオプションとパスの区切りとなります。</p>
<p>表 2-3 に、これらのオプションとその他の一般的なオプションをまとめました。</p>
<!-- Attention to translators: this is a table declaration.
The lines must be formatted as follows
<TAB><First column text><TAB><Second column text>
-->
<pre><code>オプション 説明
-(n) 直近の n 件のコミットのみを表示する
--since, --after 指定した日付/時刻以降のCommitDateのコミットのみに制限する
--until, --before 指定した日付/時刻以前のCommitDateのコミットのみに制限する
--author エントリが指定した文字列にマッチするコミットのみを表示する
--committer エントリが指定した文字列にマッチするコミットのみを表示する
</code></pre>
<h3>日時にもとづくログ出力の制限</h3>
<p>Git のリポジトリ(git://git.kernel.org/pub/scm/git/git.git)からCommitDateを使ってコミットを検索してみましょう。パソコンに設定されたタイムゾーンにおける2014/04/29のコミットを検索するには、以下のコマンドを実行します。</p>
<pre><code>$ git log --after="2014-04-29 00:00:00" --before="2014-04-29 23:59:59" \
--pretty=fuller
</code></pre>
<p>この場合、コマンドの結果はパソコンのタイムゾーン設定ごとに異なってしまいます。それを避けるには、タイムゾーンを含むISO 8601フォーマットのような日時を <code>--after</code> や <code>--before</code> の引数に指定するといいでしょう。そうすれば、上述のケースのようにコマンド実行結果が異なる可能性がなくなります。</p>
<p>特定日時(例として、中央ヨーロッパ時間で2013/04/29 17:07:22)を指定してコミットを検索するには、以下のコマンドを使います。</p>
<pre><code>$ git log --after="2013-04-29T17:07:22+0200" \
--before="2013-04-29T17:07:22+0200" --pretty=fuller
commit de7c201a10857e5d424dbd8db880a6f24ba250f9
Author: Ramkumar Ramachandra <[email protected]>
AuthorDate: Mon Apr 29 18:19:37 2013 +0530
Commit: Junio C Hamano <[email protected]>
CommitDate: Mon Apr 29 08:07:22 2013 -0700
git-completion.bash: lexical sorting for diff.statGraphWidth