さて、Git がどんなものなのか、だいたいわかったでしょうか。というわけで、まずは、ひとりで Git を使ってみましょう。
なにはともあれ、まずはリポジトリを作らなくては話ははじまりません。リポジトリを作りましょう。
と、その前に!! Git のインストールはお済みですか?まずはインストールしてください。そのあと、初期設定みたいな感じで自分の名前とメールアドレスを設定しないとだめなので、それをやってみましょう。
$ git config --global user.name 'YOUR NAME'
$ git config --global user.email '[email protected]'
YOUR NAME
と [email protected]
はあなたの名前と email アドレスに置き換えて下さい。既にこの設定が済んでいる方はこの設定は飛ばしてかまいません。
済ませましたか?でははじめましょう。空っぽのリポジトリを作ってみます。
$ mkdir my_first_workspace
$ cd my_first_workspace
$ git init
mkdir my_first_workspace
で、 my_first_workspace という「作業ディレクトリ」を作っています。cd my_first_workspace
で、そのディレクトリに入っています。そこで、git init
をすることで、この作業ディレクトリに対応するリポジトリを作成しています。
「作業ディレクトリ」と「リポジトリ」の関係は頭に入ってますか? 頭に入ってないひとは VCS入門 をおさらいしましょう。
さて、これで、「作業ディレクトリ」と「リポジトリ」が出来上がりました。が、リポジトリは一体どこにつくられたのでしょうか?my_first_workspace ディレクトリにいる状態で、
$ ls -a
としてみましょう。ls
は、そのディレクトリにあるファイル一覧を確認するコマンドで、-a
は、「特殊なファイルも全て表示する」という意味です。さて、コマンドは打ちましたか? すると、下記のように、".git" というディレクトリが存在しているのが見て取れると思います。
. .. .git
この ".git" というディレクトリが、「リポジトリ」の正体です。workspace という「作業ディレクトリ」があるとき、その作業ディレクトリに対応する「リポジトリ」は、 workspace/.git である、ということですね。
今はコマンドラインから見てみましたが、ファイラーから見てみましょう(Mac 環境であることを前提として説明しますが、他の環境の場合はそれぞれのファイラーに置き換えてみてください)。Finder で、my_first_workspace ディレクトリを開いてみましょう。
あれっ!? ".git" が無いように見えますね!? じつは、 "." から始まるファイルやディレクトリは「隠しファイル」と呼ばれ、Finder からは見えないようになっています。大切な設定情報などが書き込まれているファイルは、誤操作で消してしまったりしないように、「隠しファイル」とされることが多いのです。リポジトリも、とても大切なものですよね。誤操作でリポジトリがふっとんじゃった!なんてことになったら、目もあてられないので、リポジトリは ".git" という "." で始まる隠しファイルとなっているわけです。ちなみに、Finder から隠しファイルを見れるようにする方法もあるのですが、ここでは脇道にそれてしまうため触れません。
とにかく、これで、「作業ディレクトリ」である "my_first_workspace" と、それに対応する「リポジトリ」である ".git" が出来上がりました。この「作業ディレクトリ」の中で編集されるファイル群が、「作業コピー」となります。
ちなみに、作業コピーでの変更内容をリポジトリに登録することを、「コミット」と言いますので、ついでにここで覚えておきましょう。
まずは、作業ディレクトリの中になにかファイルを作って見ましょう。どのようなやり方でもかまいません。いまはとりあえず
nyan
と書かれた nyan.txt というファイルを作業ディレクトリ内に作ってください。
作りましたか?
これで、作業ディレクトリ内に変化が起こりました。「なにもない」という状態から、「nyan.txtというファイルがある」という状態に変化したわけですね。では、この作業ディレクトリ内の変化を Git さんはどのように認識しているのでしょうか。その様子を見てみましょう。ターミナルで作業ディレクトリに入って、git status
と打つことで、「現在のリポジトリと作業コピーの状態を Git さんがどう認識しているか」が見れます。
$ cd path/to/my_first_workspace
$ git status
path/to/my_first_workspace
はおのおの自分が my_first_workspace を作ったパスに読み替えてください。
さて、上記のようにコマンドを打ってみると、
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# nyan.txt
nothing added to commit but untracked files present (use "git add" to track)
というような表示が出てきたかと思います。「ウワァ英語だ!助けて!」みたいにならないでください。少なくとも中学で3年間、多くのひとはそのあと高校で3年間はみっちり英語習ってきたでしょう。これくらいは読みましょう。
まず上から見ていきましょう。「On branch master」 とありますね。「ブランチ master 上だよ」と言っています。ブランチについて説明していないので、いまはこれは無視してかまいません。
そのあとに 「Initial commit」 と書かれていますね。「最初のコミットだよ」と書かれています。まだ一度もコミットしていないので、「この作業コピーをコミットするとこれが最初のコミットになるよ」って意味です。
そのあと、「Untracked files:」 と書かれていて、括弧のなかにごちゃごちゃ書かれてて、その下に nyan.txt と書かれています。つまり、「トラックされていないファイルは以下のとおりだよ:nyan.txt」といったところでしょうか。この場合の "トラック" は、「追跡する」の意味ですね。つまり、「追跡されてないファイルだよ」という意味です。「追跡されていない」とはどういうことでしょうか。だれがなにを追跡していないのでしょうか。
正解は、「Git はこのファイルを追跡してないよ」という意味です。つまり、Gitさんが、「なんか知らんファイルあるんだけど、おれこれどうしたらいいか知らんよ」って言ってるわけですね。「これどうしたらいいか知らんよ」と言っているので、この状態で「コミット」をしても、リポジトリはこのファイルを無視してしまいます。
では、さきほど無視した括弧の中を見てみましょう。 「use "git add <file> ..." to include in what will be committed」 と書かれています。「コミットされるものに含めたければ "git add <file>..." 使えば良いよ」ってことですね。親切な Git さんが、「これを追跡するためにはどうすればいいか」を教えてくれてるわけです。
最後に、「nothing added to commit but untracked files present (use "git add" to track)」 と書かれていますね。「コミットするものがなにもないよ、でも追跡されてないファイルがあるよ(追跡したければ "git add" するといいよ)」ともう一度説明してくれています。
英語、ちゃんと読めば、これだけ丁寧に情報が書かれているんです。たまに「なんか表示されたけど英語だから読まなかったです」みたいなひといるけど、読んでください。ググるまでもなく、ひとに聞くまでもなく、ちゃんと読めばちゃんと情報が出ているんです。
さて、上記をまとめると、今は「nyan.txtっていうファイルが作業コピー内にあるけど、リポジトリはそのファイルのこと追跡してないよ、だからまだコミットできないよ」という状態であることがわかりました。
さて、さきほど git status
を打ったときの出力ですが、もしかしたら、
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# .DS_Store
# nyan.txt
nothing added to commit but untracked files present (use "git add" to track)
という感じで、身に覚えない .DS_Store というファイルが「Untracked files」として表示されてしまったひともいるかもしれません。この .DS_Store というファイルは、Mac OS が勝手に作る、「このフォルダのアイコンの並び順はこんな感じで表示サイズはこのくらい」みたいな情報が入ったファイルです。このファイルは、リポジトリで管理する必要のないファイルですね。むしろ、このファイルはそれぞれの環境によって内容が異なるので、リポジトリで管理すると無用なトラブルのもとになります。こういうときには、「.DS_Storeっていうファイル、無視してね」と Git に教えてあげましょう。その方法はふたつあります。
- .gitignore というファイルをリポジトリに作成する。すると、リポジトリは .gitignore の中に名前が書かれているファイルは無視する
- どのリポジトリでも .DS_Store という名前のファイルを無視するように Git を設定する
「このリポジトリの中では無視したいファイルなんだけど、他のリポジトリの中では無視したいわけではない」みたいなファイルは .gitignore に書く方法がいいでしょうし、どんな場合にも無視してほしいようなファイルに関してはグローバルに無視する設定をしたほうがいいでしょう。今回の .DS_Store は、どんなリポジトリにも追加したくない類いのものだと思いますので、今回はその方法を取りましょう。ターミナルを開いて、以下のコマンドを打ってください。
$ git config --global core.excludesfile ~/.gitignore_global
$ echo ".DS_Store" >> ~/.gitignore_global
一行目で、「グローバルに無視するファイル名を書いたファイルは ~/.gitignore_global というファイルだよ」と Git に教えてあげています。二行目で、そのファイルに ".DS_Store" を書き込み、Git に「.DS_Storeは無視してね」と教えています。
.gitignore ファイルの書き方には触れないので、グーグル先生に聞いてください。
さて、ここで再度
$ git status
してみましょう。今度は、.DS_Store が 「Untracking files:」 から消えて、Git が完全にその存在を無視していることが見て取れるでしょう。
さて、作業ディレクトリの中で新しいファイルを作っただけでは、そのファイルは untracked な状態なのでした。では、この untracked な状態のファイルを、リポジトリに track してもらいましょう。git status したときに Git さんが丁寧に教えてくれたので、その方法をあなたはもう知っているはずです。そうです。 git add
ですね。ではやってみましょう。
$ git add nyan.txt
これで、「nyan.txtを track してね」と Git さんに伝える事ができました。ではここで再度 git status
してみましょう。
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: nyan.txt
#
このような出力が得られたかと思います。ちょっと内容が変わってますね。英語だけど頑張って読んでみましょう。
「Initial commit」のところまではいいでしょう。その下、「Changes to be committed:」と書かれていて、括弧のなかにごにょごにょ書かれていて、その下に「new file: nyan.txt」とあります。日本語にすれば、「コミットされる変更は以下の通りです。・新しいファイル: nyan.txt」といったところでしょうか。つまり、この状態でコミットをすると、nyan.txt に対して行った変更がコミットされるよ、ということですね。いい感じです!
では、括弧のなかにはなんて書いてあるでしょうか。 「use "git rm --cached <file>..." to unstage」 だそうです。「unstage するには、 "git rm --cached <file>..." ってすればいいよ」ってことですね。ん? 新しい単語が出てきましたね。unstage とはなんでしょうか。というわけで、 stage と unstage について説明しましょう。
Git では、コミットの前に、「作業ディレクトリ内のこのファイルの内容はリポジトリに反映してほしいけど、このファイルの内容は反映してほしくない」みたいなことを Git に教えておく必要があります。そうしないと、Git さんはコミットのときに「えっこれどのファイルのどの変更をリポジトリに反映すればいいの!?」となってしまいます。このとき、「次にコミットするときにリポジトリに反映される内容の置き場」のことを、"staging area" と呼んでいます。
つまり、さっき git add nyan.txt
としたことで、nyan.txt はその時点でのそのファイルの内容が「staging area に上げられた」ことになります。これを、 「stage する」と言います。この状態で commit を行うと、Git は stage に上がっている内容をリポジトリに登録します。では unstage とは? もうお分かりでしょう。「stage」が「staging areaにファイルを置く」なので、「unstage」はその逆、「staging area からファイルの内容を取り下げる」です。では、実際にやってみましょう。「use "git rm --cached ..." to unstage」でしたね。今回は nyan.txt を unstage するので、以下のようになります。
$ git rm --cached nyan.txt
はい、ではここでもう一度 git status
で状態を見てみましょう
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# nyan.txt
nothing added to commit but untracked files present (use "git add" to track)
おおー。nyna.txt が Untracked files に戻っていますね。
こんな感じで、「作業ディレクトリで行った変更のうち、リポジトリに反映してほしいもの」を stage したり、「リポジトリに反映してほしくない変更」を unstage することで、どういう変更をリポジトリに反映させたいのかを Git さんに教えてあげましょう。
とりあえず今回は nyan.txt に行った変更を反映させたいので、再度 nyan.txt を stage しておきましょう。
$ git add nyan.txt
$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: nyan.txt
#
さて、それでは、ついに commit をしてみましょう。コミットをするには、
$ git commit
です。 git commit
とすると、エディタが立ち上がります。おそらく vi というターミナル内で動くエディタが立ち上がったのではないでしょうか($EDITORを設定してるような中級者以上の読者は想定してないのでそういうひとは自分で読み替えてください)。vi の使いかたについてはここでは触れないので、Google 先生に聞いてください。慣れると使いやすいですよ。
「えっなにこれは」「怖い」ってなったひとは、かなりの荒技ではありますが、Mac での標準のエディタを使うのもひとつの手かもしれません。とりあえず今はこの怖い画面を "[Esc]:q!"と打って([Esc]はエスケープキー) 抜け出してしまいましょう。そのあと、
$ git config --global core.editor 'open -t -W'
と打ってください。すると、次回のコミットからは Mac のテキストエディタが開きます。これで怖くないエディターを利用できますね!
Linuxを普段から使ってる場合はどうすればいいのかって? そういうひとは vi くらい使えるでしょ!
Windowsを使ってるひとはどうすればいいのかって? わたしもわかりません……
さて、エディタが立ち上がった画面には、先ほど git status
で確認したのと似たような、でもちょっとだけ違うものが出力されているかとおもいます。では、また英語を読みましょう。何度も言うけど、出力された英語をちゃんと読めば必要な情報はそこに書いてあります。四の五の言わずに読んでください。
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: nyan.txt
#
「On branch masater」 以下の表示については前みた通りなので説明しなくていいですね。さて、では最初の段落になんと書いてありますか?
「君がやった変更についてのコミットメッセージを書いてくれよな! '#'で始まる行は無視するぜ!空のメッセージ書きやがったらこのコミットを中止するからな!」と書いてあります。Git さんのキャラがぶれてきている気がしますがまあ気にせず進めましょう。
ところで、では「コミットメッセージ」とはなんでしょうか。コミットを進める前に、コミットメッセージについて少し話をしておきましょう。
何度も参照している VCS入門 を紐解いてみましょう。
VCSの能力は、主に次の2つです。
- 履歴を残す
- 作業の競合を防ぐ
VCS入門より
この、「履歴を残す」というのは、「誰が」「いつ」「何を」したかを残すということでしたね。「誰が」「いつ」の履歴を残すところまでは Git さんが面倒を見てくれますが、「何を」したかまでは、機械にはわかりません。なので、「何をしたか」を、コミットメッセージとして残しておく必要があるのです。
ただ、「何をしたか」は機械にはわからないと言っても、もちろん、「どのファイルを編集した」まではわかります。ここで言う「何をしたか」というのは、もっと現実世界の話、つまり、「ほげほげがふがふがしてしまうバグを直した」だとか、「ほげほげ画面にふがふが機能を追加した」とか、そういう話です。
こういうメッセージを残しておくことで、あとで履歴を見るときに「なるほどなるほど〜」と言いながら見ることができるわけですね。ちなみに、良いコミットメッセージとはどんなメッセージなのかということも、さきほどの VCS 入門に書かれています。熟読しておきましょう。
さて、コミットメッセージとはなにかがわかったところで、コミットメッセージを書いてみましょう。今回だと「猫の鳴き声を管理するファイルを作成」という感じでしょうか。
'#'から始まる行は無視される、とあるので、#から始めずに、「猫の鳴き声を管理するファイルを作成」というメッセージを書いて、保存、エディタを終了してみましょう。Macのエディタを開いてるひとは、ウィンドウを消すのではなくて、終了まで行う必要があります。言い方を変えれば、⌘+W ではなくて ⌘+Q です。
$ git commit
[master (root-commit) 33028c1] 猫の鳴き声を管理するファイルを作成
1 file changed, 1 insertion(+)
create mode 100644 nyan.txt
終了したらこんな感じになりました。なんかいろいろ出てきましたね。おめでとうございます!これで、初めてのコミットができました!
VCS の能力として、「履歴を残す」というのがあると言いました。では履歴を見てみましょう。git log
で見れます
$ git log
commit 33028c115cc19cf6122fc2004fc6393a22712d23
Author: Shinpei Maruyama <[email protected]>
Date: Fri May 3 22:32:52 2013 +0900
猫の鳴き声を管理するファイルを作成
お、ちゃんと履歴が残っていますね。一行目になんかおそろしげな文字列がありますが、次に説明するのでとりあえず無視しましょう。その下のAuthorのに「だれが」が、さらにその下の Date に「いつ」が、その下に「何を」行ったかがきちんとリポジトリに登録されています。yippie!
おっと、もしかしたら、履歴がターミナルの全画面に表示され、もとにもどれなくて困っていますか?そんなときには、キーボードの「q」を推してみてください。これでもとに戻れます。「quit」の q ですね。
さあ、はじめてのコミットは成功しましたが、まだまだこの章は終わりません。コミットしたとき、リポジトリに一体なにが起こっているのでしょうか。それを見てみましょう。
コミットされたとき、リポジトリには新しい「コミットオブジェクト」というものが生まれます。では「コミットオブジェクト」とは一体なんなのでしょうか。
簡単に言うと、コミットオブジェクトは、「staging されていたファイルの内容 + コミットメッセージ」みたいなものです。git commit したことにより、stage されていた内容が、コミットメッセージとともに「コミットオブジェクト」となり、リポジトリに大切にしまわれた、という感じです。こうして「そのときの内容」をオミットオブジェクトに詰め込んで保存しておけば、いつでもこのときの状態を復元できることができますね。
そして、次にまたなにかファイルを変更してそれをコミットすると、また新しいコミットオブジェクトが作られ、リポジトリにしまわれます。それぞれのコミットオブジェクトには一意の id がついていて、それがさっきみた謎の文字列です。
commit 33028c115cc19cf6122fc2004fc6393a22712d23
これは、このコミットオブジェクトの id が "33028c115cc19cf6122fc2004fc6393a22712d23" だよ、ということを表しているのですね。
ひとまず今はそんなふうに思っておいてください。
リポジトリを作るところから、最初のコミットまで、ていねいに見てみました。ポイントをおさらいしておきましょう。
- workspaceという作業ディレクトリに対応するリポジトリは、 workspace/.git に作られる
- 作業ディレクトリで作業しただけでは、コミットしたときに Git はその変更内容をリポジトリに登録していいのかどうかわからない
- なので、
git add
などのコマンド(その他のコマンドも後で出てきます)をつかって、変更したファイルをstageする(「staging area」に置く) - 一度 stage されたファイルは、
git rm --cached
などのコマンドを使って unstage する(「staging area」から取り下げる)ことができる git commit
を行うと、エディタが立ち上がるのでコミットメッセージを書いて保存、終了する。すると、staging areaに上がっていた変更内容がコミットメッセージとともにリポジトリに反映される。このとき、stage されていたファイルの内容とコミットメッセージは「コミットオブジェクト」としてリポジトリ内に保存されている。
今回のポイントは以上です。次回は「二回目のコミット」をしますよ!わくわく!