Pro Gitと入門gitでGitの復習 ブランチ編
参考
- Git - Book
- 入門git
他のVCSとの違い
- Subversionなどは各ファイルに対しての差分を時間軸で持っていた
- Gitではコミットのたびにその時のリポジトリ全体のスナップショットをとる
- ただし、変更がなかったファイルは以前のスナップショットで格納したファイルへのリンクを貼っている
Gitのオブジェクト
Gitには大きく分けて4つのオブジェクトが存在する。
- Commitオブジェクト
- Treeオブジェクト
- Blobオブジェクト
- Tagオブジェクト
Commitオブジェクト
リポジトリのルート。ファイル情報(ツリー)やメタデータを格納している。以下のコミットのCommitオブジェクトを見てみる。
$ git log --pretty=oneline 5f431a8cf6023e7398102dfef8b88baf1c581023 Typo 4
log --pretty=rawコマンドを実行するとハッシュタグがいろいろと。
$ git log --pretty=raw 5f431a8cf6023e7398102dfef8b88baf1c581023 commit 5f431a8cf6023e7398102dfef8b88baf1c581023 tree de445cf5b526c554dea465d09cea6d65059d1f80 parent a59ff99de68cbf359c814f25cda9c926ef9cdad9 author kk_Ataka <test@example.com> 1329818747 +0900 committer kk_Ataka <test@example.com> 1329819044 +0900 Typo 4
commit | このコミットに対するSHA1名 |
---|---|
tree | このコミットの中身を記載しているSHA1名 |
parent | 一つ前のコミットのSHA1名。存在しない場合はそれが一発目(Rootコミット)、マージされた場合は1つ以上になる場合もある |
author | 作成者 |
committer | コミッター |
author, committerあたりがメタデータになるのかな。
Treeオブジェクト
あるコミット時点の中身を格納している。ls-treeコマンドかshowコマンドで確認が出来る。ls-treeコマンドの方が詳しい。
$ git ls-tree 5f431a8cf6023e7398102dfef8b88baf1c581023 100644 blob 27f338f5bd0c368f96e063127705bd1bb81e992a README # ファイル 100644 blob 0dc64072619bf0734c878d90e9150b6978898083 index.html # ファイル 100644 blob 543200914423ddc0cb2249c322f262e31ee11c55 menu.html # ファイル
100644 blob c447b5cfd585f44aafef7d513c5efea5471e2848 convert.rb # ファイル 040000 tree a1117a81580de591d292b9e6d80deee3e1cabd85 testdata # ディレクトリ #testdataディレクトリを調査 $ git ls-tree a1117a81580de591d292b9e6d80deee3e1cabd85 040000 tree a9da0b188817cc119eff96f4c8db5306d0be009d init # ディレクトリ #initディレクトリを調査 $ git ls-tree a9da0b188817cc119eff96f4c8db5306d0be009d 100644 blob 2918a6642d19aadf2b11213978ae6044166a87e0 read_cell # ファイル
showで調査する場合はこんな感じ。ファイル名だけ?
#initディレクトリを調査 $ git show a9da0b188817cc119eff96f4c8db5306d0be009d tree a9da0b188817cc119eff96f4c8db5306d0be009d read_cell
実行権、ファイルタイプ、SHA1名、ファイル名が出力される。ファイルタイプは超ざっくりこんな感じみたい。
blob | 普通のファイル |
---|---|
tree | ディレクトリ |
Blobオブジェクト
ファイルそのもの。showコマンドで見る事が出来るのはファイルの中身。
#READMEを調査 $ git show 27f338f5bd0c368f96e063127705bd1bb81e992a Hello Wrld
#index.htmlを調査 $ git show 0dc64072619bf0734c878d90e9150b6978898083 <html> <head> <title>Welcome</title> </head> <body> <h1>Hello</h1> <p>Hello world !!</p> </body> </html>
#menu.htmlを調査 $ git show 543200914423ddc0cb2249c322f262e31ee11c55 <html> <head> </head> <body> <h1>menu</h1> </body> </html>
で、ブランチ
ブランチはこの一つのCommitオブジェクトをさすポインタとなる。今は最新がこれ。
$ git log --pretty=raw 5f431a8cf6023e7398102dfef8b88baf1c581023 commit 5f431a8cf6023e7398102dfef8b88baf1c581023 tree de445cf5b526c554dea465d09cea6d65059d1f80 parent a59ff99de68cbf359c814f25cda9c926ef9cdad9 author kk_Ataka <test@example.com> 1329818747 +0900 committer kk_Ataka <test@example.com> 1329819044 +0900 Typo 4
で、branchコマンドでブランチを確認すると……。
$ git branch * master
masterというブランチがある。これは最初にコミットした時点で作られるブランチ。次にまたコミットをするとmasterブランチはそれを追いかけていく。
ブランチの作成
branch [newbranch]で作成。
$ git branch checkpoint1
branchコマンドで確認ができる。アスタリスクがついているのブランチが今のブランチ。
$ git branch checkpoint1 * master
ブランチの確認
基本はbranchコマンドで確認できる。
$ git branch checkpoint1 * master
vオプションでCommitオブジェクトのSHA1とログなどを冗長に確認できる。今は全部同じだが……。
$ git branch -v checkpoint1 5f431a8 Typo 4 * master 5f431a8 Typo 4
rオプションでリモートのブランチも確認できる。(まだよくわかってない)
$ git remote -v rem1 c:/project/testRemote/remote1.git (fetch) rem1 c:/project/testRemote/remote1.git (push) rem2 c:\project\testRemote\remote2.git (fetch) rem2 c:\project\testRemote\remote2.git (push) $ git branch -rv rem1/master 5f431a8 Typo 4 rem2/master 5f431a8 Typo 4
ブランチの削除
branch d [branch]、またはbranch D [branch]で削除する事ができる。
$ git branch -d checkpoint1 Deleted branch checkpoint1 (was 5f431a8). $ git branch * master
ちなみになうなブランチは削除できない。
$ git branch -d master error: Cannot delete the branch 'master' which you are currently on.
dオプションとDオプションの違いは"今のブランチから到達不可能なブランチの削除を試みた場合"、警告を出す(d)か強制削除(D)か、らしい。どういうことだろう?
→parent,parentで過去へ遡及はできそうだけど、そこから未来には進めなさそう?
ブランチを切り替える
checkoutコマンドを使う。
$ git branch checkpoint1 $ git checkout checkpoint1 Switched to branch 'checkpoint1' $ git branch * checkpoint1 master
ブランチを作りつつcheckoutも同時に行う事もできるcheckout -b [newbranch] [branch]
$ git checkout -b check-b master Switched to a new branch 'check-b' $ git branch * check-b checkpoint1 master
ただし、作業ディレクトリにファイル作りっぱなしとかステージングしっぱなしの状態だと原則としてブランチの切り替えはできない。
$ git checkout master error: Your local changes to the following files would be overwritten by checkout: index.html Please, commit your changes or stash them before you can switch branches. Aborting
HEAD??
Git系のBlogエントリとか読んでるとちょいちょい出てくるHEAD。これは.gitディレクトリの中のHEADファイルに定義されていて、常に今作業中のブランチを指す、という事になっている。よく見たら前のエントリでgit reset HEAD [resetfile]というコマンドをうっていた!
$ git branch check-b checkpoint1 * master $ cat .git/HEAD ref: refs/heads/master
masterの時はHEADもmasterだ。
$ git checkout checkpoint1 Switched to branch 'checkpoint1' $ git branch check-b * checkpoint1 master $ cat .git/HEAD ref: refs/heads/checkpoint1
別のブランチに切り替えるとHEADも変わる。logコマンドでCommitオブジェクト(SHA1)の代わりにHEADを指定すると見れる!
$ git log --pretty=raw HEAD commit 5f431a8cf6023e7398102dfef8b88baf1c581023 tree de445cf5b526c554dea465d09cea6d65059d1f80 parent a59ff99de68cbf359c814f25cda9c926ef9cdad9 author kk_Ataka <test@example.com> 1329818747 +0900 committer kk_Ataka <test@example.com> 1329819044 +0900 Typo 4 commit a59ff99de68cbf359c814f25cda9c926ef9cdad9 (略)
この辺は各々のブランチの歴史を進めた上で比較しないと全部同じだからわかりづらいな。次はマージから。