はじめに
今回の記事は、GitとGitHubについてまとめていきます。
GitHubについてほとんど知らない人を対象に作成しているので、知っている人からすればかなりくどい説明になると思います。
お付き合い頂ければ幸いです。
Gitの歴史と環境構築
最初に、Gitの歴史と環境構築についてまとめていきます。
そもそもGitHubとは
GitHubの説明の前に、Gitの説明からはいります。Gitとは、簡単に説明するとファイルのバージョン管理システムのことです。
ファイルの変更履歴を各々のパソコン(ローカル環境)に保存することで、その変更履歴をたどることでファイルの状態を戻すことができます。
GitHubとは、そのGitをオンライン上に設置することで、集団でのファイルの編集を可能にするサービスのことです。
GitHubはGitHub社という会社により運営されていましたが、近年マイクロソフト社によって買収されました。
Gitの歴史
Gitを開発したのは、かの有名な世界最大規模のオープンソースソフトウェアであるLinuxの創造主であるリーナス・トーバルズです。
Linuxの開発は複数人のエンジニアにより行われるのですが、Linuxに対するどの変更を許可し、またどの変更を許可しないかなどを管理するバージョン管理システムが使用されていました。
元々Linuxの開発にはBitKeeperというバージョン管理システムが使われていたのですが、ライセンスなどの問題で開発元のBitMover社とLinux開発コミュニティとの間の協力関係が崩壊してしまい、急遽別のバージョン管理システムが必要になりました。
それにより生まれたのがGitです。つまり、GitはLinuxプロジェクトのために開発されたものなのです。
Linuxは1500万行にも及ぶコードから構成されるとても大規模なプロジェクトです。そのため、Linuxのためのバージョン管理システムであるGitには動作速度に非常に優れていて、また大人数で取り扱うことができるようにプロジェクトの枝分かれさせた「ブランチ」の並列開発が可能になっています。
Gitの特徴
従来のバージョン管理システムはファイルの変更差分を記録していましたが、Gitは各々のファイルのバージョンをスナップショットとして保存していることが挙げられます。違いを図で見比べてみましょう。差分を記録する場合は以下のようになります。
上図のように、変更差分を「レポジトリ」という場所に記録することで、バージョン管理を行うのが従来のバージョン管理システムでした。
しかし、この管理の仕方の場合、大規模なプロジェクトにおいて枝分かれして開発を行い、それを統合するときに全ての差分を計算しなければならないため、非常に時間がかかっていたのです。(枝分かれして開発するときの枝のことをブランチといい、そのブランチを統合することをmマージと呼びます)。
そこで、Gitは以下のようにバージョン管理システムを変更したのです。
このように、各々のファイルの状態をスナップショットとして記録することで、枝分かれした開発のブランチをマージする際に非常に高速になります。
このGitのファイル管理の仕方は非常に重要なので、しっかりと頭に入れておいてください。
とりあえずGitHubとGitを使えるようにする
とりあえず、GithubとGitの環境構築をしていきましょう。
###Gitのダウンロード
自分の環境がWindowsであるため、Windowsにおける説明が主になります。「git for windows」を公式サイトからダウンロードしましょう。Macの人はこちらの記事を参考にインストールしてみてください。
ダウンロード後は、ダウンロードのショートカットにあるexeファイルからインストーラーを実行しましょう。流れにそってNextを押しまくれば、インストールは終了です。
インストールが終わった後、画面左下のWindowsのマークを押して、Gitのプログラムを探してみてください。Git BashやGit GUIなどのソフトがダウンロードできていれば成功です。
GitHubへの登録
Gitのダウンロードが終了した後は、こちらからGitHubのアカウントの取得に取りかかりましょう。右上のSign upと書かれているところから、ユーザーネームとメールアドレスとパスワードを登録して、アカウントを作成してください。無料プランでも有料プランでも、どちらでも構いません。そんなに重要な選択肢はないので、流れに合わせていけばアカウントの作成は完了です。
GitHubへの公開鍵認証(SSH接続)について
ローカルの環境のGitとサーバー上のGitHubの接続には、公開鍵認証によるSSH接続が多く使われています。今回はその設定を解説します。個人的には、この部分がはまりポイントの一つだと考えています。まずは公開鍵認証の説明をはじめます。
公開鍵認証とは、リモートのコンピューターとローカルのコンピューターを安全に接続する方法です。秘密鍵と公開鍵を用いて、接続を行います。イメージとしては、公開鍵が南京錠のようなもので、秘密鍵がその南京錠のカギのようなものです。
今回の例では、公開鍵をGitHubのアカウントに渡します。そうすると、GitHub側では公開鍵(南京錠)を用いて接続をロックし、その南京錠の鍵である秘密鍵を持つ人だけの接続を許可するようになります。以下に図解します。
分かりにくい図になってしまった感じがありますが、解説します。左のGitHubのサーバー上に公開鍵がある場合、その公開鍵を開ける秘密鍵をもっているのは上の笑顔の人だけであるため、笑顔の人はログインできますが、下の明らかに悪人顔の人はログインできません。このようにして、セキュリティを高めているのです。
GitHubへの公開鍵認証のやり方
こちらのサイトを参考にしたら恐らくできると思いますが、失敗しないように、注意ポイントを解説します。
まず以下コマンドでフォルダを移動してください。
cd ~/.ssh
~/.ssh はホーム直下のsshファイルの保存場所を表しています。
できるだけ、この場所で鍵の生成をして下さい。なぜなら、別の場所で秘密鍵を生成すると、「こんな安全じゃない場所の秘密鍵なんて使いたくない」というエラーが発生する場合があるからです。
Macならchmodコマンドで鍵の安全度を変更することができますが、Windowsでは鍵の場所を移動させるしかないため(他に方法があるのかもしれませんが)、少し面倒くさいです。
そして、GitHubがデフォルトで見に行く鍵の場所が「~/.ssh/id_rsa」、「~/.ssh/id_dsa」、「~/.ssh/identity」の三つであるため、別の場所で鍵を作成したり、また作成した鍵の名前を変更したりすると、GitHubに鍵の場所を教えるために「~/.ssh/config」にファイルを作成し、鍵の場所についての情報を記載する必要があります。
次は以下のコマンドを実行しましょう。
ssh-keygen -t rsa
このコマンドを実行すると最初に鍵を生成する場所を聞かれます。デフォルトでは.ssh/ 直下に「id_rsa」と「id_rsa.pub」という名前で秘密鍵と公開鍵が作成されます。「id_rsa.pub」が公開鍵で「id_rsa」が秘密鍵です。このデフォルトの名前で保存すると、「~/.ssh/config」に鍵の場所を記載せずともデフォルトで見にいってくれるので、特にこだわりがない限りはそのままでいきましょう。一回エンターを押します。
次にパスフレーズを聞かれますが、これは秘密鍵を使用する際に使われるパスワードのようなものです。設定しなくても問題はありませんが、セキュリティが心配なら適当なパスフレーズを入力しましょう。
次は、公開鍵をこちらからGitHubにUPしましょう。titleに公開鍵の名前を(そんなに重要ではない)、Keyに公開鍵の中身を貼り付けましょう。公開鍵の中身を貼り付けるときに、/.ssh/id_rsaからファイルを開こうとしても恐らく開くことができないので、以下のコマンドでクリップボードにコピーしてください。
$ pbcopy < ~/.ssh/id_rsa.pub (Mac)
$ cat id_rsa.pub | clip (Windows)
公開鍵をUPしたら、次のコマンドで実際に接続が上手くいっているのか確かめてみましょう。
ssh -T git@github.com
以下のメッセージが返されれば成功です。
Hi (account名)! You've successfully authenticated, but GitHub does not provide shell access.
もしも失敗してしまった場合は「~/.ssh/config」を作成し、以下の文章を貼り付けましょう。
Host github github.com
HostName github.com
IdentityFile ~/.ssh/id_rsa
User git
三行目のIdentityFile の後ろは自分の秘密鍵のPATHを入力してください。
vimエディターが入っている場合は
vim ~/.ssh/config
とするとconfigファイルを作成することができます。
Gitの初期設定
これで最後の設定です。自分のローカルのGitに、リモートのGitHubのメールアドレスと場所を教えてあげましょう。Macの方はターミナルを、Windowsの方は全てのプログラムからGit Bashを開きましょう。開いたら、以下のコマンドを入力してください。
git config --global user.name 'user_name' # user_nameにはGitHubに登録したuser nameを入力
git config --global user.email 'user@gmail.com' # user@gmail.comにはGitHubに登録したメールアドレス
上のコマンドを入力すると、homeの直下にある「.gitconfig」ファイルに変更が入力されます。このhome直下の.gitconfigファイルはGit全体の設定に関わるファイルであり、上記のコマンドを入力することでローカルのGitにネットワーク上のGutHubを登録することができます。以下のコマンドで、きちんと登録されたか確認することができます。
git config user.name
git config user.email
上のコマンドで、自分が登録したアカウント名とメールアドレスが表示されれば成功です。
ここまでで、環境構築ができました。
それでは次に、GitHubにpushするまでを見ていきましょう。
とりあえずGitHubにpushする
GitHubにpushするまでの流れをざっと見ていきましょう。自分の場合はIDE(総合開発環境)としてPycharmを用いて、pythonスクリプトをGitHubにpushしていきます。
D:\Users\lesson_gitをプロジェクトファイルとして、lesson.pyというpythonスクリプトを作成します。このpythonファイルをGitHubにpushしていきます。
GitHubにファイルをpushするまでの流れは以下のようになります。
リポジトリとは、情報を保管する場所だと覚えておきましょう。
まず、ファイルに変更があった場合、git addでステージングエリアという控室のような場所にファイルを追加し、その次にgit commitでローカルの情報の保管場所であるローカルリポジトリに情報を保存します。
そのあとでgit pushコマンドでネット上の情報の保管場所であるリモートリポジトリに情報を保存します。
リモートリポジトリが、GitHubに対応します。
git initコマンドで.gitファイルの作成
まずはコマンドプロンプトを開いて、lesson.pyが存在するプロジェクトファイルまで移動しましょう。
cd D:\Users\lesson_git
最初にCドライブにいる場合は、まずDドライブに移動する必要があるので以下のコマンドを打ちましょう。
D:
プロジェクトファイルまで移動した後は、次のコマンドを打ちましょう。
git init
このコマンドを打つと、プロジェクトファイル直下に.gitファイルが作成されます。中身をみていきましょう。
.gitファイルの中身には、このように様々なファイルがあります。Gitはプロジェクトファイルごとに.gitファイルを作成し、その.gitファイルの中に様々な情報が保存されます。ローカルリポジトリに情報を保存する場合や、ステージングエリアに情報を保存する場合も、結局はこの.gitファイルに変更が加えられることになります。
git addコマンドでステージングエリアにファイルを追加
lesson.pyに以下のコードを打ちます。
print('Hello GitHub')
このコマンドをGitHubにpushしましょう。
次に、git addコマンドでファイルをステージングエリアに追加します。
git add lesson.py
git add ファイル名 という感じでコマンドを打ちます。すべてのファイルをステージングエリアに追加する場合は
git add .
としましょう。
git commitでローカルリポジトリにファイルを追加
ステージングエリアにファイルを追加した後は、次のコマンドでローカルリポジトリにファイルを追加しましょう。
git commit
このコマンドを打つと、デフォルトではvimエディターが立ち上がります。ここで打つメッセージは、後でファイルの変更履歴を確認するときに見ることになります。Gitは自分一人ではなく多くの人でファイルを管理するためのツールなので、ここに打つメッセージは慣習に従いましょう。
1行目:変更内容の要約
2行目 :空行
3行目以降:変更した理由
とすることが望ましいです。細かい書き方はこちらの記事に書かれているので、参考にしましょう。自分は以下のようにコメントを打ちました。
add lesson.py
(空行)
practice GitHub
vimエディタの使い方がよく分からない人は、
テキストエディタVimの使い方【超初心者向け】
知識0から始めるVim講座
などの記事を参考にしてください。
:wq でメッセージを保存するとcommitは終了です。
リモートリポジトリにpush
次はリモートリポジトリにpushしましょう。
まずはGitHubにログインして、右上の+ボタンからNew repositoryで新しいリポジトリを作成します。PublicとPrivateを選択できますが、これはどちらでも構いません。自分はPublicを選択しました。リポジトリを作成すると、上から三つ目に次のような画面がでると思います。
自分は今回はhangi4343というアカウントでqiita_practice.gitというリポジトリを作成しました。GitHubのコマンド通りに、コマンドラインに入力しましょう。hangi4343/qiita_practice.gitの部分は自分のアカウント名とリポジトリ名に変更して、以下のコマンドを打ってください。
git remote add origin https://github.com/hangi4343/qiita_practice.git
git push -u origin master
以上のコマンドで、リモートリポジトリにpushすることができたと思います。とりあえず、これで全体の流れは終了です。次は各々のコマンドを細かく見ていきましょう。
git add と git commitについて
git add やgit commitを実行すると、内部的にはGitオブジェクトというものが作成されます。
Gitオブジェクトには、ファイルを圧縮したblobオブジェクトと、ファイル名とファイルの中身を組み合わせたツリーファイル、「いつ、誰が、何を、何のために変更したか」が分かるコミットファイルの三つが含まれます。
このGitオブジェクトの情報は、全て.gitファイルの中に保存されています。
git add practice.pyを実行すると、practice.pyファイルの圧縮ファイルであるblobオブジェクトがローカルリポジトリに作成され、ステージにそのblobオブジェクトのファイル名(blobオブジェクトのファイル名はファイルの中身にヘッダーをつけ加えた文字列をハッシュ関数で暗号化したもの)と元々のファイル名であるpractice.pyを組み合わせたものが作成されます。
このステージの組み合わせにより、圧縮前のファイルと圧縮後のファイルの紐づけが可能となります。ここまでがgit addを実行すると内部的に起こります。
次にgit commitを実行すると、リポジトリにツリーファイルとコミットファイルが作成されます。ツリーファイルはblobオブジェクトのファイル名と元々のファイル名であるpractice.pyを組み合わせたものが保管され、コミットファイルには
- ツリーファイルの名前
- 作成者
- 日付
- コミットメッセージ
が記録されます。git addとgit commitにより、以上のことが内部的に起きています。このことはしっかりと頭に入れておきましょう。
リモートリポジトリにpushする時のコマンドについて
リモートリポジトリにpushする時に以下のコマンドを打ちました。
git remote add origin https://github.com/hangi4343/qiita_practice.git
git push -u origin master
このコマンドについて解説していきます。
git remote add origin https://github.com/hangi4343/qiita_practice.git
このコマンドは、originというショートカットに後ろのURLのリポジトリを登録する、という意味のコマンドです。これから何度もリモートリポジトリにアクセスするときにURLをいちいち打つのは面倒くさいので、originというショートカットに割り当てているだけです。
originの部分は、他の単語でも問題ないのですが、慣習的にoriginという名前を用います。というのも、git clone というコマンドを打ち込むときに、クローン元のリポジトリをデフォルトではoriginという名前に割り当てるため、その部分からきている慣習っぽいです。
次のコマンドをみていきましょう。
git push -u origin master
git push <リモート名> <ブランチ名> とすることで、<リモート名>のリポジトリに<ブランチ名>のローカルのブランチをpushすることになります。ブランチというのは、開発を枝分かれさせたときの枝のひとつのことで、ブランチを増やしていない限り、デフォルトのブランチ名はmasterとなっています。-u オプションを指定することで、次回から git pushとするだけでorigin リポジトリにmasterブランチをpushすることができます。
それでは次にブランチとマージ、プルリクエストについてみていきましょう。
ブランチ・マージ・プルリクエスト
それではこれから、ブランチはマージ、プルリクエストについてまとめていきます。
##GitHubとのやりとりについて
次のコマンドで、設定しているリモートリポジトリの情報を表示することができます。
git remote # リモートのショートカット名を表示
git remote -v # リモートのURLを表示
origin
origin https://github.com/hangi4343/qiita_practice.git (fetch)
origin https://github.com/hangi4343/qiita_practice.git (push)
次のコマンドで、GitにGitHubのリポジトリを登録することができます。
git remote add <リモート名> <リモートのURL>
前回は、originというショートカットにGitHubのリポジトリを登録しました。
ブランチについて
GitHubではブランチという概念があります。ブランチとは、開発を枝分かれさせた際の一つ一つの枝のことです。
実際に以下のコマンドで現在のブランチを確認してみましょう。
git branch
* master
ブランチを増やしていないため、今はmasterブランチというブランチしかありません。ブランチを増やすことを「ブランチを切る」と言ったりします。次のコマンドでブランチを切ってみましょう。
git branch branch_test
このコマンドを打つと、新しくbranch_testブランチを切ることができます。もう一度git branchコマンドで確認してみましょう。
git branch
branch_test
* master
branch_testという新しいブランチができていることが確認できます。*がついているのが今現在作業しているブランチになっています。
ここまでで実際にブランチを作成してみました。では、ブランチという概念についてもう少し細かく見ていきましょう。
Gitはコミットによってファイルの状態が変化します。
つまり、どのコミットの状態を保持しているかで、ファイルの状態が決まるのです。
ブランチとは、どの部分のコミットの状態を保持しているかのポインタであるということができます。今、branch_testブランチを切っただけではmasterブランチとbranch_testブランチは同じコミットを指しているため、ファイルの状態は全く同じになります。
また、HEADというものも存在し、このHEADはいずれかのブランチを指し示すことで現在のブランチを決定しています。今はmasterブランチにいるので、HEADはmasterを指しています。
HEADが指すブランチを変更するには、git checkoutコマンドを使います。
git checkout branch_test
これで現在のブランチを変更することができました。確認してみましょう。
git branch
* branch_test
master
この状態で変更を加えてcommitしてみましょう。lesson.pyを次のように変化させます。
print('Hello GitHub')
print('create new branch')
この変更をcommitしましょう。
git add lesson.py
git commit -m "add create new branch"
git commit の-mオプションで、vimエディタを開かずにコメントを追記することができます。このcommitにより、次のように変化します。
この状態で、git checkoutコマンドによりmasterブランチに移動しましょう。どのようになるか分かりますか?
git checkout master
lesson.pyを確認してみましょう。以下のようになっていると思います。
print('Hello GitHub')
print('create new branch')というコードが存在しないことが分かります。図解すると以下のようになります。
先ほどのコミットはbranch_testブランチにおいて行ったコミットであるため、masterブランチはコミット前の状態になっています。このようにしてブランチを切って開発を進めることで、複数人で開発をすすめることができます。
では、最後にmasterブランチにbranch_testブランチを統合して、コミット④をmasterブランチに反映させましょう。
このようにブランチを統合させることをマージといいます。以下のコマンドを打ちましょう。
git merge branch_test
このコマンドにより、masterブランチとbranch_testブランチがマージされました。図にすると次のようになります。
Gitにおいては、このようにブランチを切ってマージすることが開発の基本になります。また、このようなマージの仕方をとくにFast Forwardといいます。
最後に、必要なくなったbranch_testブランチを削除しましょう。
git branch -d branch_test
GitHubから情報を取得する
リモートリポジトリが他の人からのプルリクエストにより変更した場合を考えてみましょう。自分は以下のようにgit_fetch.pyファイルを作成しました。
このようにリモートとローカルのリポジトリの状況に差異があるときには、ローカルのリポジトリを更新する必要があります。
リモートから情報を取得するときに用いるgit fetch コマンドとgit pullコマンドをみていきましょう。
git fetchコマンドについて
今回はリモートのURLにoriginというショートカットを作成しているので、以下のコマンドでローカルに情報を保存することができます。
git fetch origin
git fetchコマンドを打つと、remotes/origin/masterというブランチにリモートの情報が保存されます。次のコマンドでブランチを確認してみてください。
git branch -a
* master
remotes/origin/master
git branchコマンドを打つと、ローカルのgitのブランチが表示され、-aコマンドを打つと、remotesも含めた全てのブランチが表示されます。
*がついているのが今いるブランチです。
git fetchコマンドによりリモートのリポジトリをローカルのリポジトリに取り込むことができましたが、その情報はremotes/origin/masterというブランチに取り込まれており、現在のブランチであるmasterブランチには取り込まれていません。
mergeする前に、remotes/origin/masterにブランチを切り替えてみましょう。
git checkout remotes/origin/master
ファイルを確認すると、git_fetch.pyファイルがあるのが分かると思います。
確認が終わったら、元のmasterブランチに切り替えましょう。
git checkout master
それでは、remotes/origin/masterのブランチを現在のmasterブランチにマージしましょう。
コマンドは git merge <ブランチ名> でしたね。
git merge remotes/origin/master
これで現在のブランチを確認してみると、git_fetch.pyファイルが存在するのが分かります。
git pullコマンドについて
git pullコマンドは、git fetchとgit mergeを合体させたようなコマンドです。
以下のような書式で用います。
git pull <リモート名> <ブランチ名>
再びリモートリポジトリが他の人によって更新された場合を考えます。今回はgit_pull.pyファイルを追加します。
このリモートリポジトリの変更をローカルリポジトリで取得しましょう。以下のコマンドで取得できます。
git pull origin master
以上のコマンドで、masterブランチにgit_pull.pyファイルが追加されているのが確認できると思います。
プルリクエストについて
それではプルリクエストについて解説します。
プルリクエストとは、自分の変更したコードをリポジトリに取り込んでもらうように依頼する機能になっています。
複数人で開発を行う際に、全員が好きなようにコードの変更をしてしまえば、今まで動いていたコードが動かなくなったり、質の悪い変更をしてしまうことがありますよね。
それを防ぐためにあるのがプルリクエストです。
自分の変更をリモートのリポジトリにマージする際に、他の人にレビューを依頼するようにお願いします。これがプルリクエストです。
実際にプルリクエストの行ってみましょう。
以下のコマンドでブランチを最新の状態にしましょう。
git pull origin master
ブランチを最新の状態にした後は、ブランチを切っていきます。lesson_pull_requestブランチを作成しましょう。
git checkout -b lesson_pull_request
git checkoutに-bオプションをつけると、新しいブランチを作成しながらHEADを変更することができます。
次のようにlesson.pyファイルを変更しましょう。
print('Hello GitHub')
print('create new branch')
print('lesson pull request')
lesson.pyをステージングエリアに追加します。
git add lesson.py
lesson.pyをローカルリポジトリにコミットしましょう。
git commit -m "add lesson pull request"
それではリモートリポジトリにlesson_pull_requestブランチをプッシュします。
git push origin lesson_pull_request
それではこちらからGitHubを開きます。
先ほどプッシュしたリモートリポジトリから、Pull requestのタブを開きましょう。
Compare & pull requestを押した後、プルリクエストの題名と本文を入力し、Create pull requestボタンを押せばプルリクエストの完了です。
プルリクエストが完了したあとは、右側のReviewersからレビュアーを選択し、プルリクエストをレビューしてもらう人を選択しましょう。
以上でプルリクエストは終了です。
終わりに
ここまででGitHubマニュアルは終了です。お付き合い頂きありがとうございました。