Gitについて自分なりに説明してみた
友達に説明する必要があったのでGitの使い方を誤解を恐れずメモしておきます。自分の知識の整理も兼ねています。
この記事ではローカルマシン(一台のPC)での操作で完結しています。リポジトリの作成、コミットの作成、ブランチの作成、マージまでを範囲としています(これらの単語は順を追って説明していけたら、と思います)(ブランチの扱いは、最終的なリポジトリの形としてはgithub-flow
です。)
Gitの概要
Gitは 分散型バージョン管理システム です。というとやばく聞こえますが、Gitを使う目的は 「大勢で1つのアプリケーションを一緒に作ること」 です。なのでそのために必要そうなバージョン管理機能がちゃんと備わっています。これあるべきでしょうとか予想しながら読んでいっていただけるといいかと思います。以下チュートリアルを通して概念と機能を説明していきます。
この記事を読み進めるために
- 環境: Mac (他の環境の場合、概念と機能の説明は問題ありませんが、手順に関して読み替えが必要です)
- 知識: ターミナルの基本的な操作 (自信がなくなった場合、こちらかこちらを適宜参考にしながら読んでいただければ幸いです)
チュートリアルを始める前にちょっとした下準備を行います。
(下準備)gitコマンドがインストールされているか確認
今回は CLI での使い方を説明していきます。他の使い方としては、GUIアプリケーションなど沢山開発されているのでそれ経由で操作するのもありです。(その場合GUIアプリの解説ページに色々書いてあると思うので、この記事は閉じてしまって大丈夫です!)
Macを使っている場合、すでにGitがインストールされているかと思います。アプリケーションフォルダのユーティリティの中にある ターミナル.appを開いて、Gitがインストールされていることを確認してみましょう。ターミナルを開いたらgit --version
と入力して、実行してください。
$ git --version git version 2.13.6 (Apple Git-96)
git version ...
のような表示が出たらインストールされています。
$ git --version -bash: git: command not found
と出たらインストールされていないので、ググってインストールしてください。
(下準備)Gitの初期設定
以下のコマンドを実行して、Gitのユーザー名、アドレスが登録されていることを確認してください。
$ git config user.name ushumpei $ git config user.email mail@ushumpei.com
登録されていない(実行しても何も表示されない)場合は次のコマンドを実行してユーザー情報を登録しておいてください。
$ git config --global user.name "あなたの名前" $ git config --global user.email あなたのアドレス
チュートリアル
リポジトリ作成
Gitによるバージョン管理はファイル単位で行われます。と言ってもコンピューターすべてのファイルを管理するわけではなく、管理する範囲は限定することができます。限定できる範囲はディレクトリ(フォルダ)単位で、Gitによって管理されるのはそのディレクトリに含まれているすべてのファイルになります。この限定された範囲を リポジトリ(repository) と呼びます。
実際にリポジトリを作ってみましょう。デスクトップにgit_tutorial
リポジトリを作ります。
ターミナルで 1.デスクトップに移動
2.git_tutorialディレクトリの作成
3.新規ディレクトリ内へ移動
4.ディレクトリのgitリポジトリ化
を行います。TAB
キーでファイル名を補完したりして頑張ってください。
~$ cd ~/Desktop/ ~/Desktop$ mkdir git_tutorial ~/Desktop$ cd git_tutorial ~/Desktop/git_tutorial$ git init Initialized empty Git repository in /Users/ushumpei/Desktop/git_tutorial/.git/
Initialized empty Git repository in ...
が出たら成功です。リポジトリが完成しました。
注意: もしかすると日本語環境の場合~/Desktop
がないかもしれないです(この辺りは自信ないです)。~/デスクトップ
など試してみてください。
git status
というコマンドを実行して見てください。このコマンドは現在のリポジトリの状態を表示してくれるものです。 とてもよく使います 、他のコマンドを打つ際もこのコマンドで実行前、実行後の変化の確認をしながらやると何をしているかわかってくると思います。
~/Desktop/git_tutorial$ git status On branch master Initial commit nothing to commit (create/copy files and use "git add" to track)
各行の意味は以下です。不明な単語については後ほど説明いたします。
- 現在は
master
という ブランチ(branch)にいる - まだ コミット(commit) が存在しない
- コミットの対象に含まれているものはない
Initial commit
管理下にあるファイルに対して、「誰が、いつ、なぜ、どのファイルの、どこの部分を、どのように変更したか(変更に関する5W1H)」という変更情報を管理するのがGitの大きな役割です。この変更情報は コミット(commit) と呼ばれます。コミットは開発者が好きな粒度で作成することができます、複数ファイルの変更を1つのコミットに含めるのが一般的です。
(コミットのイメージ) 変更理由: モバイルブラウザでトップページの挨拶文の表示が崩れてしまっていたので修正 日付: 2017/11/27 変更者: ushumpei index.htmlというファイルの12行目を`<p>こんにちは</p>`から`<h1>こんにちは</h1>`に変更 stylesheet/mobile.cssというファイルを追加
コミットを作成する手順は次のようになります;
- 変更: リポジトリ内でファイルに関する変更を行う(作成、更新、削除のどれか)
- ステージ:
git add
、git rm
などのコマンドで、どの変更内容を履歴に残したいかGitに知らせる - コミット:
git commit
コマンドで変更履歴を作成する
超個人的なイメージではGit管理下のファイルを変更したら「変更内容の紙が出てくる(変更) -> 変更に含めたい紙を束ねる(ステージング) -> キリのいいところで束を箱に入れる(コミット)」ということをやっている感じです。
では実際にファイルを作り、Gitの管理下に追加してみます。1.ファイルの作成
2.ファイルを追加対象に含める
3.追加
の流れになります。git status
を使いながら1つ1つ変化を追って確認していきましょう。
~/Desktop/git_tutorial$ git status On branch master Initial commit nothing to commit (create/copy files and use "git add" to track)
先ほどと同じ状態です。
~/Desktop/git_tutorial$ touch index.html # index.htmlが作成されたので、好きなエディタで開いて以下の内容を記述して保存してください(# は不要です); # <html> # <head> # <title>git_tutorial</title> # </head> # <body> # <p>Git Tutorial</p> # </body> # </html> ~/Desktop/git_tutorial$ git status On branch master Initial commit Untracked files: (use "git add <file>..." to include in what will be committed) index.html nothing added to commit but untracked files present (use "git add" to track)
git status
によると、依然としてコミットの対象に含まれているものはないですが、新しくindex.html
というファイルが作成されていて、まだGit管理下に入っていないという情報が表示されています。
Git管理下に含めるにはgit add
コマンドを実行してくださいという指示が括弧中に記載されているので実行します。
~/Desktop/git_tutorial$ git add index.html ~/Desktop/git_tutorial$ git status On branch master Initial commit Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: index.html
git status
によると、コミットの対象に「index.htmlを新規作成した」という変更を追加する準備ができたことが表示されています。この状態をindex.html
の変更が ステージ(stage) されていると言い、この変更のステージを取りやめることを アンステージ(unstage) すると言い、git rm --cached index.html
(場合に応じてgit reset HEAD index.html
)でGitに知らせることができます。
最後にステージされている変更からコミットを作成してみましょう。
~/Desktop/git_tutorial$ git commit -m "Initial commit" [master (root-commit) c04dc8f] Initial commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 index.html ~/Desktop/git_tutorial$ git status On branch master nothing to commit, working tree clean
上記のように、追加に関する情報が表示されたら成功です。git status
の結果は変更を全く行なっていない状態に戻っているかと思います。
これで 変更->ステージ->コミット の1サイクルが終わりました。Initial commitの部分は変更理由を記述します。慣習としてリポジトリを作成した直後のコミットはInitial commitと書くことが多いです。
作成したコミットを見る: git log
作成したコミットを見て見ましょう。git log
、git log -p
を実行してください。
~/Desktop/git_tutorial$ git log commit c04dc8ffd000dd7ba23b20177c208e9095901d19 (HEAD -> master) Author: ushumpei <shumpei.uzawa@gmail.com> Date: Tue Nov 28 00:59:56 2017 +0800 Initial commit ~/Desktop/git_tutorial (master)$ git log -p commit c04dc8ffd000dd7ba23b20177c208e9095901d19 (HEAD -> master) Author: ushumpei <shumpei.uzawa@gmail.com> Date: Tue Nov 28 00:59:56 2017 +0800 Initial commit diff --git a/index.html b/index.html new file mode 100644 index 0000000..e69de29
上記のコマンドで過去に行なったコミット内容が全て確認できます。変更の詳細がいらない場合はgit log
、詳細を見たい場合はgit log -p
変更履歴が確認できます。
更新
続いてindex.html
を更新してコミットして見ましょう。index.html
をエディタで開いて以下のように修正してください。(6行目のpタグをh1タグに変更します)
... <h1>Git Tutorial</h1> ...
git status
を実行して変化を見てみてください。
~/Desktop/git_tutorial$ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: index.html no changes added to commit (use "git add" and/or "git commit -a")
index.html
が変更されたことが表示されています。もしstageしたいなら先ほどと同様にgit add index.html
、変更を破棄して最後のコミットの状態に戻したいならgit checkout index.html
を実行してくださいという指示が書かれています。
ここでどんな変更が行われたかを確認するコマンドgit diff
を使ってみましょう。
~/Desktop/git_tutorial$ git diff diff --git a/index.html b/index.html index 135d8e3..243ca88 100644 --- a/index.html +++ b/index.html @@ -3,6 +3,6 @@ <title>git_tutorial</title> </head> <body> - <p>Git Tutorial</p> + <h1>Git Tutorial</h1> </body> </html>
index.html
に対する変更が表示されています。先ほど行なった通り、pタグの行が削除され(- <p>Git Tutorial</p>
)、h1タグの行が追加され(+ <h1>Git Tutorial</h1>
)ていることがわかります。そのまんまですが、行頭の-
は削除、+
は追加の意味です。(差分は文字単位ではなく、行単位での表示となります)
この変更で問題ないのでステージしてコミットしましょう。
~/Desktop/git_tutorial$ git add index.html ~/Desktop/git_tutorial$ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: index.html ~/Desktop/git_tutorial$ git commit -m "ページタイトルなのでh1にタグを変更" [master 081f264] ページタイトルなのでh1にタグを変更 1 file changed, 1 insertion(+), 1 deletion(-) ~/Desktop/git_tutorial$ git status On branch master nothing to commit, working tree clean
1サイクルが終わりました。これまで行なった作業を確認するために、git log --graph
を実行してみてください。2つのコミットが追加されていることが確認できるかと思います。
~/Desktop/git_tutorial$ git log --graph * commit 081f264cc85e5074a93f7304ba2febf9efb90bd9 (HEAD -> master) | Author: ushumpei <shumpei.uzawa@gmail.com> | Date: Tue Nov 28 10:17:57 2017 +0800 | | ページタイトルなのでh1にタグを変更 | * commit b80d4812cbde6655bee82bfa20127519e8826b81 Author: ushumpei <shumpei.uzawa@gmail.com> Date: Tue Nov 28 10:02:38 2017 +0800 Initial commit
--graph
オプションをつけて実行したので、2つのコミットが線で繋がって表示されています。これは ブランチ(branch) と呼ばれる概念に関係しています。
ブランチ(branch)
ブランチ(branch) について説明します。ブランチは連続したコミットの集まりです。先ほど作った2つのコミットはmaster
ブランチの先頭に追加されています、どんどんコミットを重ねてブランチ(枝)を伸ばしていくイメージです。
ブランチと呼ばれるからには 枝分かれ させることができます、ブランチの途中から別の ブランチを生やして そちらを伸ばしていくことができます。この機能により、ブランチを分けることによって複数の開発者が互いに影響を受けずに並列に開発を行っていくことができます。(あとで出てきますが、枝分かれしたブランチは好きなタイミングで他のブランチに合流させることができます)
リポジトリにどんなブランチがあるのかはgit branch
コマンドで確認できます。
~/Desktop/git_tutorial$ git branch * master
Gitリポジトリを作った直後、ブランチはmaster
しかありません。先ほどのindex.html
に関する変更はmaster
に追加していました。master
から違うブランチを生やしてコミットを追加してみましょう。ブランチの作成はgit branch ブランチ名
です。
# 一行目より現在masterブランチにいることがわかります ~/Desktop/git_tutorial$ git status On branch master nothing to commit, working tree clean # stylingブランチを作成 ~/Desktop/git_tutorial$ git branch styling # ブランチ一覧にstylingが表示されています、「*」は現在いるブランチを表しています ~/Desktop/git_tutorial$ git branch * master styling # git checkout ブランチ名でstylingブランチに移動します ~/Desktop/git_tutorial$ git checkout styling Switched to branch 'styling' # 一行目より現在stylingブランチにいることがわかります ~/Desktop/git_tutorial$ git status On branch styling nothing to commit, working tree clean # ブランチ一覧でも同様に確認できます ~/Desktop/git_tutorial$ git branch master * styling
それではstyling
ブランチの先頭にコミットを追加します。スタイルシートファイルstyle.css
を作成して、index.html
でそれを読み込んでスタイルを適用しましょう。
~/Desktop/git_tutorial$ touch style.css # style.cssを好きなエディタで開いて以下の内容を記述して保存してください; # h1 { # color: #727272; # font-family: monospace; # } # # index.htmlは次のようにheadタグ内にlinkタグを追加してください; # <html> # <head> # <title>git_tutorial</title> # + <link rel="stylesheet" href="./style.css" /> # </head> # ... ~/Desktop/git_tutorial$ open index.html # ブラウザで表示してみてもいいかもです # 変更の確認をしましょう。index.htmlが変更され、style.cssが追加されています ~/Desktop/git_tutorial$ git status On branch styling Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: index.html Untracked files: (use "git add <file>..." to include in what will be committed) style.css no changes added to commit (use "git add" and/or "git commit -a") # index.html、style.cssをステージします ~/Desktop/git_tutorial$ git add . # 2つのファイル変更がステージされています ~/Desktop/git_tutorial$ git status On branch styling Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: index.html new file: style.css # コミットします。現在stylingブランチにいるのでコミットはstylingブランチの先頭に追加されます(stylingブランチが1つ伸びます) ~/Desktop/git_tutorial$ git commit -m "スタイルシートを追加" [styling 59df46b] スタイルシートを追加 2 files changed, 5 insertions(+) create mode 100644 style.css
コミットが追加されました。ブランチの形を確認してみましょう。
~/Desktop/git_tutorial$ git log --graph * commit 59df46ba1df6e9a29584dd2ad2d95b79248f0409 (HEAD -> styling) | Author: ushumpei <mail@ushumpei.com> | Date: Tue Nov 28 11:10:48 2017 +0800 | | スタイルシートを追加 | * commit 081f264cc85e5074a93f7304ba2febf9efb90bd9 (master) | Author: ushumpei <mail@ushumpei.com> | Date: Tue Nov 28 10:17:57 2017 +0800 | | ページタイトルなのでh1にタグを変更 | * commit b80d4812cbde6655bee82bfa20127519e8826b81 Author: ushumpei <mail@ushumpei.com> Date: Tue Nov 28 10:02:38 2017 +0800 Initial commit
3つめのコミットが今追加したものです。今は直線で表示されているので枝分かれ感が薄いですが、2つめのコミットからstylingブランチがmasterブランチから分かれて、1コミット分伸びたという情報が表示されています。このコミットの変更はmasterブランチには影響しません。そのことをmasterブランチに移動して確認してみましょう。ブランチの移動はgit checkout ブランチ名
です。
# masterブランチへ移動 ~/Desktop/git_tutorial$ git checkout master Switched to branch 'master' # 状態の確認 ~/Desktop/git_tutorial$ git status On branch master nothing to commit, working tree clean # ファイルの確認 ~/Desktop/git_tutorial$ ls index.html
先ほど追加したファイルstyle.css
が存在しないことがわかります。またmasterブランチ上でgit log
を行うとまだコミットが2つしかないことが確認できます。
~/Desktop/git_tutorial$ git log commit 081f264cc85e5074a93f7304ba2febf9efb90bd9 (HEAD -> master) Author: ushumpei <mail@ushumpei.com> Date: Tue Nov 28 10:17:57 2017 +0800 ページタイトルなのでh1にタグを変更 commit b80d4812cbde6655bee82bfa20127519e8826b81 Author: ushumpei <mail@ushumpei.com> Date: Tue Nov 28 10:02:38 2017 +0800 Initial commit
(補足) なぜブランチを分けるか?全てmaster
にコミットしないのはなぜ?
それは多くの場合、master
ブランチは実際にユーザーが使っているアプリケーションのソースコードになることが多いからです。レビュー、テストを経て開発者みんなで合意したソースコードのみがmaster
に存在します。なのでmaster
ブランチへの変更は完全な状態で行われなければいけません。作業途中のコードを追加するといったことは避けるべきです。しかし開発作業では区切りのいいところでコミットしていく方が、全てのコードを書き終わってからコミットする(ゲームをセーブしないでクリアするようなものです)よりも断然楽です。なので開発作業を行う場所として新たにブランチを作成し、完成したらmaster
にマージするというのがより優れた方法です。
マージ(merge)
現在このリポジトリには2つのブランチが存在しています。master
とstyling
です。流儀にもよりますが、基本的にGitではmaster
ブランチに全ての作業が集約していきます。スタイル設定作業が一旦落ち着いたのでstyling
で行なった仕事をmaster
ブランチに適応しましょう。この別のブランチの変更を別のブランチに適応する作業を マージ(merge) と呼びます。分かれていた枝をくっつけるイメージです。超個人的なイメージでは、master
ブランチからstyling
ブランチの先っぽを掴んで、master
ブランチにくっつけてぎゅっとコブを作る感じです。
styling
をmaster
にマージします。コマンドはgit merge --no-ff styling
になります(--no-ff
はマージした時にコブを作るおまじないです。マージには3つくらい種類がありますが、この方法が複数人の開発では重宝されています)。この時どちらがどちらにマージされるかというのは重要で、自分がmaster
ブランチにいることを確認した上でマージを行なってください。
~/Desktop/git_tutorial$ git status On branch master nothing to commit, working tree clean ~/Desktop/git_tutorial$ git merge --no-ff styling # 実行後適当なエディタが開かれます。使い方が不明なら、vimなら`ZZ`、nanoなら`Ctrl + x`を入力してください Merge made by the 'recursive' strategy. index.html | 1 + style.css | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 style.css
マージが実行されました。git log --graph
で履歴を見ると、4つのコミットが表示されています。このことはstyling
ブランチにあった「スタイルシートを追加」のコミットがmaster
ブランチに適応されたこと、マージしたという事実を示す新しいマージコミット(merge commit)が作成されたこと、を示しています。
~/Desktop/git_tutorial$ git log --graph * commit c45179e33ebf642db092e04130bbd981078cb6f9 (HEAD -> master) |\ Merge: 081f264 59df46b | | Author: ushumpei <mail@ushumpei.com> | | Date: Tue Nov 28 11:46:57 2017 +0800 | | | | Merge branch 'styling' | | | * commit 59df46ba1df6e9a29584dd2ad2d95b79248f0409 (styling) |/ Author: ushumpei <mail@ushumpei.com> | Date: Tue Nov 28 11:10:48 2017 +0800 | | スタイルシートを追加 | * commit 081f264cc85e5074a93f7304ba2febf9efb90bd9 | Author: ushumpei <mail@ushumpei.com> | Date: Tue Nov 28 10:17:57 2017 +0800 | | ページタイトルなのでh1にタグを変更 | * commit b80d4812cbde6655bee82bfa20127519e8826b81 Author: ushumpei <mail@ushumpei.com> Date: Tue Nov 28 10:02:38 2017 +0800 Initial commit
まとめ
長い文章を読んでくださってありがとうございました。またはまとめを見てくださってありがとうございます。とりあえず基本的な概念の説明を自分なりにまとめて見ただけです。わかりにくい部分、間違っている部分、お気づきになりましたらお知らせ下さい。(コメント、メール、twitter#など最大限対応します)
おまけ
- リポジトリ(repository)は、枝分かれしたブランチ達を持っている(木みたいなもの)
- ブランチ(branch)は、連続したコミット達から成り立っている(枝みたいなもの)
- コミット(commit)は、複数ファイル達に対する変更履歴で出来ている(コブみたいなもの)
といった形です。Gitはこれら3つの対象に対して、様々な操作を行える機能を提供してくれるツールです。Gitは 分散型バージョン管理システム でその目的は 「大勢で1つのアプリケーションを一緒に作ること」 です。今回は バージョン管理システム の側面をクローズアップしてましたので、次回は 分散型 と言われる所以となる機能について書きたいと思います。