O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.
【幕張読書会】
コンセプトから理解する
Gitコマンド
基礎編
@ktateish
はじめに
Gitのコマンドってわかりにくいですよね?
Git内部のコンセプトを理解するとGitコマンドにつ
いての理解がはかどります。
この資料はGitのコンセプトからコマンドを理解する
ことを目的として作成しました。
注意
Gitを使ったことのあるエンジニア向けです。
● add/commit/pushしたことくらいならあるよ、的
な人を想定。他VCSの経験があればGitを使っ
たことがなくてもOK
● Unix関連のベーシックなスキル・コンセプトは解
説し...
目次
第1章 コミットとオブジェクト(p.5)
第2章 参照: ブランチとタグ(p.74)
第3章 インデックスとワーキングツリー(p.134)
第4章 コンセプトから理解するGitコマンド
(p.161 - p405)
第1章
コミットとオブジェクト
そもそもバージョン管理とは?
memo-20140425.txt
memo-20140428.txt
memo-20140430.txt
・・・
こういうやつですね。
これも一応バージョン管理
何でバージョン管理したいのか?
いろいろありますが根源的なのはだいたい
1. 加えた変更がまずかったら元にもどしたい
2. 何処をどう変更したのか知りたい
3. 誰がなぜ変更したのか知りたい
あたりだと思います
Gitにおけるバージョン
Gitにおいてバージョンは「コミット」という単位で管
理します
他のVCSだとリビジョンやチェンジセットなどと言わ
れるやつのことです。
コミットを作成する行為も「コミット(する)」と言いま
す。これは他VCSと同様。
Gitにおけるコミット
ひとつのコミットは以下の情報からなります
ディレクトリツリーのスナップショット
+
ひとつ前のコミット(親コミット)
+
その他(コミッタ名、コミットメッセージとか)
ちなみに
1コミットごとに完全なスナップショットを
保持しています。変化を記録しているわけではな
いので「チェンジセット」とは呼びません。
親コミットを記録しているので、差分は必要になっ
たときに作ればいいや、という思想です。
コミットが
バージョン管理の要求を満たす
1. 加えた変更がまずかったら元にもどしたい
➔ いつでも昔のコミットを取り出して戻せる
2. 何処をどう変更したのか知りたい
➔ コミット同士を比較することで可能
3. 誰がなぜ変更したのか知りたい
...
コミット
コミットの詳細
コミット =
ツリーのスナップショットへのポインタ
+ 親コミットへのポインタ
+ 著作者・著作日時
+ コミッター・コミット日時
+ コミットメッセージ
コミットを図にすると
コミット
親コミット = ひとつ前のコミット
ツリーのスナップショット
著作者等の情報
コミッター等の情報
コミットメッセージ
ツリーへのポインタ
親コミットへの
ポインタ
実際に見てみよう
% git cat-file -p HEAD
tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac
parent 897d06bcb89a12574271e74e90048cb26fe5f...
実際に見てみよう
% git cat-file -p HEAD
tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac
parent 897d06bcb89a12574271e74e90048cb26fe5f...
実際に見てみよう
% git cat-file -p HEAD
tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac
parent 897d06bcb89a12574271e74e90048cb26fe5f...
実際に見てみよう
% git cat-file -p HEAD
tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac
parent 897d06bcb89a12574271e74e90048cb26fe5f...
実際に見てみよう
% git cat-file -p HEAD
tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac
parent 897d06bcb89a12574271e74e90048cb26fe5f...
実際に見てみよう
% git cat-file -p HEAD
tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac
parent 897d06bcb89a12574271e74e90048cb26fe5f...
実際に見てみよう
% git cat-file -p HEAD
tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac
parent 897d06bcb89a12574271e74e90048cb26fe5f...
つまりコミットとは
コミット
親コミット = ひとつ前のコミット
(897d06...)
ツリーのスナップショット
(2e4038…)
コミッター等の情報
コミットメッセージ
ツリーへのポインタ
親コミットへの
ポインタ
少し周辺の情報を補うと
コミット
(03ccb3...)
親コミット = ひとつ前のコミット
(897d06...)
ツリーのスナップショット
(2e4038…)
ツリーのスナップショット
(57e952…)
少し周辺の情報を補うと
コミット
(03ccb3...)
親コミット = ひとつ前のコミット
(897d06...)
ツリーのスナップショット
(2e4038…)
ツリーのスナップショット
(57e952…)
親の名前(897d06…)と同様、...
コミットが積み重なると
コミット
ツリー
コミット
ツリー
ツリー
ツリー
コミット
ツリー
コミット
→ コミットグラフになる
(コミットが決まればツリーも一意
に決まるので、図示する際は普通
ツリーを省略します。)
コミット
コミットは親を複数持つことも可能
コミット
ツリー
コミット
ツリー
ツリー
ツリー
コミット
ツリー
コミット
いわゆるマージコミットです。マー
ジコミットを作成する行為を「マー
ジする」と言います。
本資料では深く解説しません
コミット
コ...
ところで名前 (03ccb3…)って結局何?
コミット
(03ccb3...)
名前=オブジェクトの内容のSHA1値です
先頭数桁だけでもユニークな名
前になるので、この省略名
(abbrev)をしばしば使う。
つまりコミット 03ccb3…の場合は
コミット
(03ccb3...)
内容のSHA1を計算
実際にはオブジェクトの型(commit, tree, bl...
そういえばツリーにも名前があった
コミット
親コミット
ツリーのスナップショット
(2e4038…)
コレがツリーのオブジェクト名
ツリー
図にすると
tree
2e4038...
(root)
tree
f18bca…
img
blob
ce0136...
greeting.txt
blob
64e502...
greeting2.txt
blob
6935eb...
scree...
ツリーの中を実際に見てみよう
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt
100644 blob 64e5...
ツリーエントリ:モード
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt
100644 blob 64e5028...
ツリーエントリ:オブジェクト名
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt
100644 blob 64e...
ツリーエントリ:パス名
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt
100644 blob 64e5028...
ツリーは再帰構造
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt
100644 blob 64e50281e4...
続いてツリーに記録されたブロブ
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt
100644 blob 64e...
ブロブ
ブロブの中を実際に見てみよう
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt
100644 blob 64e5...
ブロブの中を実際に見てみよう
実際に “hello” (+改行) という文字列をhash-objectコマンドでGit オブジェクト化するこ
とができます。
オブジェクト化すると、やはり ce0136… という名前のオブジェクトになりました。
...
ブロブを作ってみる
hash-object -w でGitのオブジェクトデータベースに書き込めます。
“tekitou na mojiretsu”(+改行) は 2da935 というオブジェクトになりました。
% echo "tekitou n...
ところでファイル名がでてきませんね
% echo "tekitou na mojiretsu " | git hash-object --stdin -w
2da9358db1fe68b3c8cf0196bfaf82ee0d6f9103
% l...
ではファイル名はどこにあるのか
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt
100644 blob 64e...
再び
ツリー
ツリーとは
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt
100644 blob 64e50281e4e0e...
いったい何に似ているって言うんだー
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt
100644 blob 6...
明らかにUnixのディレクトリですね
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt
100644 blob ...
再び図にしてみます
tree
2e4038...
(root)
tree
f18bca…
img
% git cat-file -p 2e4038
100644 blob ce013625030ba8dba906f756967f9e9ca394...
オブジェクトの格納状況はこんな感じ
ce0136
2e4038
f18bca64e502
6935eb
オブジェクト名が
Gitデータベース内に格納されたコンテンツを指定
% find .git/objects -type f
.git/obj...
各treeからの矢印にすると
ce0136
2e4038
f18bca64e502
6935eb
こんな感じ
% find .git/objects -type f
.git/objects/b0/de5d4beb96ad900811b3d9e...
Unixのファイルシステムの場合は
808494
808312
917641808590
917647
inodeがデータブロックを(間接的に)指定します
スーパーブロック
iノードテーブル
データ領域
各ディレクトリのデータブロックから
808494
808312
917641808590
917647
矢印を引くとこんな感じ
スーパーブロック
iノードテーブル
データ領域
そっくりだ!
Gitのtreeと
オブジェクトデータベース
Unixのディレクトリと
ファイルシステム
ce0136
2e4038
f18bca64e502
6935eb
% find .git/objects -type f
.git/obj...
つまりGitのオブジェクトは
tree
2e4038...
(root)
tree
f18bca…
img
blob
ce0136...
greeting.txt
blob
64e502...
greeting2.txt
blob
6935eb...
もちろんそれだけじゃありません
tree
2e4038...
(root)
tree
f18bca…
img
blob
ce0136...
greeting.txt
blob
64e502...
greeting2.txt
blob
6935e...
内容が同じファイルを追加すると
コンテンツが同じ
= SHA1値が同じ = 同じオブジェクト=もうある
% find .git/objects -type f
.git/objects/b0/de5d4beb96ad900811b3d9e115...
同じ内容なら同じオブジェクト
tree
……...
(root)
tree
……...
img
blob
ce0136...
greeting.txt
blob
64e502...
greeting2.txt
blob
6935eb...
sc...
改竄検知
さきほどのページの図
おかしなところがあったことを
おわかりいただけただろうか
Google Docsって隷書フォント使えないの ?(´・ω・`)
treeのオブジェクト名が変わった…
tree
.........
(root)
tree
……...
img
blob
ce0136...
greeting.txt
blob
64e502...
greeting2.txt
blob
6935...
はい。treeはツリーエントリを
内容とするオブジェクトなので
tree
771c10...
(root)
tree
716186…
img
ファイルの追加・削除等々、構造が変わればtreeオ
ブジェクトは別のものになります
←ファイルを追加
...
さらにtreeはblobの名前を持つので
tree
fe5448...
(root)
tree
f34fd4…
img
blob=ファイルの内容が1bitでも変われば連鎖的に
rootのtreeオブジェクトが変わります
↑”hellp”に変えて...
ツリーを構成する全情報のうち1bitでも変
更されればrootの名前で検知可能
tree
fe5448...
(root)
tree
f34fd4…
img
blob
ce0136...
greeting.txt
blob
64e502...
...
逆にrootのオブジェクトが同じなら
tree
fe5448...
(root)
下をチェックしなくても全体が同じだとわかる
→ ツリー同士の比較が爆速
tree
fe5448...
(root)
=
イコール
diff-treeの場合。ファイ...
tree:
fe5448
さらにさらに
tree
(fe5448)
ツリーはコミットごとに記録
されるのでした。
→バージョンを記録
commit
(8b0e1d)
commit
(f78673)
tree:771c10
parent:
f78...
改竄(破損)検知はコミットにも伝搬
コミットは親コミットの名前を含んで
います。
→ツリー全体を含む祖先のコミット
の情報のうち「何か」が1bitでも異
なれば、それ以外すべて同一でも
子孫は全て別物になります。
ef1046
09a80f
5...
改竄(破損)検知
バージョン管理
重複排除
圧縮
ファイルシステム
それがGitだ!(ドヤァ
まとめると
tree
commit
tree
commit
tree
commit
tree
commit
tree
commit
1bitでも違えば異なるオブジェクト
→データ量が肥大化(packで解決)
ツリーのスナップショットで管理
→単一ファイルの変化の追跡が苦手
(経由する全てのコミットでいちいちtree
をたどってオブジェクトが変わっている
か調べる必要がある)...
すでに散々出てきましたが
最後に改めてオブジェクトについてまとめておきま
す。
オブジェクトとはGitが管理する情報の単位です。
Gitオブジェクトの特徴
1. commit, tree, blob 等の型がある
2. オブジェクト名はコンテンツのSHA1値
→同じ内容のオブジェクトは区別されない
3. 各commitから親commitとtreeを辿れる
4. treeか...
Gitオブジェクトの特徴
ふたつのオブジェクトの名前が同じなら、そこから
辿れる全オブジェクトが構成する構造全体にわ
たって同じ内容であることが保証される
e.g.
● blob同士が同じ名前なら同じファイル
● tree同士が同じ名前なら同じ...
ここまでに出てきた主なコンセプト
コミット
親コミット
コミットグラフ
ツリー
ブロブ
オブジェクト
改竄検知
コマンドの解説はもう少し先です
コミット
親コミット
コミットグラフ
ツリー
ブロブ
オブジェクト
改竄検知
参照
シンボリックレフ
ブランチ
タグ(参照)
タグ(オブジェクト)
インデックス
ワーキングツリー
第2章
参照: ブランチとタグ
参照
参照とは
オブジェクト(主にコミット)につけられる、人間が読
みやすい名前のこと。
オブジェクト名(SHA1値)は覚えにくいので、覚えて
おいたほうが便利なオブジェクトには参照をつけま
す。
参照はレフ(ref, reference)とも呼ばれ...
こんな感じです。master という参照は有名です
よね。
参照を図にすると
ef1046
09a80f
master
これで “master” と書いてやれば、わざわざ ”
ef1046”とかSHA1値を書かないですみます。
commit
c...
参照の実体を見てみよう
参照の実体はオブジェクト名を含んだただのテキ
ストファイルです。
% cat .git/refs/heads/ master
ef1046a0117da8872b73fe72528c1fd9facd95ab
ef1046...
保存場所で参照の種類が決まる
refs/heads/ 配下の参照=ブランチ
refs/remotes/ 配下
=リモート追跡ブランチ
refs/tags/ 配下=タグ
% cat .git/refs/ heads/master
ef1046a0...
GCとの関係
参照には他に重要な役割がひとつあります。
それは参照から到達可能なコミットはgit gcで削除
されない、というものです。
(削除されてほしくなければ参照を作っておく)
master
←削除対象
←削除対象
参照を参照する参照もあります
origin/HEAD -> origin/master という表示は見たこ
とがあるのではないでしょうか。
この手の参照をシンボリックレフといいます。
% git branch -a
* master
remot...
シンボリックレフ
参照を参照する参照=シンボリックレフ
実体であるファイルの中身はコミットではなく別の
参照のパスです。
図示すると右のような感じ。
コミットを直接は指さず、参照を指しています
% cat .git/refs/remotes/ origin/HE...
最もよく使うシンボリックレフ
みんなが一番お世話になっているシンボリック
レフは HEAD です。
foo
% cat .git/HEAD
ref: refs/heads/foo
HEAD がブランチを指している場
合*、指されているブランチを...
ブランチ
ブランチとは
ブランチもタグも同じ参照だとすると何が違うの
でしょうか?
タグは「ある時点のコミットを定常的に指す」とい
う役割があり、
ブランチには「コミットを新しく作る場所を指す」と
いう役割があります。
動作の違いはコミットしたとき
カレントブランチにコミットすると、ブランチは自
動的に新しくできたコミットを指しますが、タグの
場合は動きません。
branch
tag tagbranch
“branch”をチェックアウトしてコミット作成 “ta...
この動作により
ブランチであればコミットするたびにブランチが
成長していきます。
branch
branch
HEAD
HEAD
branch
HEAD
branch
HEAD
より正確には
ref
HEADがrefを指している
HEAD
ref
新しいコミット
HEAD
HEADが参照を指している場合(≒HEADがシ
ンボリックレフの場合)、コミット時に指されてい
る参照が新しいコミットに追従します。
実はHEADが「新コミット作成場所」
新しいコミット
HEAD
HEAD
新しいコミットは HEADに作られる
新しいコミットはチェックアウトしているコミット、
つまりHEADをたどって得られるコミットを親とし
て作成されます。
実はコミット作...
じゃあブランチは一体何?
正確には「HEADがシンボリックレフで指すこと
ができる参照」がブランチです。
ブランチ以外の参照はチェックアウトしても
HEADはその先のコミットを直接指すただの参
照になってしまいます。
ref
HEAD
ref
...
結果として
「コミットを新しく作る場所を指す参照」という役
割を効果的に果たせるのはブランチだけ、という
ことになります。
branch
tag tagbranch
“branch”をチェックアウトしてコミット作成 “tag”をチェックアウトし...
動くのはHEADが指す参照だけ
例えばブランチmasterの場所にブランチtopicを作
成した直後、2つのブランチは同じコミットをさして
います。
master topic
動くのはHEADが指す参照だけ
masterをチェックアウトしている場合、HEADは
masterを指します。
master
HEAD
topic
動くのはHEADが指す参照だけ
この状態でコミットをつくると、HEAD が指すコミット
(=HEADが指す参照(master)が指すコミット)を親
とした新しいコミットが作られ
master
HEAD
topic
動くのはHEADが指す参照だけ
この状態でコミットをつくると、HEAD が指すコミット
(=HEADが指す参照(master)が指すコミット)を親
とした新しいコミットが作られ、 master がそれに追
従して動きます。topicは動きません...
動くのはHEADが指す参照だけ
masterをチェックアウトしている限り(つまりHEAD
がmasterを指している限り)、コミットするたび
masterが動き続けます。
master
HEAD
topic
動くのはHEADが指す参照だけ
今度はtopicをチェックアウトしました。
ということは、HEADはtopicを指します。
master
HEAD
topic
動くのはHEADが指す参照だけ
この状態でコミットすると、HEADが指すコミットを
親とする新しいコミットが作られ
HEAD
topic
master
動くのはHEADが指す参照だけ
この状態でコミットすると、HEADが指すコミットを
親とする新しいコミットが作られ、HEADが指す参
照が追従します。
HEAD
topic
master
動くのはHEADが指す参照だけ
さらにコミットしても同様です。
HEAD
topicmaster
動くのはHEADが指す参照だけ
もし図の場所に"backup”というタグがあったとして
HEAD
topicmaster
backup
動くのはHEADが指す参照だけ
backupをチェックアウトしてもブランチではないの
でHEADはbackupが指すコミットを直接指すことに
なります。
topicmaster
backup
HEAD
動くのはHEADが指す参照だけ
HEADがコミットを直接参照している状態をデタッ
チトヘッド(Detached HEAD)と言い、コミットは可
能ですが、
topicmaster
backup
HEAD
動くのはHEADが指す参照だけ
それに追従する参照はHEAD以外ありません。つ
まり別の参照をチェックアウトすると...
topicmaster
HEAD
backup
動くのはHEADが指す参照だけ
先ほどまでチェックアウトしていたコミット(☆)に戻
ることは難しくなります。参照を付けず放置すると、
やがてGCで完全に削除されてしまいます。
topicmaster
HEAD
backup
☆ <良い子の諸君
動くのはHEADが指す参照だけ
Detached HEADはあくまで特定のコミットを見るた
めだけに使い、コミットを作るにはブランチを使いま
しょう。
topicmaster
HEAD
backup
ちなみに
コミットオブジェクトの中身は「ツリー」「親コミット」
「著作者+日時」「コミッター+日時」「コミットメッ
セージ」でした。
topicmaster
つまり
全てのコミットオブジェクトはブランチの情報をどこ
にも持っていません。(コミットメッセージに残すこと
は可能)
topicmaster
他のVCSだと
ブランチ(たとえばtopic)は下図のように分岐したあ
との枝全体をイメージしてしまいがちですが・・・
topic
master
他のVCSだと
ブランチ(たとえばtopic)は下図のように分岐したあ
との枝全体をイメージしてしまいがちですが・・・
topic
master
Gitにおけるブランチとは
あくまでコミットを指している参照に過ぎません。枝
というよりも枝の先端(頭)だけを指し示しているイ
メージです。
topicmaster
ここだけがブランチ
HEAD
実際、Gitではブランチの参照を
「ブランチヘッド」とか「ヘッドレフ」などと言います。
保存先も refs/heads/ 配下でしたよね。「HEAD」も
その流れで考えれば自然な名前です。
topicmaster
ブランチヘッド
HEAD
ブラ...
コミットがブランチを全く記録しない
このコンセプトは賛否両論ありますが、「ブランチを
捨てるのが簡単」という大きな利点があります。例
えば・・・
topicmaster
トピックブランチを利用した開発では
「トピックに関係ないコミットはするな」ということに
なってますが・・・
feature-foomaster fix-bar
ちゃんと機能とバグ
フィックスはブランチ分
けろよ
開発リーダーの声
Gitの場合は
あまりこだわらずノリノリで仕上げて・・・
ああああ
master
後から
適切に分割し・・・
master feature-foo
fix-bar
コミットをコピー
ああああ
いらないブランチを消す
なんてことをよくやります。
master feature-foo
fix-bar
このとき
最初に作ったブランチの情報がfeature-fooやfix-
barのコミットに残るとしたら、(消す方法が用意され
ていたとしても)ちょっと面倒ですよね
master feature-foo
fix-bar
元ああああ
元ああああ
元...
ちょっと視点を変えて
Gitにおけるトピックブランチ開発では、最初から
topicの切り方が完璧でなくても良い、と考えると、
このコンセプトの強力さがわかると思います。
master feature-foo
fix-bar
でもまぁ、コンセプトの良し悪しは
置いておいて、Gitのブランチとはそういうものだと
覚えてしまいましょう。
ブランチヘッドをつけたり外したり、移動したりが簡
単そうに見えますが、実際簡単です。
後ほど具体的なコマンドで説明します。
タグ(参照)
すでに散々出てきましたが
タグは特定のコミットを指すただの参照です。
タグをチェックアウトしても、HEADはシンボリックレ
フとしてタグを指せないので、ブランチとしては使え
ません。
tag
一度指した場所が変わらない
というのは利点にもなります。
Gitではトピックのコミットを組み替
える作業(rebase等)をしばしば行
うので、
topic
master
一度指した場所が変わらない
もともとの場所にタグをつけておけ
ば、元に戻すのも簡単です backup
master
topic
もちろんブランチでも
コミットさえしなければ同じ感覚で
使えますが、指す場所が変わらな
いというのは作業するうえでの安
心感につながります。
backup
master
topic
でもそんな軽い存在で良いのか?
リリース用のタグにはタグ付けした日時や人の情
報とか残したいんだけど、と思うかもしれません。
また、改竄耐性の強いGitのコミットと比較して、あ
まりの軽さに違和感を覚えるかもしれません。
大丈夫
実はアノテーションタグと呼ばれる、作者やメッ
セージなどの注釈情報(アノテーション)を残せるタ
グもあります。
アノテーションはタグオブジェクト(tag)使って残しま
す。
タグ(オブジェクト)
タグオブジェクト
タグオブジェクトはコミットに似ています。
tag = タグ付け対象のオブジェクト名
+ その型(commit, tree, blob等)
+ タグ名
+ タグ作成者
+ タグメッセージ
tag
タグオブジェクトを実際に見てみよう
“v1.0”という名前のアノテーションタグがある場合、
下記のように中身を確認できます
v1.0
もちろんタグ名を直接指定して git cat-file -p v1.0 でも可能
タグオブジェクト
(275b...
tag obj内にもタグ名がありますが
参照としてのタグ(refs/tags/...)の付与は必須で
す。参照を削除すると、やがてはタグオブジェクトも
GCで削除されます。
が、アノテーションタグを作れば
自動で参照も作成されるので
あまり心配...
参照についての話題は以上です
コミット
親コミット
コミットグラフ
ツリー
ブロブ
オブジェクト
改竄検知
参照
シンボリックレフ
ブランチ
タグ(参照)
タグ(オブジェクト)
インデックス
ワーキングツリー
第3章
インデックスとワーキングツリー
インデックス
インデックスとは
新しく作るコミットのtreeを事前に組み立てる場所、
というイメージです。
tree
fe5448
commit
ef1046
master
HEAD
tree
fe5448
index
初期状態(チェックアウト直後)では
インデックスはHEADの指すコミットのtree(fe5448)
と同じtree(fe5448)を保持しています
tree
fe5448
commit
ef1046
master
HEAD
tree
fe544...
新しいコミットを作る準備として
インデックスのtreeを更新します(git add)。
インデックスのtreeは621a50になったとします
tree
fe5448
commit
ef1046
master
HEAD
新しいtreeで
inde...
インデックスを更新後コミットすると
インデックスに作ったtree(621a50)がそのまま新し
いコミットの指すtreeになります
tree
fe5448
commit
ef1046
master
HEAD tree
fe5448
commit...
コミット直後は
インデックスのtree(621a50)とHEADのtree
(621a50)が同じである状態に戻ってます。
tree
fe5448
commit
ef1046
master
HEAD tree
fe5448
commit
ef1...
インデックス=treeオブジェクト?
正確には違うものです。したがってcat-fileでイン
デックスを表示することはできません。
しかし、インデックスはtreeを作るために必要な情
報を保持しており、treeを持っているとイメージして
問題あ...
インデックスの中身を見たい!
HEADからの変化をサマリで見るにはgit statusが
適していますが、git ls-files(引数なし)でインデック
スに格納されたエントリを一覧できます。
treeオブジェクトとして見たい場合、git w...
インデックスの詳細
インデックスは他にもマージ中に複数のバージョン
のツリーのキャッシュを保持するなどの役割があり
ます。
詳細を知りたい人はGitソースツリーの
Documentation/technical/index-format.txt...
ワーキングツリー
これまでのコンセプトは全て
リポジトリの.git/配下の話でしたが、ワーキングツ
リーは .git/ 以外の部分のことです。
tree
fe5448
commit
ef1046
master
HEAD
tree
fe5448
index
.gi...
ワーキングツリーとは
Gitの管理するtreeが通常のUnixディレクトリツリー
としてチェックアウトされたものです。
tree
fe5448
commit
ef1046
master
HEAD
tree
fe5448
indexworking...
初期状態(チェックアウト直後)では
ワーキングツリーにはindexの内容がコピーされて
います。つまりHEADのtree(fe5448)相当の内容
です。
tree
fe5448
commit
ef1046
master
HEAD
tree
f...
ワーキングツリーの中身は
通常のディレクトリ・ファイルですので、
自由に追加・削除・変更できます。
.git/の世界の状況は関係なく編集可能です。
tree
fe5448
commit
ef1046
master
HEAD
tree
fe544...
コミットを作成するには
インデックスを更新してから、インデックスのツリー
を次のコミットとして登録するのでした。
tree
fe5448
commit
ef1046
master
HEAD
indexworking tree
locally
c...
このインデックス更新の元ネタが
ワーキングツリーの内容です。下図のtree 621a50
はワーキングツリーのファイルでインデックスを更
新してできたtreeだったのです。
working tree
621a50
equiv
tree
fe54...
元ネタとは言っても
コミット時にワークツリーとインデックスを完全に一
致させる必要はありません。コミットはあくまでもイ
ンデックスの内容で作られます。
working tree
0efb8b
equiv
tree
fe5448
commit
e...
ワーキングツリーの状態とコミットは
独立している、とも言えます。
これは非常に強力なコンセプトです。例えば・・・
working tree
0efb8b
equiv
tree
fe5448
commit
ef1046
master
HEAD
i...
開発中についつい
気になったtypoなど些細な修正をしたくなることが
あります。(あるいは、あとでやろうと思ってそのま
ま忘れてしまう)
tree
fe5448
commit
ef1046
master
HEAD
tree
fe5448
ind...
ひとつの修正に
意味的に複数の変更を加えるのは行儀の悪い行
為とされています。(後から取り消すのが面倒だっ
たりするので)
tree
fe5448
commit
ef1046
tree
5b94ca
indexworking tree
5b94...
そういう場合も
Gitなら気にせずワーキングツリーを修正して問題
ありません。その変更はインデックスに送らずにコ
ミットすれば良いのです。
tree
fe5448
commit
ef1046
tree
621a50
indexworking t...
その後
残っていた修正を改めてインデックスに送り、コミッ
トすれば、行儀の悪いコミットを作らなくてすみま
す。
tree
fe5448
commit
ef1046
tree
5b94ca
indexworking tree
5b94ca
equ...
つまりGitでは
ワーキングツリーの編集内容と、次回コミット内容
(=インデックス)が分離されているわけです。
tree
621a50
indexworking tree
5b94ca
equiv
ワーキングツリー
編集内容
次回コミットの内容...
視点を変えると
Gitでは次回コミットの事を気にしてワーキングツ
リーを編集する必要はない、というわけです。(イン
デックスに送る時に気にすればよい)
tree
621a50
indexworking tree
locally
changed
...
インデックスに送るコマンドは
主にgit addですが、これにはワーキングツリーの
変更を部分的にインデックスに送る機能が用意さ
れています。具体的には次章で。
tree
621a50
indexworking tree
5b94ca
equi...
ちなみに
インデックスは次回コミット、ワーキングツリーはそ
れ以降のコミットの内容を含んでいるので、コミット
グラフではHEADの続きのコミットのように図示す
る場合があります。
index working tree
master
HEAD
m...
第4章
コンセプトから理解するGitコマンド
いよいよコマンドの解説です
これまでに解説したコンセプトをもとにコマンドを解
説します。
具体的な解説を見る前に個々のコンセプトを思い
出しておきましょう。
解説した主なコンセプト
コミット
親コミット
コミットグラフ
ツリー
ブロブ
オブジェクト
改竄検知
参照
シンボリックレフ
ブランチ
タグ(参照)
タグ(オブジェクト)
インデックス
ワーキングツリー
追加で: commit-ishとは
Gitのマニュアルにはcommit-ishという表記がよく
出てきます。commit自身や参照など、commitが
一意に決まるものがcommit-ishです。
v1.0
コミット
master
タグ
ブラン...
この章で紹介するコマンド
● ワーキングツリー操作
○ checkout, reset
● インデックス操作
○ add, reset
● コミット操作
○ commit, merge, cherry-pick, revert
● ブランチ操作...
この章で紹介するコマンド(2)
● コミット・ブランチ複合操作
○ commit(--amend), rebase
● タグ操作
○ tag
● さまざまな調査
○ log, gitk, diff, reflog, fsck
● その他の複合操...
ワーキングツリー操作系
ワーキングツリーの内容を変更するコマンドを解説
します。
ワーキングツリー操作系
1. 全体を指定ブランチの内容に切り替える
checkout <branch>
checkout <commit-ish>
2. ワーキングツリーの変更を捨てる
checkout -- <path>
checkout <...
ワーキングツリー操作系
1. 全体を指定ブランチの内容に切り替える
checkout <branch>
checkout <commit-ish>
2. ワーキングツリーの変更を捨てる
checkout -- <path>
checkout <...
1. ワーキングツリー全体を指定したブラン
チの内容に切り替える
① checkout <branch>
② checkout <commit-ish>
①ワーキングツリーの内容を <branch> のツリー
の内容に切り替えます。同時にインデ...
checkout <branch>
checkout topicであれば、カレントブランチをtopic
に切り替えるわけですが、動きとしては・・・
tree
5b94ca
index
working tree
5b94ca
equiv git ...
checkout <branch>
HEADがtopicに移動し(カレントブランチが切り替
わり)・・・
tree
5b94ca
index
working tree
5b94ca
equiv git checkout topic
tree
6...
checkout <branch>
HEADのツリーでインデックスの内容を更新
tree
5b94ca
index
working tree
5b94ca
equiv git checkout topic
tree
621a50
commit
...
checkout <branch>
同じくワーキングツリーも内容を更新します。
tree
5b94ca
index
working tree
5b94ca
equiv git checkout topic
tree
621a50
commit
...
checkout <branch>
これがカレントブランチを切り替えるということの正
確な意味です。
tree
5b94ca
index
working tree
5b94ca
equiv git checkout topic
tree
621...
1. ワーキングツリー全体を指定したブラン
チの内容に切り替える
① checkout <branch>
② checkout <commit-ish>
②実は <branch> に限定されず、<commit-ish>な
らなんでも指定可能です。
checkout <commit-ish>
動きとしては<branch>指定のときとほとんど同じ
で・・・
tree
5b94ca
index
working tree
5b94ca
equiv git checkout topic
tree
...
checkout <commit-ish>
HEADがブランチを指すシンボリックレフではなく、
コミットを直接指す参照になる、という点が違うだけ
で・・・
tree
5b94ca
index
working tree
5b94ca
equiv ...
checkout <commit-ish>
インデックスとワーキングツリーが新しいHEADの
ツリーの内容で更新されるのは同じです
tree
5b94ca
index
working tree
5b94ca
equiv git checkout...
注意: チェックアウト実行前に
ワーキングツリー/インデックスがコミットされてない
変更を含んでいた場合、差分がチェックアウト後の
ツリーに適用されます。(変更が保持される)
tree
5b94ca
index
working tree
loc...
ワーキングツリー操作系
1. 全体を指定ブランチの内容に切り替える
checkout <branch>
checkout <commit-ish>
2. ワーキングツリーの変更を捨てる
checkout -- <path>
checkout <...
2. ワーキングツリーの内容を捨てる
① checkout -- <path>
② checkout <commit-ish> -- <path>
①インデックスの<path>の内容を取り出し、そいつ
でワーキングツリー配下の<path>を上書...
checkout -- <path>
hello.txtの変更でインデックスを更新し、ワーキン
グツリーのhello.txtを更に編集、greeting.txtにも編
集を加えた状態を考えます。
working tree index
hello...
checkout -- <path>
checkout -- greeting.txt を実行すると、インデック
スのgreeting.txtでワーキングツリーのgreeting.txt
を上書きします。
working tree index
...
checkout -- <path>
インデックスのgreeting.txtはもともとHEADから変
更されていないので、HEAD=インデックス=ワー
キングツリーな内容になります
working tree index
hello.txt
gr...
checkout -- <path>
続いて checkout -- hello.txt を実行すると、同様に
インデックスのhello.txtでワーキングツリーのhello.
txtを上書きします。
working tree index
he...
checkout -- <path>
ワーキングツリーのhello.txtがインデックスの
hello.txtと同じ内容になりました。これはHEADと
は異なる内容です。
working tree index
hello.txt
greetin...
checkout -- <path>
どちらの例もワーキングツリーの編集内容は捨て
られます。
working tree index
hello.txt
greeting.txthello.txt
greeting.txt
HEAD
hello...
checkout -- <path>
インデックスが変更されている場合はHEADと同じ
ならないことに注意。
HEADの内容で上書きしたい場合は次に出てくる
書式を使います。
working tree index
hello.txt
greet...
2. ワーキングツリーの内容を捨てる
① checkout -- <path>
② checkout <commit-ish> -- <path>
②<commit-ish>を指定した場合、そのコミットの内
容でインデックスとワーキングツリーの...
checkout <commit-ish> -- <path>
さっきの続きです。ここで checkout HEAD --
hello.txt を実行すると・・・
working tree index
hello.txt
greeting.tx...
checkout <commit-ish> -- <path>
インデックスのhello.txtがHEADのhello.txtで上書
きされ・・・
working tree index
hello.txt
greeting.txthello.t...
checkout <commit-ish> -- <path>
ワーキングツリーのhello.txtも同じ内容で上書きさ
れます。
どちらの書式も編集内容が捨てられるので注意し
てください。
working tree index
hello.t...
ワーキングツリー操作系
1. 全体を指定ブランチの内容に切り替える
checkout <branch>
checkout <commit-ish>
2. ワーキングツリーの変更を捨てる
checkout -- <path>
checkout <...
3. ワーキングツリーの内容を捨てる(2)
reset --hard [ HEAD ]
インデックスとワーキングツリーをHEADの内容で
上書きします。HEADは省略可能。
HEADの位置に他の<commit-ish>を指定可能ですが、カレント...
reset --hard
動作は checkout HEAD -- . (pathにカレントディレ
クトリを指定)と同じで・・・
working tree index
hello.txt
greeting.txthello.txt
greeti...
reset --hard
ツリー全体がHEADの内容で上書きされ、インデッ
クスとワーキングツリーの変更は捨てられます。
working tree index HEAD
hello.txt
greeting.txthello.txt
greet...
インデックス操作系
インデックスの内容を変更するコマンドを解説しま
す。
インデックス操作系
1. インデックスに変更を登録する
add <path>
add -p <path>
2. インデックスの変更を捨てる
reset HEAD -- <path>
インデックス操作系
1. インデックスに変更を登録する
add <path>
add -p <path>
2. インデックスの変更を捨てる
reset HEAD -- <path>
1. インデックスに変更を登録する
① add <path>
② add -p <path>
①<path>で指定したワーキングツリーの内容でイ
ンデックスの同名の<path>を上書きします。
add <path>
ワーキングツリーの greeting.txt と hello.txt が
ローカルな変更を持っている(編集されている)とし
ます。
working tree index
hello.txt
greeting.txthell...
add <path>
git add hello.txt を実行すると、ワーキングツリー
にある hello.txt の内容でインデックスの hello.txt
を上書きすることになります。
greeting.txt はインデックスに含まれませ...
greeting.txt
add <path>
インデックス=次回コミットの内容です。
コミットとしてふさわしい内容になるまで git add
<path> や git reset HEAD -- <path> (後述)で調
整しましょう。
w...
greeting.txt
add <path>
なお、ファイルの削除を反映する場合も Git 2.0 か
らは add コマンドで可能です。(古いGitの場合は
git rm <path>や git add -A <path>で反映します)
w...
1. インデックスに変更を登録する
① add <path>
② add -p <path>
②<path>で指定したワーキングツリーの内容とイ
ンデックスの同名の<path>の差分を選択してイン
デックスに登録します
greeting.txt
add -p <path>
ワーキングツリーの hello.txt がローカルな変更を
持っているとします。
working tree index
hello.txt
greeting.txthello.txt
greeting.txt
add -p <path>
add -p hello.txt を実行すると、対話的な処理が開
始され、ワーキングツリーとインデックスのhello.txt
の差分のハンクごとにインデックスにaddするかど
うかを選択でき...
greeting.txt
add -p <path>
結果としてワーキングツリーともHEADとも違う内
容の hello.txt をインデックスに登録することができ
ます。
working tree index
hello.txt
greeti...
インデックス操作系
1. インデックスに変更を登録する
add <path>
add -p <path>
2. インデックスの変更を捨てる
reset HEAD -- <path>
2. インデックスの変更を捨てる
① reset HEAD -- <path>
①<path>で指定したインデックスの内容を捨てて
HEAD の内容に戻すことができます。
greeting.txt
reset HEAD -- <path>
ワーキングツリーの hello.txt がローカルな変更を
持っており、インデックスにそれが登録されている
とします。
working tree index
hello.txt...
greeting.txt
reset HEAD -- <path>
git reset HEAD -- hello.txt によって、HEADの
hello.txt の内容でインデックスを更新します。つま
り、ワーキングツリーをもとに追加されて...
greeting.txt
reset HEAD -- <path>
ちなみに git init した直後だと git rm --cached
<path> を使う必要があります。いずれにしろ git
status にどうしたら良いか表示されてい...
コミット操作系
コミットを作成するコマンドを解説します。
コミット操作系
1. コミットを作成する
commit
merge <commit-ish>
cherry-pick <commit-ish>
revert <commit-ish>
コミット操作系
1. コミットを作成する
commit
merge <commit-ish>
cherry-pick <commit-ish>
revert <commit-ish>
1. コミットを作成する
① commit
② merge <commit-ish>
③ cherry-pick <commit-ish>
④ revert <commit-ish>
① インデックスの内容で、カレントブランチに新し
いコミット...
commit
現在のインデックスの内容で新しいコミットをカレン
トブランチに作ります。すでに解説したとおり、この
効果は正確には・・・
tree
5b94ca
index
working tree
local
change
tree
621a5...
commit
HEADを親とした新しいコミットを作成し、HEADが
指すブランチヘッドの参照先を今作ったコミットに
書き換える、という動作の結果がそのように見えて
います。
tree
5b94ca
index
working tree
loca...
1. コミットを作成する
① commit
② merge <commit-ish>
③ cherry-pick <commit-ish>
④ revert <commit-ish>
② HEADと指定した <commit-ish> をマージし...
merge <commit-ish>
マージは他のコミットによる変更を取り込む操作で
す。
ここではfooをチェックアウトした状態で bar をマー
ジしてみます。
foo
bar
HEAD
git merge bar
merge <commit-ish>
HEADとfooの両方の編集結果を持つ(マージし
た)新しいコミットを作成し・・・
New commit
foo
HEAD
foo
HEAD
bar
bar
git merge bar
merge <commit-ish>
HEADが指している参照を新しいコミットに移動し
ます。これがマージです。
foo
HEAD
foo
HEAD
bar
bar
New commitgit merge bar
マージコミット
このとき新しくできたコミットをマージコミットと言い
ます。親コミットとして複数のコミットが記録されて
いるコミットがマージコミットです。
foo
HEAD
foo
HEAD
bar
bar
merge
commitgit mer...
foo
HEAD
bar
3wayマージ
Gitで用いられるマージの手法は3wayマージと呼
ばれます。
3wayマージ
これはマージするふたつのコミットと、それらから最
も近い共通祖先の3つを使ってマージを行う、とい
うものです。
foo
HEAD
bar
3wayマージ
今回の例で言えば、foo, bar, およびそれらの共通
祖先(図示)を使うということです。
common
ancestor
foo
HEAD
bar
merge
commit
3wayマージ
マージする際に最適な共通祖先はマージベースと
も呼ばれます。これはコマンド git merge-base foo
bar で表示できます。
merge-base
foo
HEAD
bar
merge
commit
3wayマージ
3wayマージの特徴のひとつは、途中の変更(コミッ
ト)は考慮しないという点です。マージベース→foo
の差分、マージベース→barの差分をもとにマージ
コミットを作成します。
merge-base
foo
HEAD
bar
差...
3wayマージ
マージベースとマージ対象のコミットそれぞれの間
に複雑な変更がどれだけあろうとも、3つのコミット
を材料にマージされます。
merge-base
foo
HEAD
bar
merge
commit
HEAD
bar
3wayマージが使われないパターン
ふたつの差分のうちのひとつがなくなってしまう場
合は3wayマージになりません。
例えば図のような状態で git merge bar することを
考えます。
foo
HEAD
bar
3wayマージが使われないパターン
つまりマージベースとfoo(HEAD)が一致している
場合です。barがfooの子孫である場合とも言えま
す。
merge-base
foo
HEAD
bar
Fast-Forwardマージ
この場合は foo を単に bar まで進めます。これは
Fast-Forward マージ(FFマージ)とよばれていま
す。
merge-base
foo
HEAD
foo
merge --no...
bar
3wayマージが使われないパターン
逆のパターンも見てみましょう。つまり、上図の状
態で bar をチェックアウトし、 git merge foo する場
合です。
HEAD
foo
bar
3wayマージが使われないパターン
この場合もやはりマージベースは foo になります。
マージしようとしているコミット(foo)がマージベース
の場合、つまり祖先のコミットをマージしようとした
場合...
merge-base HEA...
bar
マージ済み(Already up-to-date)
Already up-to-date と表示されるだけで何もおこり
ません。
すでにマージ済みであるとみなされるからです。
merge-base HEAD
foo
マージの方向に注意
barをfooにマージした結果(左)とfooをbarにマージ
した結果(右)はツリーは同じになったとしても、別
物です。マージコミットに記録される親コミットの順
番が異なるからです。
foo
HEAD
foo
bar
bar...
ファーストペアレント
マージしたときのカレントブランチ側の親
=先に記録される親
=1番目に記録される親
=ファーストペアレントとなります。
foo
HEAD
foo
bar
bar
HEAD
first-parent
first-parent
ファーストペアレント
ファーストペアレントは他のVCSで言えばtrunk的
な意味合いがあります。
Gitでもファーストペアレントは特別扱いされる場合
があり、意識しておくと有用です。
foo
HEAD
foo
bar
bar
HEAD
fir...
ファーストペアレント
特にトピックブランチによる開発をする場合には統
合ブランチ(master等)側が常にファーストペアレン
トになるようにマージしましょう
foo
HEAD
foo
bar
bar
first-parent
first-par...
ファーストペアレント
ちなみにマージコミットを図示する場合、ファースト
ペアレントの系列はふつう直線上に書きます。例
外はありますが、fooからbarをマージしたときは大
抵左のように書きます。
foo
HEAD
foo
bar
bar
まっす...
マージ対象はコミットなら何でも可
マージ対象はブランチである必要はありません。
bar^ (「X^」はXの親コミットを指定する書き方) を
マージすれば、上図のようになります。SHA1指定
ももちろんOK
foo
HEAD
foo
HEAD
b...
1. コミットを作成する
① commit
② merge <commit-ish>
③ cherry-pick <commit-ish>
④ revert <commit-ish>
③ 指定した <commit-ish> と同じ差分のコミット...
cherry-pick <commit-ish>
チェリーピックはマージと同様、他のコミットによる
変更を取り込む操作です。ただし、マージとは異な
り単一のコミットを取り込みます。
foo に bd48f1 をチェリーピックしてみます。
foo...
cherry-pick <commit-ish>
取り込むと言っても、 bd48f1 のコミットやツリーが
そのままfooの上に作られるわけではありません。
そんなことできても嬉しくないですし。
foo
HEAD
bar
git cherry-...
cherry-pick <commit-ish>
実際のところ bd48f1^ と bd4f1 のツリーの差分
(patch)を取り出し…
foo
HEAD
bar
git cherry-pick bd48f1
bd48f1
foo
HEAD
...
cherry-pick <commit-ish>
そのパッチを foo に適用したツリーでコミットを新し
く作成する、という動作になります。
著作者、コミットメッセージはbd48f1のものを引き
継ぎますが、コミッターは更新されます。
foo
...
cherry-pickの使いどころ
開発ブランチから生えたトピックのコミットはより安
定したブランチにマージすると、トピックの開始点ま
での開発ブランチの内容も一緒に安定ブランチに
マージされてしまいます。
master
devel
maste...
cherry-pickの使いどころ
そのような場合に、チェリーピックであれば、コミット
の場所に関係なく、安全にそのコミットだけを取り
込むことができます。
master
devel
master
devel
git cherry-pick X...
cherry-pickの使いどころ
欲しいコミットが複数の場合はrebase --onto でま
るごと取ってくることも可能です。いずれにしろ、ブ
ランチ開始点が間違っている場合の対処法であ
り、常用するものではありません。
master
de...
cherry-pickの使いどころ
トピックの開始点に注意して、コミットの取込みはで
きるだけマージを使いましょう。(マージする必要の
ある統合ブランチのうち、最も古い(下流の)ものか
ら開始するのがコツです)
master
devel
dev...
1. コミットを作成する
① commit
② merge <commit-ish>
③ cherry-pick <commit-ish>
④ revert <commit-ish>
④ 指定した <commit-ish> を打ち消すような差分...
revert <commit-ish>
コミット32ff01をrevertするとします。
まず 32ff01 から 32ff01^ への差分(patch)を取り
出します。これは子から親へのパッチ(リバース
パッチ)です。
foo
HEAD
g...
revert <commit-ish>
そのリバースパッチをfooのツリーに適用して新し
いコミットを作ります。
foo
HEAD
git revert 32ff01
32ff01
foo
HEAD
32ff01
apply
revert <commit-ish>
32ff01 と revert commitの変更は互いに打ち消し
あい、結果としてHEADのツリーは 32ff01 による
変更がなかったかのような状態になります。
foo
HEAD
git rever...
ブランチ操作系
ブランチを作成・変更するコマンドを解説します。
ブランチ操作系
1. ブランチを作成/削除/名前変更する
branch <branch> [ <commit-ish> ]
branch -d | -D <branch>
branch -m [ <old> ] <new>
2. ブランチの指す...
ブランチ操作系
1. ブランチを作成/削除/名前変更する
branch <branch> [ <commit-ish> ]
branch -d | -D <branch>
branch -m [ <old> ] <new>
2. ブランチの指す...
1. ブランチを作成/削除/名前変更する
① branch <branch> [ <commit-ish> ]
② branch -d | -D <branch>
③ branch -m [ <old> ] <new>
① 指定したコミットに新...
branch <branch> [ <commit-ish> ]
branch は単にブランチヘッドとなる参照を作成し
ます。図はコミット32ff01にbarというブランチを作
成した場合。
foo
HEAD
git branch bar 32...
branch <branch> [ <commit-ish> ]
コミットを指定しなければHEADに新しい参照を作
ることになります。
foo
HEAD
git branch bar
foo
HEAD
bar
1. ブランチを作成/削除/名前変更する
① branch <branch> [ <commit-ish> ]
② branch -d | -D <branch>
③ branch -m [ <old> ] <new>
② 指定した <bran...
branch -d | -D <branch>
branch -d はブランチヘッド参照を削除します。-d
だとHEADの祖先に付いているブランチのみ削除
できます。
foo
HEAD
git branch -d bar
foo
HEAD
ba...
branch -d | -D <branch>
これはマージされていないブランチを削除しないた
めの安全装置です。上の場合、 buz を削除するこ
とはできません。
foo
HEAD
git branch -d buz
buz
foo
HEAD
branch -d | -D <branch>
HEADの祖先でないブランチを削除したければ、
branch -D を使います。
foo
HEAD
git branch -D buz
foo
HEAD
buz
1. ブランチを作成/削除/名前変更する
① branch <branch> [ <commit-ish> ]
② branch -d | -D <branch>
③ branch -m [ <old> ] <new>
③ ブランチ <old>...
branch -m [ <old> ] <new>
branch -m でブランチヘッドの名前を変更できま
す。
foo
HEAD
git branch -m buz bar
foo
HEAD
buz
bar
ブランチ操作系
1. ブランチを作成/削除/名前変更する
branch <branch> [ <commit-ish> ]
branch -d | -D <branch>
branch -m [ <old> ] <new>
2. ブランチの指す...
2. ブランチの指すコミットを変更する
① reset [ --hard ] <commit-ish>
① カレントブランチの参照が指すコミットを指定し
たコミットに変更し、そのコミットでインデックスを更
新します。--hardを指定した場合は...
reset [ --hard ] <commit-ish>
reset はカレントブランチが指す先を変更します。
例えば今作ったコミットの内容が間違えていた時
に、そのコミットをなかったことにする用途で git
reset HEAD^ を使いま...
reset [ --hard ] <commit-ish>
--hard をつけるとワーキングツリーが指定したコ
ミットで上書きされます。ブランチヘッドを他のコミッ
トに付け替えたい場合によく使います。
foo
HEAD
git reset -...
コミット・ブランチ複合操作系
コミット・ブランチを複合的に操作するコマンドを解
説します。実質的にはコミットの修正のために用い
られます。
コミット・ブランチ複合操作系
1. コミットを修正する
commit --amend
rebase <commit-ish>
コミット・ブランチ複合操作系
1. コミットを修正する
commit --amend
rebase <commit-ish>
1. コミットを修正する
① commit --amend
② rebase <commit-ish>
① インデックスの内容でHEADコミットを修正しま
す。実際にはHEADの兄弟として新しくコミットを作
り、カレントブランチをそこに移動しま...
commit --amend
foo
HEAD
git commit --amend
tree
5b94ca
index
commit --amendはHEADを修正するコマンドで
す。修正内容をインデックスにaddした状態を考え
ます。
commit --amend
foo
HEAD
git commit
tree
5b94ca
index
本来ここでコミットすれば、目的の内容を持った新
しいコミットが作成されますが、--amendをつけて
いると…
foo
HEAD
amen...
commit --amend
foo
HEAD
git commit --amend
tree
5b94ca
index
インデックスの内容でHEAD^を親とした新しいコ
ミット、つまりHEADの兄弟のコミットが作られ…
foo
HEAD
commit --amend
foo
HEAD
git commit --amend
tree
5b94ca
index
ブランチfooがHEADとともに新しく作られた兄弟コ
ミットの方に移動します。
foo
HEAD
commit --amend
foo
HEAD
git commit --amend
tree
5b94ca
index
以前のHEADは見えなくなりますから、結果として
ブランチfooの最新コミットが修正されたように見え
ます。
foo
HE...
1. コミットを修正する
① commit --amend
② rebase <commit-ish>
② 指定したコミット(これを含まない)からHEADま
でのコミットを一括して再作成します。
rebase <commit-ish>
ブランチbarを開発中、masterから分岐後のbar全
体を現在のmasterの先端に移動したい場合に
rebaseを使います。動きとしては…
master
HEAD git rebase master...
rebase <commit-ish>
まず master のコミットにHEADを移動し…
master
HEAD git rebase master
bar
master
bar
HEAD
rebase <commit-ish>
masterから分岐後のbarのコミットを順次 cherry-
pickのように差分を取り出しては適用し…
master
HEAD git rebase master
bar
master
bar
HEA...
rebase <commit-ish>
参照 bar を新しいコミットに付け替えてカレントブラ
ンチをbarに切り替えます。
master
HEAD git rebase master
bar
master
HEAD
bar
rebase <commit-ish>
応用として rebase -i を使ってcherry-pickする際に
編集を加えたり、コミットを取捨選択したり、といっ
たことを対話的に指定できます。
図では2つだったコミットを1つにまとめてます
ma...
rebase <commit-ish>
あるいは<commit-ish>に上流ブランチではなく、
祖先のコミットを指定することで、それ以降のコミッ
トを(ブランチを付け替えせずに)作りなおしたりでき
ます。
master
HEAD git re...
タグ操作系
タグを作ったり削除したりといった操作です。
タグ操作系
1. タグを作成/削除する
tag <tag> [ <commit-ish> ]
tag -a <tag> [ <commit-ish> ]
tag -d <tag>
1. タグを作成/削除する
① tag <tag> [ <commit-ish> ]
② tag -a <tag> [ <commit-ish> ]
③ tag -d <tag>
① 指定したコミットを指すタグ(参照)を作成します
tag <tag> [ <commit-ish> ]
指定したコミットに参照のタグを作成します。コミッ
トを指定しない場合、HEADが対象になります。
master
HEAD
git tag backup bar
bar
master
HEAD...
1. タグを作成/削除する
① tag <tag> <commit-ish>
② tag -a <tag> <commit-ish>
③ tag -d <tag>
② 指定したコミットを指すアノテーションタグを作成
します。
tag -a <tag> [ <commit-ish> ]
-a を指定するとアノテーションタグを作成します。
実際には指定したコミットを指すタグオブジェクト
(△)を作成し、それを指す参照のタグを作成しま
す。
master
HEAD
git...
1. タグを作成/削除する
① tag <tag> <commit-ish>
② tag -a <tag> <commit-ish>
③ tag -d <tag>
③ 指定したタグ(参照)を削除します。
tag -a <tag> [ <commit-ish> ]
-d を指定するとタグを削除します。アノテーションタ
グが指定された場合、タグオブジェクトはすぐに削
除されるわけではありませんが、そのうちGCで削
除されます。
master
HEA...
さまざまな調査系
いろいろなものを調査するためのコマンドです。実
に様々なコマンド・使い方があり、有名なものも多
いのですが、理解しておくと便利なもの・使い方を
中心に解説します。
さまざまな調査系
1. コミットの履歴を見る
log (範囲指定について)
gitk
2. 差分を見る
diff
log
3. なくしたものを探す
reflog, fsck
さまざまな調査系
1. コミットの履歴を見る
log (範囲指定について)
gitk
2. 差分を見る
diff
log
3. なくしたものを探す
reflog, fsck
1. コミットの履歴を見る
① log (範囲指定について)
② gitk
① 指定したコミット範囲の著作者やコミットメッセー
ジを表示します。
log (範囲指定について)
log はコミットメッセージ等のコミットの情報を表示
します。ここではコミットの範囲指定について有用
なものを紹介します。
master
HEAD
bar
foo
backup
log
log に何も指定しなければHEADを指定したことと
等価です。この場合、HEADから辿れる全コミット
が対象になります。
master
HEAD
bar
foo
backup
log <commit-ish>
コミットを指定した場合はその祖先全体が対象に
なります。この状態では master を指定すれば
HEAD を指定した場合と同じで…
master
HEAD
bar
foo
backup
log <commit-ish>
bar を指定すれば、barの祖先全体が対象になり
…
master
HEAD
bar
foo
backup
log <commit-ish>
foo を指定すれば、foo の祖先全体が対象になり
ます。
master
HEAD
bar
foo
backup
log <commit-ish>^
既出ですが、コミットを指す名前に ^ を加えると、そ
の親(ファーストペアレント)を指定したことになりま
す。master^ を指定すれば図の範囲になります。
master
HEAD
bar
foo
back...
log <commit-ish>^
ちなみに本来 master^ が指すのはこのコミット(黄
色)だけである点に注意してください。log が
master^から辿れる祖先全体を表示するのは、log
がそのような仕様だからです。
master
H...
log <commit-ish>^
^は繰り返し指定可能です。master^^であれば図
の範囲で…
master
HEAD
bar
foo
backup
log <commit-ish>^
master^^^であれば図の範囲になります。
^のn回指定には ~n という省略記法が用意されて
います。 master^^^ は master~3 と等価です。
master
HEAD
bar
foo
b...
log <commit-ish>^<n>
^ はファーストペアレントですが、 ^ の後ろには数
字で何番目の親かを指定できます。 backup^2 で
あれば図のようにbackupの2番めの親になりま
す。 ^^ や ~2 との違いに注意。
m...
log <commit-ish>^<n>
「^」の覚え方ですが、上図のようにマージしたコミッ
トの左側にファーストペアレント、右側に2番の親が
ある状態の矢印の形と「^」を関連付けると覚えや
すいです。
1 2
^2
^と~の組み合わせ
^[n] 指定(と~m 指定)を繰り返すことで祖先であれ
ば任意のコミットを指定できます。
master^^2^であれば図の範囲…
master
HEAD
bar
foo
backup
^と~の組み合わせ
master~2^2であれば図の範囲になります。
先に書いたとおりどんな祖先でも指定可能です
が、実際には log や gitk などで目的のコミットの
SHA1を調べて直接指定するほうが楽です…
master
HEAD
b...
log <commit-ish>..<commit-ish>
コミットをふたつのドットでつないだ範囲指定法が
あります。X..Y であれば、Y およびその祖先に含
まれるコミットからXおよびその祖先をのぞいた範
囲、つまり Y - X を表しま...
log <commit-ish>..<commit-ish>
master..bar を見てみましょう。maser..bar は bar
の祖先から master の祖先を取り除いたものです
が、まず bar の祖先は図のような黄色の範囲で
す...
log <commit-ish>..<commit-ish>
master の祖先は図の青の範囲ですから、これを
取り除くと…
master
HEAD
bar
foo
backup
log <commit-ish>..<commit-ish>
最終的に上図の黄色い部分がのこります。 これが
master..bar という書き方が表す範囲です。
master
HEAD
bar
foo
backup
log <commit-ish>..<commit-ish>
逆に bar..master を見てみます。master の祖先
は図の青の範囲で…
master
HEAD
bar
foo
backup
log <commit-ish>..<commit-ish>
bar の祖先は図の黄色い部分ですから、これを取
り除くと…
master
HEAD
bar
foo
backup
log <commit-ish>..<commit-ish>
bar..master は図の青の範囲ということになりま
す。
master
HEAD
bar
foo
backup
log <commit-ish>...<commit-ish>
なお、ドットを3つにすると、 (X - Y) ∪ (Y - X)の意
味になります。 これは bar..master と master..bar
の両方という意味です。bar......
log --first-parent
ファーストペアレントだけをたどるオプションもあり
ます。log --first-parent master であれば図の範囲
になります。統合ブランチのログのサマライズに非
常に便利です。
master
H...
1. コミットの履歴を見る
① log
② gitk
② 指定したコミット範囲のコミットグラフをGUIで表
示します。
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
コンセプトから理解するGitコマンド
Próximos SlideShares
Carregando em…5
×

コンセプトから理解するGitコマンド

33.555 visualizações

Publicada em

会社関係の勉強会向けに作った資料です。
パラパラマンガ調のためページ数は多いですが、内容は基礎的なものです。

このスライドを読み終わった人にオススメ: 「図解gitworkflows(7)」 www.slideshare.net/ktateish/gitworkflows7

Publicada em: Software
  • ACCESS that WEBSITE Over for All Ebooks (Unlimited) ......................................................................................................................... DOWNLOAD FULL PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... DOWNLOAD FULL EPUB Ebook here { http://bit.ly/2m77EgH } ......................................................................................................................... Download Full PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m77EgH }
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui
  • accessibility Books Library allowing access to top content, including thousands of title from favorite author, plus the ability to read or download a huge selection of books for your pc or smartphone within minutes ,Download or read Ebooks here ... ......................................................................................................................... Download FULL PDF EBOOK here { http://bit.ly/2m6jJ5M }
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui
  • If you want to download or read this book, Copy link or url below in the New tab ......................................................................................................................... DOWNLOAD FULL PDF EBOOK here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download Doc Ebook here { http://bit.ly/2m6jJ5M } ......................................................................................................................... .........................................................................................................................
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui
  • If you want to download or read this book, copy link or url below in the New tab ......................................................................................................................... DOWNLOAD FULL PDF EBOOK here { http://bit.ly/2m6jJ5M } ......................................................................................................................... Download EPUB Ebook here { http://bit.ly/2m6jJ5M } .........................................................................................................................
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui
  • -- DOWNLOAD THIS BOOKS INTO AVAILABLE FORMAT -- ......................................................................................................................... ......................................................................................................................... Download FULL PDF EBOOK here { http://bit.ly/2m77EgH } ......................................................................................................................... (Unlimited)
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui

コンセプトから理解するGitコマンド

  1. 1. 【幕張読書会】 コンセプトから理解する Gitコマンド 基礎編 @ktateish
  2. 2. はじめに Gitのコマンドってわかりにくいですよね? Git内部のコンセプトを理解するとGitコマンドにつ いての理解がはかどります。 この資料はGitのコンセプトからコマンドを理解する ことを目的として作成しました。
  3. 3. 注意 Gitを使ったことのあるエンジニア向けです。 ● add/commit/pushしたことくらいならあるよ、的 な人を想定。他VCSの経験があればGitを使っ たことがなくてもOK ● Unix関連のベーシックなスキル・コンセプトは解 説しません ● 正確さよりもわかりやすさ優先 (正確な情報はマニュアル読んでね)
  4. 4. 目次 第1章 コミットとオブジェクト(p.5) 第2章 参照: ブランチとタグ(p.74) 第3章 インデックスとワーキングツリー(p.134) 第4章 コンセプトから理解するGitコマンド (p.161 - p405)
  5. 5. 第1章 コミットとオブジェクト
  6. 6. そもそもバージョン管理とは? memo-20140425.txt memo-20140428.txt memo-20140430.txt ・・・ こういうやつですね。 これも一応バージョン管理
  7. 7. 何でバージョン管理したいのか? いろいろありますが根源的なのはだいたい 1. 加えた変更がまずかったら元にもどしたい 2. 何処をどう変更したのか知りたい 3. 誰がなぜ変更したのか知りたい あたりだと思います
  8. 8. Gitにおけるバージョン Gitにおいてバージョンは「コミット」という単位で管 理します 他のVCSだとリビジョンやチェンジセットなどと言わ れるやつのことです。 コミットを作成する行為も「コミット(する)」と言いま す。これは他VCSと同様。
  9. 9. Gitにおけるコミット ひとつのコミットは以下の情報からなります ディレクトリツリーのスナップショット + ひとつ前のコミット(親コミット) + その他(コミッタ名、コミットメッセージとか)
  10. 10. ちなみに 1コミットごとに完全なスナップショットを 保持しています。変化を記録しているわけではな いので「チェンジセット」とは呼びません。 親コミットを記録しているので、差分は必要になっ たときに作ればいいや、という思想です。
  11. 11. コミットが バージョン管理の要求を満たす 1. 加えた変更がまずかったら元にもどしたい ➔ いつでも昔のコミットを取り出して戻せる 2. 何処をどう変更したのか知りたい ➔ コミット同士を比較することで可能 3. 誰がなぜ変更したのか知りたい ➔ コミットメッセージを見れば良い
  12. 12. コミット
  13. 13. コミットの詳細 コミット = ツリーのスナップショットへのポインタ + 親コミットへのポインタ + 著作者・著作日時 + コミッター・コミット日時 + コミットメッセージ
  14. 14. コミットを図にすると コミット 親コミット = ひとつ前のコミット ツリーのスナップショット 著作者等の情報 コミッター等の情報 コミットメッセージ ツリーへのポインタ 親コミットへの ポインタ
  15. 15. 実際に見てみよう % git cat-file -p HEAD tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac parent 897d06bcb89a12574271e74e90048cb26fe5f6bb author John Smith <js@example.com> 1398774567 +0900 committer John Smith <js@example.com> 1398774567 +0900 Add new file: greeting2.txt
  16. 16. 実際に見てみよう % git cat-file -p HEAD tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac parent 897d06bcb89a12574271e74e90048cb26fe5f6bb author John Smith <js@example.com> 1398774567 +0900 committer John Smith <js@example.com> 1398774567 +0900 Add new file: greeting2.txt cat-file: Gitに登録されたオブジェクト(データ)をダンプするコマンド -p: いい感じの出力にするオプション HEAD: 最新のコミット git cat-file -p HEAD →「最新のコミットオブジェクトをいい感じに表示してくれ」
  17. 17. 実際に見てみよう % git cat-file -p HEAD tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac parent 897d06bcb89a12574271e74e90048cb26fe5f6bb author John Smith <js@example.com> 1398774567 +0900 committer John Smith <js@example.com> 1398774567 +0900 Add new file: greeting2.txt tree: ディレクトリツリーのスナップショット (2e4038…: treeオブジェクトの名前)
  18. 18. 実際に見てみよう % git cat-file -p HEAD tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac parent 897d06bcb89a12574271e74e90048cb26fe5f6bb author John Smith <js@example.com> 1398774567 +0900 committer John Smith <js@example.com> 1398774567 +0900 Add new file: greeting2.txt parent: 親コミット
  19. 19. 実際に見てみよう % git cat-file -p HEAD tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac parent 897d06bcb89a12574271e74e90048cb26fe5f6bb author John Smith <js@example.com> 1398774567 +0900 committer John Smith <js@example.com> 1398774567 +0900 Add new file: greeting2.txt author: コミット内容の作者+作成日時 committer: authorが作った内容を実際のコミットオブジェクトにした人+日時 大抵の場合 author=committer なので今のところ気にしなくて良い
  20. 20. 実際に見てみよう % git cat-file -p HEAD tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac parent 897d06bcb89a12574271e74e90048cb26fe5f6bb author John Smith <js@example.com> 1398774567 +0900 committer John Smith <js@example.com> 1398774567 +0900 Add new file: greeting2.txt “Add new…”: コミットメッセージ
  21. 21. 実際に見てみよう % git cat-file -p HEAD tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac parent 897d06bcb89a12574271e74e90048cb26fe5f6bb author John Smith <js@example.com> 1398774567 +0900 committer John Smith <js@example.com> 1398774567 +0900 Add new file: greeting2.txt コミット = ツリーのスナップショットへのポインタ + 親コミットへのポインタ + 著作者情報+コミッター情報 + コミットメッセージ
  22. 22. つまりコミットとは コミット 親コミット = ひとつ前のコミット (897d06...) ツリーのスナップショット (2e4038…) コミッター等の情報 コミットメッセージ ツリーへのポインタ 親コミットへの ポインタ
  23. 23. 少し周辺の情報を補うと コミット (03ccb3...) 親コミット = ひとつ前のコミット (897d06...) ツリーのスナップショット (2e4038…) ツリーのスナップショット (57e952…)
  24. 24. 少し周辺の情報を補うと コミット (03ccb3...) 親コミット = ひとつ前のコミット (897d06...) ツリーのスナップショット (2e4038…) ツリーのスナップショット (57e952…) 親の名前(897d06…)と同様、全てのコミットには必 ず名前(03ccb3...のような文字列)がある 親コミットもツリーへのポインタと・・・ そのさらに親コミットへのポインタを持つ
  25. 25. コミットが積み重なると コミット ツリー コミット ツリー ツリー ツリー コミット ツリー コミット → コミットグラフになる (コミットが決まればツリーも一意 に決まるので、図示する際は普通 ツリーを省略します。) コミット
  26. 26. コミットは親を複数持つことも可能 コミット ツリー コミット ツリー ツリー ツリー コミット ツリー コミット いわゆるマージコミットです。マー ジコミットを作成する行為を「マー ジする」と言います。 本資料では深く解説しません コミット コミット ツリー コミット ツリー ツリー ツリー コミット コミット
  27. 27. ところで名前 (03ccb3…)って結局何? コミット (03ccb3...) 名前=オブジェクトの内容のSHA1値です
  28. 28. 先頭数桁だけでもユニークな名 前になるので、この省略名 (abbrev)をしばしば使う。 つまりコミット 03ccb3…の場合は コミット (03ccb3...) 内容のSHA1を計算 実際にはオブジェクトの型(commit, tree, blob,etc…)、サイズ情報等を含む % git cat-file -p 03ccb3 tree 2e4038cce3649c830daaf38f6e411b4d55d5b7ac parent 897d06bcb89a12574271e74e90048cb26fe5f6bb author John Smith <js@example.com> 1398774567 +0900 committer John Smith <js@example.com> 1398774567 +0900 Add new file: greeting2.txt 03ccb30ce6b8b7d157b6d28fb479257eb424af02 名前 (オブジェクト名)
  29. 29. そういえばツリーにも名前があった コミット 親コミット ツリーのスナップショット (2e4038…) コレがツリーのオブジェクト名
  30. 30. ツリー
  31. 31. 図にすると tree 2e4038... (root) tree f18bca… img blob ce0136... greeting.txt blob 64e502... greeting2.txt blob 6935eb... screenshot.jpg こんな感じです。先ほどの図で コミットから指されてたやつを詳細化してます コミット 親コミット ツリーのスナップショットtree: 2e4038
  32. 32. ツリーの中を実際に見てみよう % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img ツリーオブジェクトの中身=3種類の情報をエントリの数だけ記録 (1行1エントリで表示されています) 3種類の情報= 1. モード(タイプ) 2. オブジェクト名 3. パス名
  33. 33. ツリーエントリ:モード % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img モード(タイプ): tree=ツリーオブジェクト、blob=tree以外≒普通のファイル symlinkやスクリプト等の実行ビットも記録可能
  34. 34. ツリーエントリ:オブジェクト名 % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img オブジェクト名: greeting.txt や greeting2.txt のオブジェクト名。treeやcommitと同様、それぞれ の内容のSHA1値(ce013…や64e50…)になっている。
  35. 35. ツリーエントリ:パス名 % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img パス名: 人間が読みやすい名前をオブジェクトにつけている。 いわゆるファイル名やディレクトリ名のこと。
  36. 36. ツリーは再帰構造 % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img treeエントリには他のtreeを含められます = 再帰構造をとれます。 ここには f18bca... というオブジェクト名のtreeが含まれています。 % git cat-file -p f18bca 100644 blob 6935eb316843d05f389830ecb4022fbc9debbea5 screenshot.jpg もちろん f18bca… の中身も確認できます。screenshot.jpg というエントリ名 で 6935e… というblobが含まれているのがわかります。
  37. 37. 続いてツリーに記録されたブロブ % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img について見ていきます。greeting.txtの実体は ce0136という名前のブロブオブジェクト(blob)で す。
  38. 38. ブロブ
  39. 39. ブロブの中を実際に見てみよう % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img ブロブ(blob)は型のないオブジェクトのこと。大抵の場合は普通のファイルです。 greeting.txtはce0136...というオブジェクトです。 % git cat-file -p ce0136 hello 中身を見てみると “hello" というテキストです。
  40. 40. ブロブの中を実際に見てみよう 実際に “hello” (+改行) という文字列をhash-objectコマンドでGit オブジェクト化するこ とができます。 オブジェクト化すると、やはり ce0136… という名前のオブジェクトになりました。 % git cat-file -p ce0136 hello % echo hello | git hash-object --stdin ce013625030ba8dba906f756967f9e9ca394464a
  41. 41. ブロブを作ってみる hash-object -w でGitのオブジェクトデータベースに書き込めます。 “tekitou na mojiretsu”(+改行) は 2da935 というオブジェクトになりました。 % echo "tekitou na mojiretsu " | git hash-object --stdin -w 2da9358db1fe68b3c8cf0196bfaf82ee0d6f9103 % ls .git/objects/ 2d/a9358db1fe68b3c8cf0196bfaf82ee0d6f9103 .git/objects/2d/a9358db1fe68b3c8cf0196bfaf82ee0d6f9103 % git cat-file -p 2da935 tekitou na mojiretsu 作成したオブジェクトをcat-file -pで2da935を確認すると、書き込んだ内容と同じ” tekitou na mojiretsu”(+改行)を取り出せました。
  42. 42. ところでファイル名がでてきませんね % echo "tekitou na mojiretsu " | git hash-object --stdin -w 2da9358db1fe68b3c8cf0196bfaf82ee0d6f9103 % ls .git/objects/ 2d/a9358db1fe68b3c8cf0196bfaf82ee0d6f9103 .git/objects/2d/a9358db1fe68b3c8cf0196bfaf82ee0d6f9103 % git cat-file -p 2da935 tekitou na mojiretsu ブロブオブジェクトの作成・取り出しにファイル名(パス名)が一切登場しなかったことを 少し覚えておいてください。 Gitデータベースにおける全てのオブジェクトの名前は常にSHA1値です。
  43. 43. ではファイル名はどこにあるのか % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img greeting.txtの実体はce0136というオブジェクトで すが、ce0136自体には “greeting.txt” という名前 は記録してませんでした。 ”greeting.txt”という名前を記録しているのは、 tree オブジェクト(2e4038)です。
  44. 44. 再び ツリー
  45. 45. ツリーとは % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img ● オブジェクトの属性、名前、パス名(ファイル名) を記録するためのオブジェクト ● 再帰的にツリー構造を形成 ● パス名はツリーが記録しており、記録されるオブ ジェクト側では持っていない これ、何かに似てるデータ構造ですよね。
  46. 46. いったい何に似ているって言うんだー % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img % git cat-file -p f18bca 100644 blob 6935eb316843d05f389830ecb4022fbc9debbea5 screenshot.jpg % ls -liR 808494 -rw-r--r-- 1 js js 6 May 1 08:25 greeting.txt 808590 -rw-r--r-- 1 js js 13 May 1 08:25 greeting2.txt 917641 drwxr-xr-x 2 js js 4096 May 1 08:25 img/ ./img: 917647 -rw-r--r-- 1 js js 109350 May 1 08:25 screenshot.jpg
  47. 47. 明らかにUnixのディレクトリですね % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img % git cat-file -p f18bca 100644 blob 6935eb316843d05f389830ecb4022fbc9debbea5 screenshot.jpg % ls -liR 808494 -rw-r--r-- 1 js js 6 May 1 08:25 greeting.txt 808590 -rw-r--r-- 1 js js 13 May 1 08:25 greeting2.txt 917641 drwxr-xr-x 2 js js 4096 May 1 08:25 img/ ./img: 917647 -rw-r--r-- 1 js js 109350 May 1 08:25 screenshot.jpg モード/stat オブジェクト名/inode パス名/リンク
  48. 48. 再び図にしてみます tree 2e4038... (root) tree f18bca… img % git cat-file -p 2e4038 100644 blob ce013625030ba8dba906f756967f9e9ca394464a greeting.txt 100644 blob 64e50281e4e0ebbbdc438095b6a222931ec0240f greeting2.txt 040000 tree f18bca942070f88dfc217a58d8766376fb642abc img % git cat-file -p f18bca 100644 blob 6935eb316843d05f389830ecb4022fbc9debbea5 screenshot.jpg blob ce0136... greeting.txt blob 64e502... greeting2.txt blob 6935eb... screenshot.jpg どう見ても ディレクトリです。 本当に(ry
  49. 49. オブジェクトの格納状況はこんな感じ ce0136 2e4038 f18bca64e502 6935eb オブジェクト名が Gitデータベース内に格納されたコンテンツを指定 % find .git/objects -type f .git/objects/b0/de5d4beb96ad900811b3d9e115487fac54f99a .git/objects/50/d659153f572c2ee2655c54d8084d987613d796 .git/objects/8c/6d0205c764e18d26f411770c081628e076e51f .git/objects/f1/8bca942070f88dfc217a58d8766376fb642abc .git/objects/ce/013625030ba8dba906f756967f9e9ca394464a .git/objects/89/7d06bcb89a12574271e74e90048cb26fe5f6bb .git/objects/cf/2d7699c6f20728bf126c8af08e7874a84b8696 .git/objects/8e/19af5536b93bcdcdf9d7c5b2df89d15c5876e8 .git/objects/b4/9b64efff762751cbc746633bc39be3e32090ad .git/objects/69/35eb316843d05f389830ecb4022fbc9debbea5 .git/objects/49/6cd51216313fc969a1f61d5ebf96a843eb57e0 .git/objects/57/e9529754dc514a3ec10db2ff882018fbe1fcbf .git/objects/2e/4038cce3649c830daaf38f6e411b4d55d5b7ac .git/objects/03/ccb30ce6b8b7d157b6d28fb479257eb424af02 .git/objects/64/e50281e4e0ebbbdc438095b6a222931ec0240f .git/objects/a8/0202bb5efd9949dc61fc7a8da48d0c8ac4faf0
  50. 50. 各treeからの矢印にすると ce0136 2e4038 f18bca64e502 6935eb こんな感じ % find .git/objects -type f .git/objects/b0/de5d4beb96ad900811b3d9e115487fac54f99a .git/objects/50/d659153f572c2ee2655c54d8084d987613d796 .git/objects/8c/6d0205c764e18d26f411770c081628e076e51f .git/objects/f1/8bca942070f88dfc217a58d8766376fb642abc .git/objects/ce/013625030ba8dba906f756967f9e9ca394464a .git/objects/89/7d06bcb89a12574271e74e90048cb26fe5f6bb .git/objects/cf/2d7699c6f20728bf126c8af08e7874a84b8696 .git/objects/8e/19af5536b93bcdcdf9d7c5b2df89d15c5876e8 .git/objects/b4/9b64efff762751cbc746633bc39be3e32090ad .git/objects/69/35eb316843d05f389830ecb4022fbc9debbea5 .git/objects/49/6cd51216313fc969a1f61d5ebf96a843eb57e0 .git/objects/57/e9529754dc514a3ec10db2ff882018fbe1fcbf .git/objects/2e/4038cce3649c830daaf38f6e411b4d55d5b7ac .git/objects/03/ccb30ce6b8b7d157b6d28fb479257eb424af02 .git/objects/64/e50281e4e0ebbbdc438095b6a222931ec0240f .git/objects/a8/0202bb5efd9949dc61fc7a8da48d0c8ac4faf0
  51. 51. Unixのファイルシステムの場合は 808494 808312 917641808590 917647 inodeがデータブロックを(間接的に)指定します スーパーブロック iノードテーブル データ領域
  52. 52. 各ディレクトリのデータブロックから 808494 808312 917641808590 917647 矢印を引くとこんな感じ スーパーブロック iノードテーブル データ領域
  53. 53. そっくりだ! Gitのtreeと オブジェクトデータベース Unixのディレクトリと ファイルシステム ce0136 2e4038 f18bca64e502 6935eb % find .git/objects -type f .git/objects/b0/de5d4beb96ad900811b3d9e115487fac54f99a .git/objects/50/d659153f572c2ee2655c54d8084d987613d796 .git/objects/8c/6d0205c764e18d26f411770c081628e076e51f .git/objects/f1/8bca942070f88dfc217a58d8766376fb642abc .git/objects/ce/013625030ba8dba906f756967f9e9ca394464a .git/objects/89/7d06bcb89a12574271e74e90048cb26fe5f6bb .git/objects/cf/2d7699c6f20728bf126c8af08e7874a84b8696 .git/objects/8e/19af5536b93bcdcdf9d7c5b2df89d15c5876e8 .git/objects/b4/9b64efff762751cbc746633bc39be3e32090ad .git/objects/69/35eb316843d05f389830ecb4022fbc9debbea5 .git/objects/49/6cd51216313fc969a1f61d5ebf96a843eb57e0 .git/objects/57/e9529754dc514a3ec10db2ff882018fbe1fcbf .git/objects/2e/4038cce3649c830daaf38f6e411b4d55d5b7ac .git/objects/03/ccb30ce6b8b7d157b6d28fb479257eb424af02 .git/objects/64/e50281e4e0ebbbdc438095b6a222931ec0240f .git/objects/a8/0202bb5efd9949dc61fc7a8da48d0c8ac4faf0 808494 808312 917641808590 917647 スーパーブロック iノードテーブル データ領域
  54. 54. つまりGitのオブジェクトは tree 2e4038... (root) tree f18bca… img blob ce0136... greeting.txt blob 64e502... greeting2.txt blob 6935eb... screenshot.jpg Unixのファイルシステムと言えます
  55. 55. もちろんそれだけじゃありません tree 2e4038... (root) tree f18bca… img blob ce0136... greeting.txt blob 64e502... greeting2.txt blob 6935eb... screenshot.jpg 各オブジェクトはzlibで圧縮されて格納されます つまり圧縮ファイルシステムです
  56. 56. 内容が同じファイルを追加すると コンテンツが同じ = SHA1値が同じ = 同じオブジェクト=もうある % find .git/objects -type f .git/objects/b0/de5d4beb96ad900811b3d9e115487fac54f99a .git/objects/50/d659153f572c2ee2655c54d8084d987613d796 .git/objects/8c/6d0205c764e18d26f411770c081628e076e51f .git/objects/f1/8bca942070f88dfc217a58d8766376fb642abc .git/objects/ce/013625030ba8dba906f756967f9e9ca394464a .git/objects/89/7d06bcb89a12574271e74e90048cb26fe5f6bb .git/objects/cf/2d7699c6f20728bf126c8af08e7874a84b8696 .git/objects/8e/19af5536b93bcdcdf9d7c5b2df89d15c5876e8 .git/objects/b4/9b64efff762751cbc746633bc39be3e32090ad .git/objects/69/35eb316843d05f389830ecb4022fbc9debbea5 .git/objects/49/6cd51216313fc969a1f61d5ebf96a843eb57e0 .git/objects/57/e9529754dc514a3ec10db2ff882018fbe1fcbf .git/objects/2e/4038cce3649c830daaf38f6e411b4d55d5b7ac .git/objects/03/ccb30ce6b8b7d157b6d28fb479257eb424af02 .git/objects/64/e50281e4e0ebbbdc438095b6a222931ec0240f .git/objects/a8/0202bb5efd9949dc61fc7a8da48d0c8ac4faf0 ce0136 ce0136
  57. 57. 同じ内容なら同じオブジェクト tree ……... (root) tree ……... img blob ce0136... greeting.txt blob 64e502... greeting2.txt blob 6935eb... screenshot.jpg つまり重複排除圧縮ファイルシステムです blob ce0136... hello.txt
  58. 58. 改竄検知
  59. 59. さきほどのページの図 おかしなところがあったことを おわかりいただけただろうか Google Docsって隷書フォント使えないの ?(´・ω・`)
  60. 60. treeのオブジェクト名が変わった… tree ......... (root) tree ……... img blob ce0136... greeting.txt blob 64e502... greeting2.txt blob 6935eb... screenshot.jpg ...とでもいうのだろうか。 blob ce0136... hello.txt 隷書フォント(´・ω・`)
  61. 61. はい。treeはツリーエントリを 内容とするオブジェクトなので tree 771c10... (root) tree 716186… img ファイルの追加・削除等々、構造が変わればtreeオ ブジェクトは別のものになります ←ファイルを追加 tree 2e4038... (root) tree f18bca… img ←変化 ←変化
  62. 62. さらにtreeはblobの名前を持つので tree fe5448... (root) tree f34fd4… img blob=ファイルの内容が1bitでも変われば連鎖的に rootのtreeオブジェクトが変わります ↑”hellp”に変えてコミット =1bit変更してコミット tree 771c10... (root) tree 716186… img ↑中身は”hello”でした blob ce0136... hello.txt blob d7a963... hello.txt ←変化 ←変化 ←変化
  63. 63. ツリーを構成する全情報のうち1bitでも変 更されればrootの名前で検知可能 tree fe5448... (root) tree f34fd4… img blob ce0136... greeting.txt blob 64e502... greeting2.txt blob 6935eb... screenshot.jpg つまり 改竄(破損)検知 重複排除圧縮ファイルシステムです blob d7a963... hello.txt
  64. 64. 逆にrootのオブジェクトが同じなら tree fe5448... (root) 下をチェックしなくても全体が同じだとわかる → ツリー同士の比較が爆速 tree fe5448... (root) = イコール diff-treeの場合。ファイル内容まで取り出して比較するとそれなりに遅い
  65. 65. tree: fe5448 さらにさらに tree (fe5448) ツリーはコミットごとに記録 されるのでした。 →バージョンを記録 commit (8b0e1d) commit (f78673) tree:771c10 parent: f78673 parent: ... tree (771c10)
  66. 66. 改竄(破損)検知はコミットにも伝搬 コミットは親コミットの名前を含んで います。 →ツリー全体を含む祖先のコミット の情報のうち「何か」が1bitでも異 なれば、それ以外すべて同一でも 子孫は全て別物になります。 ef1046 09a80f 5c0ed0 8b0e1d f78673 003b47 995f60 995f60 fe5448 9d2296 771c10 0eaea3 6a4fcc 6a4fcc fe5448 771c10 変更が伝搬
  67. 67. 改竄(破損)検知 バージョン管理 重複排除 圧縮 ファイルシステム それがGitだ!(ドヤァ まとめると tree commit tree commit tree commit tree commit tree commit
  68. 68. 1bitでも違えば異なるオブジェクト →データ量が肥大化(packで解決) ツリーのスナップショットで管理 →単一ファイルの変化の追跡が苦手 (経由する全てのコミットでいちいちtree をたどってオブジェクトが変わっている か調べる必要がある) もちろん欠点もあります tree commit tree commit tree commit tree commit tree commit
  69. 69. すでに散々出てきましたが 最後に改めてオブジェクトについてまとめておきま す。 オブジェクトとはGitが管理する情報の単位です。
  70. 70. Gitオブジェクトの特徴 1. commit, tree, blob 等の型がある 2. オブジェクト名はコンテンツのSHA1値 →同じ内容のオブジェクトは区別されない 3. 各commitから親commitとtreeを辿れる 4. treeから他のtree/blobを辿れる 5. 辿る先はオブジェクト名で記録している →その結果...
  71. 71. Gitオブジェクトの特徴 ふたつのオブジェクトの名前が同じなら、そこから 辿れる全オブジェクトが構成する構造全体にわ たって同じ内容であることが保証される e.g. ● blob同士が同じ名前なら同じファイル ● tree同士が同じ名前なら同じディレクトリ構成 ● commit同士が同じ名前なら、先祖代々のcommitにわ たって同じ
  72. 72. ここまでに出てきた主なコンセプト コミット 親コミット コミットグラフ ツリー ブロブ オブジェクト 改竄検知
  73. 73. コマンドの解説はもう少し先です コミット 親コミット コミットグラフ ツリー ブロブ オブジェクト 改竄検知 参照 シンボリックレフ ブランチ タグ(参照) タグ(オブジェクト) インデックス ワーキングツリー
  74. 74. 第2章 参照: ブランチとタグ
  75. 75. 参照
  76. 76. 参照とは オブジェクト(主にコミット)につけられる、人間が読 みやすい名前のこと。 オブジェクト名(SHA1値)は覚えにくいので、覚えて おいたほうが便利なオブジェクトには参照をつけま す。 参照はレフ(ref, reference)とも呼ばれます。
  77. 77. こんな感じです。master という参照は有名です よね。 参照を図にすると ef1046 09a80f master これで “master” と書いてやれば、わざわざ ” ef1046”とかSHA1値を書かないですみます。 commit commit
  78. 78. 参照の実体を見てみよう 参照の実体はオブジェクト名を含んだただのテキ ストファイルです。 % cat .git/refs/heads/ master ef1046a0117da8872b73fe72528c1fd9facd95ab ef1046 master gcやcloneした直後のリポジトリでは .git/packed-refs にまとめて書かれている場合もあります
  79. 79. 保存場所で参照の種類が決まる refs/heads/ 配下の参照=ブランチ refs/remotes/ 配下 =リモート追跡ブランチ refs/tags/ 配下=タグ % cat .git/refs/ heads/master ef1046a0117da8872b73fe72528c1fd9facd95ab % cat .git/refs/ remotes/origin/master ef1046a0117da8872b73fe72528c1fd9facd95ab % cat .git/refs/ tags/backup 09a80f7e839b0ba298652eeaff523c0ac9427df8 ef1046 09a80f master backup origin/master アノテーションタグについては後述
  80. 80. GCとの関係 参照には他に重要な役割がひとつあります。 それは参照から到達可能なコミットはgit gcで削除 されない、というものです。 (削除されてほしくなければ参照を作っておく) master ←削除対象 ←削除対象
  81. 81. 参照を参照する参照もあります origin/HEAD -> origin/master という表示は見たこ とがあるのではないでしょうか。 この手の参照をシンボリックレフといいます。 % git branch -a * master remotes/origin/HEAD -> origin/master remotes/origin/maint remotes/origin/master remotes/origin/next remotes/origin/pu
  82. 82. シンボリックレフ
  83. 83. 参照を参照する参照=シンボリックレフ 実体であるファイルの中身はコミットではなく別の 参照のパスです。 図示すると右のような感じ。 コミットを直接は指さず、参照を指しています % cat .git/refs/remotes/ origin/HEAD ref: refs/remotes/origin/master origin/master origin/HEAD
  84. 84. 最もよく使うシンボリックレフ みんなが一番お世話になっているシンボリック レフは HEAD です。 foo % cat .git/HEAD ref: refs/heads/foo HEAD がブランチを指している場 合*、指されているブランチをカレ ントブランチと言いいます。 上図の状態だとカレントブランチは foo HEAD * HEADがただの参照の場合もある
  85. 85. ブランチ
  86. 86. ブランチとは ブランチもタグも同じ参照だとすると何が違うの でしょうか? タグは「ある時点のコミットを定常的に指す」とい う役割があり、 ブランチには「コミットを新しく作る場所を指す」と いう役割があります。
  87. 87. 動作の違いはコミットしたとき カレントブランチにコミットすると、ブランチは自 動的に新しくできたコミットを指しますが、タグの 場合は動きません。 branch tag tagbranch “branch”をチェックアウトしてコミット作成 “tag”をチェックアウトしてコミット作成 新しいコミット 新しいコミット HEAD HEAD HEAD HEAD
  88. 88. この動作により ブランチであればコミットするたびにブランチが 成長していきます。 branch branch HEAD HEAD branch HEAD branch HEAD
  89. 89. より正確には ref HEADがrefを指している HEAD ref 新しいコミット HEAD HEADが参照を指している場合(≒HEADがシ ンボリックレフの場合)、コミット時に指されてい る参照が新しいコミットに追従します。
  90. 90. 実はHEADが「新コミット作成場所」 新しいコミット HEAD HEAD 新しいコミットは HEADに作られる 新しいコミットはチェックアウトしているコミット、 つまりHEADをたどって得られるコミットを親とし て作成されます。 実はコミット作成にブランチは関係なかったんで す。
  91. 91. じゃあブランチは一体何? 正確には「HEADがシンボリックレフで指すこと ができる参照」がブランチです。 ブランチ以外の参照はチェックアウトしても HEADはその先のコミットを直接指すただの参 照になってしまいます。 ref HEAD ref HEAD チェックアウトしたのがブランチ チェックアウトしたのがブランチ以外 (タグ等) もちろんHEADをエディタ等で無理やり編集すればタグをシンボリックレフで指せます。その場合コミットすると・・・ ただの参照(=コミットを 直接指している) シンボリックレフ (=参照を指す参照)
  92. 92. 結果として 「コミットを新しく作る場所を指す参照」という役 割を効果的に果たせるのはブランチだけ、という ことになります。 branch tag tagbranch “branch”をチェックアウトしてコミット作成 “tag”をチェックアウトしてコミット作成 新しいコミット 新しいコミット HEAD HEAD HEAD HEAD
  93. 93. 動くのはHEADが指す参照だけ 例えばブランチmasterの場所にブランチtopicを作 成した直後、2つのブランチは同じコミットをさして います。 master topic
  94. 94. 動くのはHEADが指す参照だけ masterをチェックアウトしている場合、HEADは masterを指します。 master HEAD topic
  95. 95. 動くのはHEADが指す参照だけ この状態でコミットをつくると、HEAD が指すコミット (=HEADが指す参照(master)が指すコミット)を親 とした新しいコミットが作られ master HEAD topic
  96. 96. 動くのはHEADが指す参照だけ この状態でコミットをつくると、HEAD が指すコミット (=HEADが指す参照(master)が指すコミット)を親 とした新しいコミットが作られ、 master がそれに追 従して動きます。topicは動きません。 master HEAD topic 新コミット作成と HEADが指すブランチの移動はユー ザから見るとアトミックです。
  97. 97. 動くのはHEADが指す参照だけ masterをチェックアウトしている限り(つまりHEAD がmasterを指している限り)、コミットするたび masterが動き続けます。 master HEAD topic
  98. 98. 動くのはHEADが指す参照だけ 今度はtopicをチェックアウトしました。 ということは、HEADはtopicを指します。 master HEAD topic
  99. 99. 動くのはHEADが指す参照だけ この状態でコミットすると、HEADが指すコミットを 親とする新しいコミットが作られ HEAD topic master
  100. 100. 動くのはHEADが指す参照だけ この状態でコミットすると、HEADが指すコミットを 親とする新しいコミットが作られ、HEADが指す参 照が追従します。 HEAD topic master
  101. 101. 動くのはHEADが指す参照だけ さらにコミットしても同様です。 HEAD topicmaster
  102. 102. 動くのはHEADが指す参照だけ もし図の場所に"backup”というタグがあったとして HEAD topicmaster backup
  103. 103. 動くのはHEADが指す参照だけ backupをチェックアウトしてもブランチではないの でHEADはbackupが指すコミットを直接指すことに なります。 topicmaster backup HEAD
  104. 104. 動くのはHEADが指す参照だけ HEADがコミットを直接参照している状態をデタッ チトヘッド(Detached HEAD)と言い、コミットは可 能ですが、 topicmaster backup HEAD
  105. 105. 動くのはHEADが指す参照だけ それに追従する参照はHEAD以外ありません。つ まり別の参照をチェックアウトすると... topicmaster HEAD backup
  106. 106. 動くのはHEADが指す参照だけ 先ほどまでチェックアウトしていたコミット(☆)に戻 ることは難しくなります。参照を付けず放置すると、 やがてGCで完全に削除されてしまいます。 topicmaster HEAD backup ☆ <良い子の諸君
  107. 107. 動くのはHEADが指す参照だけ Detached HEADはあくまで特定のコミットを見るた めだけに使い、コミットを作るにはブランチを使いま しょう。 topicmaster HEAD backup
  108. 108. ちなみに コミットオブジェクトの中身は「ツリー」「親コミット」 「著作者+日時」「コミッター+日時」「コミットメッ セージ」でした。 topicmaster
  109. 109. つまり 全てのコミットオブジェクトはブランチの情報をどこ にも持っていません。(コミットメッセージに残すこと は可能) topicmaster
  110. 110. 他のVCSだと ブランチ(たとえばtopic)は下図のように分岐したあ との枝全体をイメージしてしまいがちですが・・・ topic master
  111. 111. 他のVCSだと ブランチ(たとえばtopic)は下図のように分岐したあ との枝全体をイメージしてしまいがちですが・・・ topic master
  112. 112. Gitにおけるブランチとは あくまでコミットを指している参照に過ぎません。枝 というよりも枝の先端(頭)だけを指し示しているイ メージです。 topicmaster ここだけがブランチ HEAD
  113. 113. 実際、Gitではブランチの参照を 「ブランチヘッド」とか「ヘッドレフ」などと言います。 保存先も refs/heads/ 配下でしたよね。「HEAD」も その流れで考えれば自然な名前です。 topicmaster ブランチヘッド HEAD ブランチを指定すれば枝全体も一意に決まる場合が多 いので、マニュアル等で「ブランチ」という単語が枝全体 を意味する場合はあります。区別の要否は文脈で判断し ましょう。
  114. 114. コミットがブランチを全く記録しない このコンセプトは賛否両論ありますが、「ブランチを 捨てるのが簡単」という大きな利点があります。例 えば・・・ topicmaster
  115. 115. トピックブランチを利用した開発では 「トピックに関係ないコミットはするな」ということに なってますが・・・ feature-foomaster fix-bar ちゃんと機能とバグ フィックスはブランチ分 けろよ 開発リーダーの声
  116. 116. Gitの場合は あまりこだわらずノリノリで仕上げて・・・ ああああ master
  117. 117. 後から 適切に分割し・・・ master feature-foo fix-bar コミットをコピー ああああ
  118. 118. いらないブランチを消す なんてことをよくやります。 master feature-foo fix-bar
  119. 119. このとき 最初に作ったブランチの情報がfeature-fooやfix- barのコミットに残るとしたら、(消す方法が用意され ていたとしても)ちょっと面倒ですよね master feature-foo fix-bar 元ああああ 元ああああ 元ああああ 元ああああ
  120. 120. ちょっと視点を変えて Gitにおけるトピックブランチ開発では、最初から topicの切り方が完璧でなくても良い、と考えると、 このコンセプトの強力さがわかると思います。 master feature-foo fix-bar
  121. 121. でもまぁ、コンセプトの良し悪しは 置いておいて、Gitのブランチとはそういうものだと 覚えてしまいましょう。 ブランチヘッドをつけたり外したり、移動したりが簡 単そうに見えますが、実際簡単です。 後ほど具体的なコマンドで説明します。
  122. 122. タグ(参照)
  123. 123. すでに散々出てきましたが タグは特定のコミットを指すただの参照です。 タグをチェックアウトしても、HEADはシンボリックレ フとしてタグを指せないので、ブランチとしては使え ません。 tag
  124. 124. 一度指した場所が変わらない というのは利点にもなります。 Gitではトピックのコミットを組み替 える作業(rebase等)をしばしば行 うので、 topic master
  125. 125. 一度指した場所が変わらない もともとの場所にタグをつけておけ ば、元に戻すのも簡単です backup master topic
  126. 126. もちろんブランチでも コミットさえしなければ同じ感覚で 使えますが、指す場所が変わらな いというのは作業するうえでの安 心感につながります。 backup master topic
  127. 127. でもそんな軽い存在で良いのか? リリース用のタグにはタグ付けした日時や人の情 報とか残したいんだけど、と思うかもしれません。 また、改竄耐性の強いGitのコミットと比較して、あ まりの軽さに違和感を覚えるかもしれません。
  128. 128. 大丈夫 実はアノテーションタグと呼ばれる、作者やメッ セージなどの注釈情報(アノテーション)を残せるタ グもあります。 アノテーションはタグオブジェクト(tag)使って残しま す。
  129. 129. タグ(オブジェクト)
  130. 130. タグオブジェクト タグオブジェクトはコミットに似ています。 tag = タグ付け対象のオブジェクト名 + その型(commit, tree, blob等) + タグ名 + タグ作成者 + タグメッセージ tag
  131. 131. タグオブジェクトを実際に見てみよう “v1.0”という名前のアノテーションタグがある場合、 下記のように中身を確認できます v1.0 もちろんタグ名を直接指定して git cat-file -p v1.0 でも可能 タグオブジェクト (275b7f) タグが指すコミット (ef1046a) % cat .git/refs/tags/ v1.0 275b7fa60415bd5103e91f96f8689e8536492f55 % git cat-file -p 275b7f object ef1046a0117da8872b73fe72528c1fd9facd95ab type commit tag v1.0 tagger John Smith <js@example.com> 1399263544 +0900 Project foo Release 1.0
  132. 132. tag obj内にもタグ名がありますが 参照としてのタグ(refs/tags/...)の付与は必須で す。参照を削除すると、やがてはタグオブジェクトも GCで削除されます。 が、アノテーションタグを作れば 自動で参照も作成されるので あまり心配はいりません。 v1.0 タグオブジェクト タグ(参照) signed tagは解説を省略
  133. 133. 参照についての話題は以上です コミット 親コミット コミットグラフ ツリー ブロブ オブジェクト 改竄検知 参照 シンボリックレフ ブランチ タグ(参照) タグ(オブジェクト) インデックス ワーキングツリー
  134. 134. 第3章 インデックスとワーキングツリー
  135. 135. インデックス
  136. 136. インデックスとは 新しく作るコミットのtreeを事前に組み立てる場所、 というイメージです。 tree fe5448 commit ef1046 master HEAD tree fe5448 index
  137. 137. 初期状態(チェックアウト直後)では インデックスはHEADの指すコミットのtree(fe5448) と同じtree(fe5448)を保持しています tree fe5448 commit ef1046 master HEAD tree fe5448 index
  138. 138. 新しいコミットを作る準備として インデックスのtreeを更新します(git add)。 インデックスのtreeは621a50になったとします tree fe5448 commit ef1046 master HEAD 新しいtreeで indexを更新 tree fe5448 commit ef1046 master HEAD tree 621a50 index tree fe5448 index
  139. 139. インデックスを更新後コミットすると インデックスに作ったtree(621a50)がそのまま新し いコミットの指すtreeになります tree fe5448 commit ef1046 master HEAD tree fe5448 commit ef1046 master HEAD コミット tree fe5448 commit ef1046 master HEAD tree 621a50 commit 6cc41b 新しいtreeで indexを更新 tree 621a50 index tree fe5448 index tree 621a50 index
  140. 140. コミット直後は インデックスのtree(621a50)とHEADのtree (621a50)が同じである状態に戻ってます。 tree fe5448 commit ef1046 master HEAD tree fe5448 commit ef1046 master HEAD コミット tree fe5448 commit ef1046 master HEAD tree 621a50 commit 6cc41b 新しいtreeで indexを更新 tree 621a50 index tree fe5448 index tree 621a50 index
  141. 141. インデックス=treeオブジェクト? 正確には違うものです。したがってcat-fileでイン デックスを表示することはできません。 しかし、インデックスはtreeを作るために必要な情 報を保持しており、treeを持っているとイメージして 問題ありません というわけでインデックスに treeオブジェクトがある図は厳密には誤りですが、わかりやすさを優先しています。
  142. 142. インデックスの中身を見たい! HEADからの変化をサマリで見るにはgit statusが 適していますが、git ls-files(引数なし)でインデック スに格納されたエントリを一覧できます。 treeオブジェクトとして見たい場合、git write-tree を実行するとインデックスの内容でtreeをGitデータ ベースに書き出すので、表示されたSHA1値をcat- fileすればOKです。
  143. 143. インデックスの詳細 インデックスは他にもマージ中に複数のバージョン のツリーのキャッシュを保持するなどの役割があり ます。 詳細を知りたい人はGitソースツリーの Documentation/technical/index-format.txt ほか、関連マニュアルを見ましょう。
  144. 144. ワーキングツリー
  145. 145. これまでのコンセプトは全て リポジトリの.git/配下の話でしたが、ワーキングツ リーは .git/ 以外の部分のことです。 tree fe5448 commit ef1046 master HEAD tree fe5448 index .git/ 配下 working tree fe5448 equivalent ここ(.git/の外側)の話
  146. 146. ワーキングツリーとは Gitの管理するtreeが通常のUnixディレクトリツリー としてチェックアウトされたものです。 tree fe5448 commit ef1046 master HEAD tree fe5448 indexworking tree fe5448 equivalent
  147. 147. 初期状態(チェックアウト直後)では ワーキングツリーにはindexの内容がコピーされて います。つまりHEADのtree(fe5448)相当の内容 です。 tree fe5448 commit ef1046 master HEAD tree fe5448 indexworking tree fe5448 equivalent
  148. 148. ワーキングツリーの中身は 通常のディレクトリ・ファイルですので、 自由に追加・削除・変更できます。 .git/の世界の状況は関係なく編集可能です。 tree fe5448 commit ef1046 master HEAD tree fe5448 indexworking tree locally changed
  149. 149. コミットを作成するには インデックスを更新してから、インデックスのツリー を次のコミットとして登録するのでした。 tree fe5448 commit ef1046 master HEAD indexworking tree locally changed tree 621a50 tree 621a50 commit 6cc41b コミット
  150. 150. このインデックス更新の元ネタが ワーキングツリーの内容です。下図のtree 621a50 はワーキングツリーのファイルでインデックスを更 新してできたtreeだったのです。 working tree 621a50 equiv tree fe5448 commit ef1046 master HEAD index tree 621a50 tree 621a50 commit 6cc41b コミット インデックス更 新
  151. 151. 元ネタとは言っても コミット時にワークツリーとインデックスを完全に一 致させる必要はありません。コミットはあくまでもイ ンデックスの内容で作られます。 working tree 0efb8b equiv tree fe5448 commit ef1046 master HEAD index tree 621a50 tree 621a50 commit 6cc41b コミット インデックス更 新 インデックス=コミット とは違う内容 コミットと同じ内容
  152. 152. ワーキングツリーの状態とコミットは 独立している、とも言えます。 これは非常に強力なコンセプトです。例えば・・・ working tree 0efb8b equiv tree fe5448 commit ef1046 master HEAD index tree 621a50 tree 621a50 commit 6cc41b コミット 無関係
  153. 153. 開発中についつい 気になったtypoなど些細な修正をしたくなることが あります。(あるいは、あとでやろうと思ってそのま ま忘れてしまう) tree fe5448 commit ef1046 master HEAD tree fe5448 indexworking tree locally changed 本来の開発とは 無関係な修正 本来の開発
  154. 154. ひとつの修正に 意味的に複数の変更を加えるのは行儀の悪い行 為とされています。(後から取り消すのが面倒だっ たりするので) tree fe5448 commit ef1046 tree 5b94ca indexworking tree 5b94ca equiv 本来の開発とは 無関係な修正 本来の開発 コミット インデックス更 新 tree 5b94ca commit 393ce0 master HEAD 無関係な修正が一緒 になったコミット
  155. 155. そういう場合も Gitなら気にせずワーキングツリーを修正して問題 ありません。その変更はインデックスに送らずにコ ミットすれば良いのです。 tree fe5448 commit ef1046 tree 621a50 indexworking tree 5b94ca equiv 本来の開発とは 無関係な修正 本来の開発 コミット インデックス更 新 tree 621a50 commit 6cc41b master HEAD 本来の開発だけイン デックスに反映 本来の開発だけを含 むコミットになる
  156. 156. その後 残っていた修正を改めてインデックスに送り、コミッ トすれば、行儀の悪いコミットを作らなくてすみま す。 tree fe5448 commit ef1046 tree 5b94ca indexworking tree 5b94ca equiv 本来の開発とは 無関係な修正 コミット インデックス更 新 tree 621a50 commit 6cc41b 改めてインデックスに 反映 tree 5b94ca commit 861bb7 master HEAD
  157. 157. つまりGitでは ワーキングツリーの編集内容と、次回コミット内容 (=インデックス)が分離されているわけです。 tree 621a50 indexworking tree 5b94ca equiv ワーキングツリー 編集内容 次回コミットの内容 分離
  158. 158. 視点を変えると Gitでは次回コミットの事を気にしてワーキングツ リーを編集する必要はない、というわけです。(イン デックスに送る時に気にすればよい) tree 621a50 indexworking tree locally changed 自由に編集してよい 分離
  159. 159. インデックスに送るコマンドは 主にgit addですが、これにはワーキングツリーの 変更を部分的にインデックスに送る機能が用意さ れています。具体的には次章で。 tree 621a50 indexworking tree 5b94ca equiv git add
  160. 160. ちなみに インデックスは次回コミット、ワーキングツリーはそ れ以降のコミットの内容を含んでいるので、コミット グラフではHEADの続きのコミットのように図示す る場合があります。 index working tree master HEAD master HEAD index working tree
  161. 161. 第4章 コンセプトから理解するGitコマンド
  162. 162. いよいよコマンドの解説です これまでに解説したコンセプトをもとにコマンドを解 説します。 具体的な解説を見る前に個々のコンセプトを思い 出しておきましょう。
  163. 163. 解説した主なコンセプト コミット 親コミット コミットグラフ ツリー ブロブ オブジェクト 改竄検知 参照 シンボリックレフ ブランチ タグ(参照) タグ(オブジェクト) インデックス ワーキングツリー
  164. 164. 追加で: commit-ishとは Gitのマニュアルにはcommit-ishという表記がよく 出てきます。commit自身や参照など、commitが 一意に決まるものがcommit-ishです。 v1.0 コミット master タグ ブランチ タグオブジェクト commit-ish HEAD シンボリックレフ
  165. 165. この章で紹介するコマンド ● ワーキングツリー操作 ○ checkout, reset ● インデックス操作 ○ add, reset ● コミット操作 ○ commit, merge, cherry-pick, revert ● ブランチ操作 ○ branch, reset
  166. 166. この章で紹介するコマンド(2) ● コミット・ブランチ複合操作 ○ commit(--amend), rebase ● タグ操作 ○ tag ● さまざまな調査 ○ log, gitk, diff, reflog, fsck ● その他の複合操作 ○ 出てきたコマンドの組み合わせ
  167. 167. ワーキングツリー操作系 ワーキングツリーの内容を変更するコマンドを解説 します。
  168. 168. ワーキングツリー操作系 1. 全体を指定ブランチの内容に切り替える checkout <branch> checkout <commit-ish> 2. ワーキングツリーの変更を捨てる checkout -- <path> checkout <commit-ish> -- <path> 3. ワーキングツリーの変更を捨てる(2) reset --hard
  169. 169. ワーキングツリー操作系 1. 全体を指定ブランチの内容に切り替える checkout <branch> checkout <commit-ish> 2. ワーキングツリーの変更を捨てる checkout -- <path> checkout <commit-ish> -- <path> 3. ワーキングツリーの変更を捨てる(2) reset --hard
  170. 170. 1. ワーキングツリー全体を指定したブラン チの内容に切り替える ① checkout <branch> ② checkout <commit-ish> ①ワーキングツリーの内容を <branch> のツリー の内容に切り替えます。同時にインデックスと HEADも<branch>に従って更新されます。
  171. 171. checkout <branch> checkout topicであれば、カレントブランチをtopic に切り替えるわけですが、動きとしては・・・ tree 5b94ca index working tree 5b94ca equiv git checkout topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic tree 5b94ca index working tree 5b94ca equiv tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic
  172. 172. checkout <branch> HEADがtopicに移動し(カレントブランチが切り替 わり)・・・ tree 5b94ca index working tree 5b94ca equiv git checkout topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master topic HEADtree 5b94ca index working tree 5b94ca equiv HEAD
  173. 173. checkout <branch> HEADのツリーでインデックスの内容を更新 tree 5b94ca index working tree 5b94ca equiv git checkout topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master topic HEADtree 621a50 index working tree 5b94ca equiv
  174. 174. checkout <branch> 同じくワーキングツリーも内容を更新します。 tree 5b94ca index working tree 5b94ca equiv git checkout topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master topic HEADtree 621a50 index working tree 621a50 equiv
  175. 175. checkout <branch> これがカレントブランチを切り替えるということの正 確な意味です。 tree 5b94ca index working tree 5b94ca equiv git checkout topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master topic index working tree 621a50 equiv tree 621a50 HEAD
  176. 176. 1. ワーキングツリー全体を指定したブラン チの内容に切り替える ① checkout <branch> ② checkout <commit-ish> ②実は <branch> に限定されず、<commit-ish>な らなんでも指定可能です。
  177. 177. checkout <commit-ish> 動きとしては<branch>指定のときとほとんど同じ で・・・ tree 5b94ca index working tree 5b94ca equiv git checkout topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic tree 5b94ca index working tree 5b94ca equiv tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic
  178. 178. checkout <commit-ish> HEADがブランチを指すシンボリックレフではなく、 コミットを直接指す参照になる、という点が違うだけ で・・・ tree 5b94ca index working tree 5b94ca equiv git checkout 6cc41b tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic tree 5b94ca index working tree 5b94ca equiv tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic HEAD
  179. 179. checkout <commit-ish> インデックスとワーキングツリーが新しいHEADの ツリーの内容で更新されるのは同じです tree 5b94ca index working tree 5b94ca equiv git checkout topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master topic index working tree 621a50 equiv tree 621a50 HEAD
  180. 180. 注意: チェックアウト実行前に ワーキングツリー/インデックスがコミットされてない 変更を含んでいた場合、差分がチェックアウト後の ツリーに適用されます。(変更が保持される) tree 5b94ca index working tree local change on 5b94ca git checkout 6cc41b tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master HEAD topic tree 621a50 index working tree local change on 621a50 tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 master topic HEAD
  181. 181. ワーキングツリー操作系 1. 全体を指定ブランチの内容に切り替える checkout <branch> checkout <commit-ish> 2. ワーキングツリーの変更を捨てる checkout -- <path> checkout <commit-ish> -- <path> 3. ワーキングツリーの変更を捨てる(2) reset --hard
  182. 182. 2. ワーキングツリーの内容を捨てる ① checkout -- <path> ② checkout <commit-ish> -- <path> ①インデックスの<path>の内容を取り出し、そいつ でワーキングツリー配下の<path>を上書きしま す。
  183. 183. checkout -- <path> hello.txtの変更でインデックスを更新し、ワーキン グツリーのhello.txtを更に編集、greeting.txtにも編 集を加えた状態を考えます。 working tree index hello.txt greeting.txthello.txt greeting.txt HEAD hello.txt greeting.txt
  184. 184. checkout -- <path> checkout -- greeting.txt を実行すると、インデック スのgreeting.txtでワーキングツリーのgreeting.txt を上書きします。 working tree index hello.txt greeting.txthello.txt greeting.txt HEAD hello.txt greeting.txt git checkout -- greeting.txt
  185. 185. checkout -- <path> インデックスのgreeting.txtはもともとHEADから変 更されていないので、HEAD=インデックス=ワー キングツリーな内容になります working tree index hello.txt greeting.txthello.txt greeting.txt HEAD hello.txt greeting.txt git checkout -- greeting.txt
  186. 186. checkout -- <path> 続いて checkout -- hello.txt を実行すると、同様に インデックスのhello.txtでワーキングツリーのhello. txtを上書きします。 working tree index hello.txt greeting.txthello.txt greeting.txt HEAD hello.txt greeting.txt git checkout -- hello.txt
  187. 187. checkout -- <path> ワーキングツリーのhello.txtがインデックスの hello.txtと同じ内容になりました。これはHEADと は異なる内容です。 working tree index hello.txt greeting.txthello.txt greeting.txt HEAD hello.txt greeting.txt git checkout -- hello.txt
  188. 188. checkout -- <path> どちらの例もワーキングツリーの編集内容は捨て られます。 working tree index hello.txt greeting.txthello.txt greeting.txt HEAD hello.txt greeting.txt git checkout -- hello.txtgit checkout -- greeting.txt
  189. 189. checkout -- <path> インデックスが変更されている場合はHEADと同じ ならないことに注意。 HEADの内容で上書きしたい場合は次に出てくる 書式を使います。 working tree index hello.txt greeting.txthello.txt greeting.txt HEAD hello.txt greeting.txt git checkout -- hello.txtgit checkout -- greeting.txt
  190. 190. 2. ワーキングツリーの内容を捨てる ① checkout -- <path> ② checkout <commit-ish> -- <path> ②<commit-ish>を指定した場合、そのコミットの内 容でインデックスとワーキングツリーの<path>を上 書きします。 ②は<commit-ish>と書いてるけど実は tree オブジェクト指定でも OK.(<tree-ish>)
  191. 191. checkout <commit-ish> -- <path> さっきの続きです。ここで checkout HEAD -- hello.txt を実行すると・・・ working tree index hello.txt greeting.txthello.txt greeting.txt HEAD hello.txt greeting.txt
  192. 192. checkout <commit-ish> -- <path> インデックスのhello.txtがHEADのhello.txtで上書 きされ・・・ working tree index hello.txt greeting.txthello.txt greeting.txt HEAD hello.txt greeting.txt git checkout HEAD -- greeting.txt
  193. 193. checkout <commit-ish> -- <path> ワーキングツリーのhello.txtも同じ内容で上書きさ れます。 どちらの書式も編集内容が捨てられるので注意し てください。 working tree index hello.txt greeting.txthello.txt greeting.txt HEAD hello.txt greeting.txt git checkout HEAD -- greeting.txt
  194. 194. ワーキングツリー操作系 1. 全体を指定ブランチの内容に切り替える checkout <branch> checkout <commit-ish> 2. ワーキングツリーの変更を捨てる checkout -- <path> checkout <commit-ish> -- <path> 3. ワーキングツリーの変更を捨てる(2) reset --hard
  195. 195. 3. ワーキングツリーの内容を捨てる(2) reset --hard [ HEAD ] インデックスとワーキングツリーをHEADの内容で 上書きします。HEADは省略可能。 HEADの位置に他の<commit-ish>を指定可能ですが、カレントブランチが指す場所を変更する副作用がある ので、要注意。
  196. 196. reset --hard 動作は checkout HEAD -- . (pathにカレントディレ クトリを指定)と同じで・・・ working tree index hello.txt greeting.txthello.txt greeting.txt HEAD hello.txt greeting.txt
  197. 197. reset --hard ツリー全体がHEADの内容で上書きされ、インデッ クスとワーキングツリーの変更は捨てられます。 working tree index HEAD hello.txt greeting.txthello.txt greeting.txthello.txt greeting.txt git reset --hard
  198. 198. インデックス操作系 インデックスの内容を変更するコマンドを解説しま す。
  199. 199. インデックス操作系 1. インデックスに変更を登録する add <path> add -p <path> 2. インデックスの変更を捨てる reset HEAD -- <path>
  200. 200. インデックス操作系 1. インデックスに変更を登録する add <path> add -p <path> 2. インデックスの変更を捨てる reset HEAD -- <path>
  201. 201. 1. インデックスに変更を登録する ① add <path> ② add -p <path> ①<path>で指定したワーキングツリーの内容でイ ンデックスの同名の<path>を上書きします。
  202. 202. add <path> ワーキングツリーの greeting.txt と hello.txt が ローカルな変更を持っている(編集されている)とし ます。 working tree index hello.txt greeting.txthello.txt greeting.txt
  203. 203. add <path> git add hello.txt を実行すると、ワーキングツリー にある hello.txt の内容でインデックスの hello.txt を上書きすることになります。 greeting.txt はインデックスに含まれません。 working tree index hello.txt greeting.txthello.txt greeting.txt git add hello.txt
  204. 204. greeting.txt add <path> インデックス=次回コミットの内容です。 コミットとしてふさわしい内容になるまで git add <path> や git reset HEAD -- <path> (後述)で調 整しましょう。 working tree index hello.txt greeting.txthello.txt git add <path> git reset HEAD -- <path> HEAD hello.txt greeting.txt
  205. 205. greeting.txt add <path> なお、ファイルの削除を反映する場合も Git 2.0 か らは add コマンドで可能です。(古いGitの場合は git rm <path>や git add -A <path>で反映します) working tree index hello.txt greeting.txthello.txt git add hello.txt
  206. 206. 1. インデックスに変更を登録する ① add <path> ② add -p <path> ②<path>で指定したワーキングツリーの内容とイ ンデックスの同名の<path>の差分を選択してイン デックスに登録します
  207. 207. greeting.txt add -p <path> ワーキングツリーの hello.txt がローカルな変更を 持っているとします。 working tree index hello.txt greeting.txthello.txt
  208. 208. greeting.txt add -p <path> add -p hello.txt を実行すると、対話的な処理が開 始され、ワーキングツリーとインデックスのhello.txt の差分のハンクごとにインデックスにaddするかど うかを選択できます。 working tree index hello.txt greeting.txthello.txt git add -p hello.txt
  209. 209. greeting.txt add -p <path> 結果としてワーキングツリーともHEADとも違う内 容の hello.txt をインデックスに登録することができ ます。 working tree index hello.txt greeting.txthello.txt
  210. 210. インデックス操作系 1. インデックスに変更を登録する add <path> add -p <path> 2. インデックスの変更を捨てる reset HEAD -- <path>
  211. 211. 2. インデックスの変更を捨てる ① reset HEAD -- <path> ①<path>で指定したインデックスの内容を捨てて HEAD の内容に戻すことができます。
  212. 212. greeting.txt reset HEAD -- <path> ワーキングツリーの hello.txt がローカルな変更を 持っており、インデックスにそれが登録されている とします。 working tree index hello.txt greeting.txthello.txt HEAD hello.txt greeting.txt
  213. 213. greeting.txt reset HEAD -- <path> git reset HEAD -- hello.txt によって、HEADの hello.txt の内容でインデックスを更新します。つま り、ワーキングツリーをもとに追加されていたイン デックスの変更が捨てられます。 working tree index hello.txt greeting.txthello.txt HEAD hello.txt greeting.txt git reset HEAD -- hello.txt
  214. 214. greeting.txt reset HEAD -- <path> ちなみに git init した直後だと git rm --cached <path> を使う必要があります。いずれにしろ git status にどうしたら良いか表示されているので、 迷ったら status の出力を見ましょう。 working tree index hello.txt greeting.txthello.txt HEAD hello.txt greeting.txt git reset HEAD -- hello.txt
  215. 215. コミット操作系 コミットを作成するコマンドを解説します。
  216. 216. コミット操作系 1. コミットを作成する commit merge <commit-ish> cherry-pick <commit-ish> revert <commit-ish>
  217. 217. コミット操作系 1. コミットを作成する commit merge <commit-ish> cherry-pick <commit-ish> revert <commit-ish>
  218. 218. 1. コミットを作成する ① commit ② merge <commit-ish> ③ cherry-pick <commit-ish> ④ revert <commit-ish> ① インデックスの内容で、カレントブランチに新し いコミットを作成します。
  219. 219. commit 現在のインデックスの内容で新しいコミットをカレン トブランチに作ります。すでに解説したとおり、この 効果は正確には・・・ tree 5b94ca index working tree local change tree 621a50 commit 6cc41b HEAD topic tree 5b94ca index working tree local change tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 HEAD topic git add hello.txt 新しい コミット
  220. 220. commit HEADを親とした新しいコミットを作成し、HEADが 指すブランチヘッドの参照先を今作ったコミットに 書き換える、という動作の結果がそのように見えて います。 tree 5b94ca index working tree local change tree 621a50 commit 6cc41b HEAD topic tree 5b94ca index working tree local change tree 621a50 commit 6cc41b tree 5b94ca commit 861bb7 HEAD topic git add hello.txt 新しい コミット
  221. 221. 1. コミットを作成する ① commit ② merge <commit-ish> ③ cherry-pick <commit-ish> ④ revert <commit-ish> ② HEADと指定した <commit-ish> をマージした マージコミットをHEADに作成します。
  222. 222. merge <commit-ish> マージは他のコミットによる変更を取り込む操作で す。 ここではfooをチェックアウトした状態で bar をマー ジしてみます。 foo bar HEAD git merge bar
  223. 223. merge <commit-ish> HEADとfooの両方の編集結果を持つ(マージし た)新しいコミットを作成し・・・ New commit foo HEAD foo HEAD bar bar git merge bar
  224. 224. merge <commit-ish> HEADが指している参照を新しいコミットに移動し ます。これがマージです。 foo HEAD foo HEAD bar bar New commitgit merge bar
  225. 225. マージコミット このとき新しくできたコミットをマージコミットと言い ます。親コミットとして複数のコミットが記録されて いるコミットがマージコミットです。 foo HEAD foo HEAD bar bar merge commitgit merge bar
  226. 226. foo HEAD bar 3wayマージ Gitで用いられるマージの手法は3wayマージと呼 ばれます。
  227. 227. 3wayマージ これはマージするふたつのコミットと、それらから最 も近い共通祖先の3つを使ってマージを行う、とい うものです。 foo HEAD bar
  228. 228. 3wayマージ 今回の例で言えば、foo, bar, およびそれらの共通 祖先(図示)を使うということです。 common ancestor foo HEAD bar merge commit
  229. 229. 3wayマージ マージする際に最適な共通祖先はマージベースと も呼ばれます。これはコマンド git merge-base foo bar で表示できます。 merge-base foo HEAD bar merge commit
  230. 230. 3wayマージ 3wayマージの特徴のひとつは、途中の変更(コミッ ト)は考慮しないという点です。マージベース→foo の差分、マージベース→barの差分をもとにマージ コミットを作成します。 merge-base foo HEAD bar 差分 差分 merge commit
  231. 231. 3wayマージ マージベースとマージ対象のコミットそれぞれの間 に複雑な変更がどれだけあろうとも、3つのコミット を材料にマージされます。 merge-base foo HEAD bar merge commit
  232. 232. HEAD bar 3wayマージが使われないパターン ふたつの差分のうちのひとつがなくなってしまう場 合は3wayマージになりません。 例えば図のような状態で git merge bar することを 考えます。 foo
  233. 233. HEAD bar 3wayマージが使われないパターン つまりマージベースとfoo(HEAD)が一致している 場合です。barがfooの子孫である場合とも言えま す。 merge-base foo
  234. 234. HEAD bar Fast-Forwardマージ この場合は foo を単に bar まで進めます。これは Fast-Forward マージ(FFマージ)とよばれていま す。 merge-base foo HEAD foo merge --no-ff でマージコミットを強制することも可能
  235. 235. bar 3wayマージが使われないパターン 逆のパターンも見てみましょう。つまり、上図の状 態で bar をチェックアウトし、 git merge foo する場 合です。 HEAD foo
  236. 236. bar 3wayマージが使われないパターン この場合もやはりマージベースは foo になります。 マージしようとしているコミット(foo)がマージベース の場合、つまり祖先のコミットをマージしようとした 場合... merge-base HEAD foo
  237. 237. bar マージ済み(Already up-to-date) Already up-to-date と表示されるだけで何もおこり ません。 すでにマージ済みであるとみなされるからです。 merge-base HEAD foo
  238. 238. マージの方向に注意 barをfooにマージした結果(左)とfooをbarにマージ した結果(右)はツリーは同じになったとしても、別 物です。マージコミットに記録される親コミットの順 番が異なるからです。 foo HEAD foo bar bar merge commit merge commit HEAD
  239. 239. ファーストペアレント マージしたときのカレントブランチ側の親 =先に記録される親 =1番目に記録される親 =ファーストペアレントとなります。 foo HEAD foo bar bar HEAD first-parent first-parent
  240. 240. ファーストペアレント ファーストペアレントは他のVCSで言えばtrunk的 な意味合いがあります。 Gitでもファーストペアレントは特別扱いされる場合 があり、意識しておくと有用です。 foo HEAD foo bar bar HEAD first-parent first-parent
  241. 241. ファーストペアレント 特にトピックブランチによる開発をする場合には統 合ブランチ(master等)側が常にファーストペアレン トになるようにマージしましょう foo HEAD foo bar bar first-parent first-parent HEAD
  242. 242. ファーストペアレント ちなみにマージコミットを図示する場合、ファースト ペアレントの系列はふつう直線上に書きます。例 外はありますが、fooからbarをマージしたときは大 抵左のように書きます。 foo HEAD foo bar bar まっすぐ HEAD あまりこういう 風には描かな い
  243. 243. マージ対象はコミットなら何でも可 マージ対象はブランチである必要はありません。 bar^ (「X^」はXの親コミットを指定する書き方) を マージすれば、上図のようになります。SHA1指定 ももちろんOK foo HEAD foo HEAD bar bar マージ コミットgit merge bar^
  244. 244. 1. コミットを作成する ① commit ② merge <commit-ish> ③ cherry-pick <commit-ish> ④ revert <commit-ish> ③ 指定した <commit-ish> と同じ差分のコミットを HEADに作成します。
  245. 245. cherry-pick <commit-ish> チェリーピックはマージと同様、他のコミットによる 変更を取り込む操作です。ただし、マージとは異な り単一のコミットを取り込みます。 foo に bd48f1 をチェリーピックしてみます。 foo HEAD bar git cherry-pick bd48f1 bd48f1
  246. 246. cherry-pick <commit-ish> 取り込むと言っても、 bd48f1 のコミットやツリーが そのままfooの上に作られるわけではありません。 そんなことできても嬉しくないですし。 foo HEAD bar git cherry-pick bd48f1 bd48f1 foo HEAD barbd48f1 bd48f1
  247. 247. cherry-pick <commit-ish> 実際のところ bd48f1^ と bd4f1 のツリーの差分 (patch)を取り出し… foo HEAD bar git cherry-pick bd48f1 bd48f1 foo HEAD barbd48f1 patch
  248. 248. cherry-pick <commit-ish> そのパッチを foo に適用したツリーでコミットを新し く作成する、という動作になります。 著作者、コミットメッセージはbd48f1のものを引き 継ぎますが、コミッターは更新されます。 foo HEAD bar git cherry-pick bd48f1 bd48f1 foo HEAD barbd48f1 apply
  249. 249. cherry-pickの使いどころ 開発ブランチから生えたトピックのコミットはより安 定したブランチにマージすると、トピックの開始点ま での開発ブランチの内容も一緒に安定ブランチに マージされてしまいます。 master devel master devel git merge X X
  250. 250. cherry-pickの使いどころ そのような場合に、チェリーピックであれば、コミット の場所に関係なく、安全にそのコミットだけを取り 込むことができます。 master devel master devel git cherry-pick X X X’
  251. 251. cherry-pickの使いどころ 欲しいコミットが複数の場合はrebase --onto でま るごと取ってくることも可能です。いずれにしろ、ブ ランチ開始点が間違っている場合の対処法であ り、常用するものではありません。 master devel devel git branch Z Y git rebase --onto master Z~2 Z Y Z Y master
  252. 252. cherry-pickの使いどころ トピックの開始点に注意して、コミットの取込みはで きるだけマージを使いましょう。(マージする必要の ある統合ブランチのうち、最も古い(下流の)ものか ら開始するのがコツです) master devel devel git branch Z Y git rebase --onto master Z~2 Z Y Z Y master
  253. 253. 1. コミットを作成する ① commit ② merge <commit-ish> ③ cherry-pick <commit-ish> ④ revert <commit-ish> ④ 指定した <commit-ish> を打ち消すような差分 のコミットをHEADに作成します。
  254. 254. revert <commit-ish> コミット32ff01をrevertするとします。 まず 32ff01 から 32ff01^ への差分(patch)を取り 出します。これは子から親へのパッチ(リバース パッチ)です。 foo HEAD git revert 32ff01 32ff01 foo HEAD 32ff01 reverse patch
  255. 255. revert <commit-ish> そのリバースパッチをfooのツリーに適用して新し いコミットを作ります。 foo HEAD git revert 32ff01 32ff01 foo HEAD 32ff01 apply
  256. 256. revert <commit-ish> 32ff01 と revert commitの変更は互いに打ち消し あい、結果としてHEADのツリーは 32ff01 による 変更がなかったかのような状態になります。 foo HEAD git revert 32ff01 32ff01 foo HEAD 32ff01
  257. 257. ブランチ操作系 ブランチを作成・変更するコマンドを解説します。
  258. 258. ブランチ操作系 1. ブランチを作成/削除/名前変更する branch <branch> [ <commit-ish> ] branch -d | -D <branch> branch -m [ <old> ] <new> 2. ブランチの指すコミットを変更する reset [ --hard ] <commit-ish>
  259. 259. ブランチ操作系 1. ブランチを作成/削除/名前変更する branch <branch> [ <commit-ish> ] branch -d | -D <branch> branch -m [ <old> ] <new> 2. ブランチの指すコミットを変更する reset [ --hard ] <commit-ish>
  260. 260. 1. ブランチを作成/削除/名前変更する ① branch <branch> [ <commit-ish> ] ② branch -d | -D <branch> ③ branch -m [ <old> ] <new> ① 指定したコミットに新しいブランチの参照を <branch> という名前で作成します。<commit-ish> を省略すると HEAD に作成します。
  261. 261. branch <branch> [ <commit-ish> ] branch は単にブランチヘッドとなる参照を作成し ます。図はコミット32ff01にbarというブランチを作 成した場合。 foo HEAD git branch bar 32ff01 32ff01 foo HEAD 32ff01 bar
  262. 262. branch <branch> [ <commit-ish> ] コミットを指定しなければHEADに新しい参照を作 ることになります。 foo HEAD git branch bar foo HEAD bar
  263. 263. 1. ブランチを作成/削除/名前変更する ① branch <branch> [ <commit-ish> ] ② branch -d | -D <branch> ③ branch -m [ <old> ] <new> ② 指定した <branch> を削除します。 -d では HEAD から到達可能なコミットに付けられた参照で ないと(=カレントブランチにマージされてないと)削 除できません。 -D であれば無条件に削除します。
  264. 264. branch -d | -D <branch> branch -d はブランチヘッド参照を削除します。-d だとHEADの祖先に付いているブランチのみ削除 できます。 foo HEAD git branch -d bar foo HEAD bar buz buz
  265. 265. branch -d | -D <branch> これはマージされていないブランチを削除しないた めの安全装置です。上の場合、 buz を削除するこ とはできません。 foo HEAD git branch -d buz buz foo HEAD
  266. 266. branch -d | -D <branch> HEADの祖先でないブランチを削除したければ、 branch -D を使います。 foo HEAD git branch -D buz foo HEAD buz
  267. 267. 1. ブランチを作成/削除/名前変更する ① branch <branch> [ <commit-ish> ] ② branch -d | -D <branch> ③ branch -m [ <old> ] <new> ③ ブランチ <old> の名前を <new> に変更しま す。<old> を指定しない場合はカレントブランチの 名前が <new> に変更されます。
  268. 268. branch -m [ <old> ] <new> branch -m でブランチヘッドの名前を変更できま す。 foo HEAD git branch -m buz bar foo HEAD buz bar
  269. 269. ブランチ操作系 1. ブランチを作成/削除/名前変更する branch <branch> [ <commit-ish> ] branch -d | -D <branch> branch -m [ <old> ] <new> 2. ブランチの指すコミットを変更する reset [ --hard ] <commit-ish>
  270. 270. 2. ブランチの指すコミットを変更する ① reset [ --hard ] <commit-ish> ① カレントブランチの参照が指すコミットを指定し たコミットに変更し、そのコミットでインデックスを更 新します。--hardを指定した場合はワーキングツ リーもそのコミットの内容で上書きします。 言い換えると、ブランチヘッドをコミットグラフの中 の別の場所へ移動する効果があります。
  271. 271. reset [ --hard ] <commit-ish> reset はカレントブランチが指す先を変更します。 例えば今作ったコミットの内容が間違えていた時 に、そのコミットをなかったことにする用途で git reset HEAD^ を使います。 foo HEAD git reset HEAD^ foo HEAD bar bar
  272. 272. reset [ --hard ] <commit-ish> --hard をつけるとワーキングツリーが指定したコ ミットで上書きされます。ブランチヘッドを他のコミッ トに付け替えたい場合によく使います。 foo HEAD git reset --hard bar foo HEAD bar bar
  273. 273. コミット・ブランチ複合操作系 コミット・ブランチを複合的に操作するコマンドを解 説します。実質的にはコミットの修正のために用い られます。
  274. 274. コミット・ブランチ複合操作系 1. コミットを修正する commit --amend rebase <commit-ish>
  275. 275. コミット・ブランチ複合操作系 1. コミットを修正する commit --amend rebase <commit-ish>
  276. 276. 1. コミットを修正する ① commit --amend ② rebase <commit-ish> ① インデックスの内容でHEADコミットを修正しま す。実際にはHEADの兄弟として新しくコミットを作 り、カレントブランチをそこに移動します。
  277. 277. commit --amend foo HEAD git commit --amend tree 5b94ca index commit --amendはHEADを修正するコマンドで す。修正内容をインデックスにaddした状態を考え ます。
  278. 278. commit --amend foo HEAD git commit tree 5b94ca index 本来ここでコミットすれば、目的の内容を持った新 しいコミットが作成されますが、--amendをつけて いると… foo HEAD amendなしの場合
  279. 279. commit --amend foo HEAD git commit --amend tree 5b94ca index インデックスの内容でHEAD^を親とした新しいコ ミット、つまりHEADの兄弟のコミットが作られ… foo HEAD
  280. 280. commit --amend foo HEAD git commit --amend tree 5b94ca index ブランチfooがHEADとともに新しく作られた兄弟コ ミットの方に移動します。 foo HEAD
  281. 281. commit --amend foo HEAD git commit --amend tree 5b94ca index 以前のHEADは見えなくなりますから、結果として ブランチfooの最新コミットが修正されたように見え ます。 foo HEAD
  282. 282. 1. コミットを修正する ① commit --amend ② rebase <commit-ish> ② 指定したコミット(これを含まない)からHEADま でのコミットを一括して再作成します。
  283. 283. rebase <commit-ish> ブランチbarを開発中、masterから分岐後のbar全 体を現在のmasterの先端に移動したい場合に rebaseを使います。動きとしては… master HEAD git rebase master bar master bar HEAD
  284. 284. rebase <commit-ish> まず master のコミットにHEADを移動し… master HEAD git rebase master bar master bar HEAD
  285. 285. rebase <commit-ish> masterから分岐後のbarのコミットを順次 cherry- pickのように差分を取り出しては適用し… master HEAD git rebase master bar master bar HEAD cherry-pick相当
  286. 286. rebase <commit-ish> 参照 bar を新しいコミットに付け替えてカレントブラ ンチをbarに切り替えます。 master HEAD git rebase master bar master HEAD bar
  287. 287. rebase <commit-ish> 応用として rebase -i を使ってcherry-pickする際に 編集を加えたり、コミットを取捨選択したり、といっ たことを対話的に指定できます。 図では2つだったコミットを1つにまとめてます master HEAD git rebase -i master bar master HEAD bar
  288. 288. rebase <commit-ish> あるいは<commit-ish>に上流ブランチではなく、 祖先のコミットを指定することで、それ以降のコミッ トを(ブランチを付け替えせずに)作りなおしたりでき ます。 master HEAD git rebase -i HEAD~2 bar master HEAD bar
  289. 289. タグ操作系 タグを作ったり削除したりといった操作です。
  290. 290. タグ操作系 1. タグを作成/削除する tag <tag> [ <commit-ish> ] tag -a <tag> [ <commit-ish> ] tag -d <tag>
  291. 291. 1. タグを作成/削除する ① tag <tag> [ <commit-ish> ] ② tag -a <tag> [ <commit-ish> ] ③ tag -d <tag> ① 指定したコミットを指すタグ(参照)を作成します
  292. 292. tag <tag> [ <commit-ish> ] 指定したコミットに参照のタグを作成します。コミッ トを指定しない場合、HEADが対象になります。 master HEAD git tag backup bar bar master HEAD bar backup
  293. 293. 1. タグを作成/削除する ① tag <tag> <commit-ish> ② tag -a <tag> <commit-ish> ③ tag -d <tag> ② 指定したコミットを指すアノテーションタグを作成 します。
  294. 294. tag -a <tag> [ <commit-ish> ] -a を指定するとアノテーションタグを作成します。 実際には指定したコミットを指すタグオブジェクト (△)を作成し、それを指す参照のタグを作成しま す。 master HEAD git tag -a backup bar bar master HEAD backup bar
  295. 295. 1. タグを作成/削除する ① tag <tag> <commit-ish> ② tag -a <tag> <commit-ish> ③ tag -d <tag> ③ 指定したタグ(参照)を削除します。
  296. 296. tag -a <tag> [ <commit-ish> ] -d を指定するとタグを削除します。アノテーションタ グが指定された場合、タグオブジェクトはすぐに削 除されるわけではありませんが、そのうちGCで削 除されます。 master HEAD git tag -d backup bar master HEAD bar backup
  297. 297. さまざまな調査系 いろいろなものを調査するためのコマンドです。実 に様々なコマンド・使い方があり、有名なものも多 いのですが、理解しておくと便利なもの・使い方を 中心に解説します。
  298. 298. さまざまな調査系 1. コミットの履歴を見る log (範囲指定について) gitk 2. 差分を見る diff log 3. なくしたものを探す reflog, fsck
  299. 299. さまざまな調査系 1. コミットの履歴を見る log (範囲指定について) gitk 2. 差分を見る diff log 3. なくしたものを探す reflog, fsck
  300. 300. 1. コミットの履歴を見る ① log (範囲指定について) ② gitk ① 指定したコミット範囲の著作者やコミットメッセー ジを表示します。
  301. 301. log (範囲指定について) log はコミットメッセージ等のコミットの情報を表示 します。ここではコミットの範囲指定について有用 なものを紹介します。 master HEAD bar foo backup
  302. 302. log log に何も指定しなければHEADを指定したことと 等価です。この場合、HEADから辿れる全コミット が対象になります。 master HEAD bar foo backup
  303. 303. log <commit-ish> コミットを指定した場合はその祖先全体が対象に なります。この状態では master を指定すれば HEAD を指定した場合と同じで… master HEAD bar foo backup
  304. 304. log <commit-ish> bar を指定すれば、barの祖先全体が対象になり … master HEAD bar foo backup
  305. 305. log <commit-ish> foo を指定すれば、foo の祖先全体が対象になり ます。 master HEAD bar foo backup
  306. 306. log <commit-ish>^ 既出ですが、コミットを指す名前に ^ を加えると、そ の親(ファーストペアレント)を指定したことになりま す。master^ を指定すれば図の範囲になります。 master HEAD bar foo backup
  307. 307. log <commit-ish>^ ちなみに本来 master^ が指すのはこのコミット(黄 色)だけである点に注意してください。log が master^から辿れる祖先全体を表示するのは、log がそのような仕様だからです。 master HEAD bar foo backup
  308. 308. log <commit-ish>^ ^は繰り返し指定可能です。master^^であれば図 の範囲で… master HEAD bar foo backup
  309. 309. log <commit-ish>^ master^^^であれば図の範囲になります。 ^のn回指定には ~n という省略記法が用意されて います。 master^^^ は master~3 と等価です。 master HEAD bar foo backup
  310. 310. log <commit-ish>^<n> ^ はファーストペアレントですが、 ^ の後ろには数 字で何番目の親かを指定できます。 backup^2 で あれば図のようにbackupの2番めの親になりま す。 ^^ や ~2 との違いに注意。 master HEAD bar foo backup
  311. 311. log <commit-ish>^<n> 「^」の覚え方ですが、上図のようにマージしたコミッ トの左側にファーストペアレント、右側に2番の親が ある状態の矢印の形と「^」を関連付けると覚えや すいです。 1 2 ^2
  312. 312. ^と~の組み合わせ ^[n] 指定(と~m 指定)を繰り返すことで祖先であれ ば任意のコミットを指定できます。 master^^2^であれば図の範囲… master HEAD bar foo backup
  313. 313. ^と~の組み合わせ master~2^2であれば図の範囲になります。 先に書いたとおりどんな祖先でも指定可能です が、実際には log や gitk などで目的のコミットの SHA1を調べて直接指定するほうが楽です… master HEAD bar foo backup
  314. 314. log <commit-ish>..<commit-ish> コミットをふたつのドットでつないだ範囲指定法が あります。X..Y であれば、Y およびその祖先に含 まれるコミットからXおよびその祖先をのぞいた範 囲、つまり Y - X を表します。 master HEAD bar foo backup
  315. 315. log <commit-ish>..<commit-ish> master..bar を見てみましょう。maser..bar は bar の祖先から master の祖先を取り除いたものです が、まず bar の祖先は図のような黄色の範囲で す。 master HEAD bar foo backup
  316. 316. log <commit-ish>..<commit-ish> master の祖先は図の青の範囲ですから、これを 取り除くと… master HEAD bar foo backup
  317. 317. log <commit-ish>..<commit-ish> 最終的に上図の黄色い部分がのこります。 これが master..bar という書き方が表す範囲です。 master HEAD bar foo backup
  318. 318. log <commit-ish>..<commit-ish> 逆に bar..master を見てみます。master の祖先 は図の青の範囲で… master HEAD bar foo backup
  319. 319. log <commit-ish>..<commit-ish> bar の祖先は図の黄色い部分ですから、これを取 り除くと… master HEAD bar foo backup
  320. 320. log <commit-ish>..<commit-ish> bar..master は図の青の範囲ということになりま す。 master HEAD bar foo backup
  321. 321. log <commit-ish>...<commit-ish> なお、ドットを3つにすると、 (X - Y) ∪ (Y - X)の意 味になります。 これは bar..master と master..bar の両方という意味です。bar...master であれば図 の範囲になります。 master HEAD bar foo backup
  322. 322. log --first-parent ファーストペアレントだけをたどるオプションもあり ます。log --first-parent master であれば図の範囲 になります。統合ブランチのログのサマライズに非 常に便利です。 master HEAD bar foo backup
  323. 323. 1. コミットの履歴を見る ① log ② gitk ② 指定したコミット範囲のコミットグラフをGUIで表 示します。

×