【github初心者】研究室の共同開発環境構築メモ

#はじめに
この記事はgithubやgitコマンドを本当に全く知らない人向けに書いています。
特に研究室でメンバー同士のコードを管理したいけどgithub触ったことない人向けです。
そして自分もそんなに詳しくないですが書いています。
ご了承ください。

#githubとは
###ざっくり概要
超簡単に言えば、プログラミングのコードを管理することに特化したGoogle Driveです。
使い方は以下のとおり。

- 自分のコードのバックアップをとる
- 他人、もしくは自分の異なるコンピュータ同士でコードを共有する
- 世界中のプログラマが書いたコードをダウンロードして利用できる。

1つ目、2つ目の用途は企業も利用しているようなものなので学生の皆さんは勉強しておいて損はないと思います。
自分もそのためにしっかり管理しようと思いました。
3つ目は研究機関などが公開しているコードを利用し、それに機能を追加していくときに使います。

###具体的には
本当に初めての人にとってはイメージがつかないと思うのでもう少し詳細に書きます。
みなさんが実際にやる作業としては、

1. コードをダウンロードする。
2. コードを改変する。
3. コードを**リモート**(Google Driveみたいなもの)に送る準備をする
4. コードを送信する

こんな感じです。
これらの作業全てをターミナルコマンド上で行っていきます。

#開発環境の構築
##前提
###想定する事例
今回は研究室メンバーの開発環境をubuntuとします。
また、みんなでそれぞれ機能を実装し、最終的に一つのフォルダの中にすべてをまとめ実装すべき機能を完成させようと思います。

図にするとこんな感じで木構造のようになっています。

- 実際にロボットが動くコード(機能ABC)
    - 研究のために皆の知識を借りて色々いじくったコード(機能ABC)
        - Aさんがいじったコード(機能A)
        - Bさんがいじったコード(機能B)
        - Cさんがいじったコード(機能C)
        - …

`実際にロボットが動くコード`と`研究のために皆の知識を借りて色々いじくったコード`は全く一緒の内容です。
`研究のために皆の知識を借りて色々いじくったコード`を動かして動作確認をしたら`実際にロボットが動くコード`へとコピーします。
バックアップみたいなものです。

###覚えるべき用語
上記の図はgithub上では下記の図のように言います。
これらの用語を覚えておいてください。

- `master`**ブランチ**
    - `develop`**ブランチ**
        - `機能A`**ブランチ**
        - `機能B`**ブランチ**
        - `機能C`**ブランチ**
        - ...

実際に管理者以外の人がコードを書いていくのは`機能A`、`機能B`、`機能C`、…、ブランチに対してです。
例えば機能Aを完成させたら管理者の人が`develop`ブランチにその変更を反映させてくれるでしょう。

##gitのセットアップ
この項に書くことはやらなくても大丈夫です。
ただ、パソコンが得意な人は絶対やってください。

###公開鍵の登録
自分のパソコンからリモート(Google Drive的なもの)に送信する際に毎回idとパスワードを聞かれるのがデフォルトなのですが、これを省略するためのセットアップです。
省略するために必要なものが**公開鍵**と呼ばれるインターネット上の鍵です。

まずはそもそも自分が公開鍵を持っているか確認をします。

```terminal
$ ls ~/.ssh
```
これで`id_rsa`、`id_rsa.pub`などが表示されたら鍵を持っています。
ない場合は以下で作成することができます。

```terminal
$ ssh-keygen -t rsa
```
なにか入力する画面が出力されますが、すべてデフォルトのもので大丈夫なので何も入力せずエンターキーを押していけば大丈夫です。
作成したら`ls ~/.ssh`で確認してみてください。

次に公開鍵の登録を行います。
[githubの公開鍵設定のとこ](https://github.com/settings/keys)にアクセスして、"New SSH key"を押しましょう。
Titleは"id_rsa.pub"、Keyには以下のコマンドで表示される文字列をすべてコピペします。

```terminal
$ cat ~/.ssh/id_rsa.pub
ssh-rsa ADDDB3LzaC3....(これをコピペ)
```

その後、以下のコマンドでgithubとの接続確認をしてください。

```terminal
$ ssh -T git@github.com
Hi kokok! You've successfully authenticated, ...
```

最後にこちらのパソコンの通信に関する設定ファイルをいじれば完了です。エディタはなんでもいいですが、ここではgeditとします。

```terminal
$ gedit ~/.gitconfig
```

以下をコピペする。

```~/.gitconfig
[url "github:"]
    InsteadOf = https://github.com/
    InsteadOf = git@github.com:
```

これでうまくいくと思います。

ただ、これでも以下のようなエラーでうまくいかなかったときもありました。

```
ssh: Could not resolve hostname github: Name or service not known
```

なんでやねんって感じで悪戦苦闘したのですが、最終的に`~/.ssh/config`というファイルを作成し、以下をコピペしたらうまくいきました。

```~/.ssh/config
Host github github.com
  HostName github.com
  IdentityFile ~/.ssh/id_rsa
  User git
```

あとこのとき`~/.gitconfig`の内容は以下のようにしました。

```~/.gitconfig
[url "github:"]
    InsteadOf = https://github.com/
    InsteadOf = github:git@github.com:
```

参考：
**GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~**
https://qiita.com/shizuma/items/2b2f873a0034839e47ce

###ターミナル表示画面の設定
先ほどの「ブランチ」という概念がgithubを使う上でとても重要なのですが、これをターミナルの画面上に常に表示させるためのセットアップです。
自分が今どのブランチにいるのか分からないと、間違えて一番大事な`master`ブランチを編集してしまう可能性があります。

まず必要なファイル`git-completion.bash`があるか確認を行います。
`git-completion.bash`は`bash_completion.d`というディレクトリにあるため、`find`コマンドでそのディレクトリを探します。

```terminal
$ sudo find / -name bash_completion.d
```

自分の環境では`/usr/local/etc/bash_completion.d`にありました。
検索結果が一つも現れなかった場合は「gitのインストール」でGoogle検索してください。

次に`git-completion.bash`があるか確認します。

```terminal
$ cd /usr/local/etc/bash_completion.d
$ ls
```

lsコマンドを行なって`git-completion.bash`がなければ以下のコマンドでダウンロードします。

```terminal
$ cd /usr/local/etc/bash_completion.d
$ sudo wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash -o git-completion.bash
```

あとは@varmilさんの記事を参考にしてください。

**「Git補完をしらない」「git statusを1日100回は使う」そんなあなたに朗報【git-completionとgit-prompt】**
https://qiita.com/varmil/items/9b0aeafa85975474e9b6

やることだけ以下にまとめます。

```terminal
$ wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash -O ~/.git-completion.bash
$ chmod a+x ~/.git-completion.bash
$ wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh -O ~/.git-prompt.sh
$ chmod a+x ~/.git-prompt.sh
```

`gedit ~/.bashrc`とかで`.bashrc`を開き以下を追記。

```bash:.bashrc
# スクリプト読み込み
source $HOME/.git-completion.bash
source $HOME/.git-prompt.sh

# プロンプトに各種情報を表示
GIT_PS1_SHOWDIRTYSTATE=1
GIT_PS1_SHOWUPSTREAM=1
GIT_PS1_SHOWUNTRACKEDFILES=
GIT_PS1_SHOWSTASHSTATE=1

# ターミナルのコマンド受付状態の表示変更
export PS1='\[\033[1;32m\]\u\[\033[00m\]:\[\033[1;34m\]\w\[\033[1;31m\]$(__git_ps1)\[\033[00m\] \$ '
```

最後に`source ~/.bashrc`で変更を更新。

##管理者が最初にやること
ここでは管理者の人がはじめにやることをまとめます。
管理者ではない人は読み飛ばしてください。

今回は[Institute for Artificial Intelligence - University of Bremen](https://github.com/code-iai)で開発されているコードを元に開発を行なっていきます。
下記の`fork`と書かれているところをクリックしてください。
<img width="414" alt="スクリーンショット 2019-07-12 13.43.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208979/1cfb6bb5-d469-f5a4-225a-6512214fd25f.png">

すると自分のアカウントのページに飛び、元にしたいコード全てがコピーされていると思います。

---以下、後で更新してきます---

##管理者以外の人がやること
###共用フォルダのダウンロード
まずgithubのアカウントを作成しましょう。
アカウント作成については省略させていただきます。Google検索してください。

次に共用したいフォルダを自分のパソコン(**ローカル**と言います)にダウンロードしましょう。
ROSの場合のコマンドを以下に書きます。

```terminal
$ cd ~/catkin_ws/src
$ git clone https://github.com/なんちゃらかんちゃら
```

`https://github.com/なんちゃらかんちゃら`は共用したいフォルダが公開されているgithubのURLです。
管理者に聞いてください。
`git clone`はGoogle Driveからのダウンロードみたいなものです。
今回は`your_repository`という名前の共用フォルダをダウンロードしたとしましょう。

無事、ダウンロードできたら以下のコマンドを入力して確認してください。
途中でパスワードとかidとか聞かれることもありますが、`Everything up-to-date`と出力されればOKです。

```terminal
$ cd ~/catkin_ws/src/your_repository
$ git push
Everything up-to-date
```

###自分のコードを書く準備
ダウンロードした共用フォルダのコードを編集する前に、自分のブランチを作成し大元のデータを編集しないようにしましょう。
以下、`git`コマンドは必ず**ダウンロードした共用フォルダ内で実行**してください!

```terminal
$ git checkout -b 好きなブランチ名
```

ブランチ名はなんでもいいですが、作成する機能がわかるものにしましょう。
画像認識なら`pic-recog`とか、まあなんでもいいです。

ブランチを作成したら`git branch`で自分の今いるブランチを確認しましょう。
`*`で先ほど作成したブランチが指定されていればOKです。

次に`git push`コマンドで送信テストを行いましょう。
なんかエラーっぽいことを言われます。

```terminal
$ git push
fatal: The current branch develop has no upstream branch.
To push the current branch and set the remote as upstream, use

   git push --set-upstream origin 好きなブランチ名
```

最初の`git push`では必ずこれを言われるので、言われるがままターミナルコマンドに入力してください。

```terminal
$ git push --set-upstream origin 好きなブランチ名
```

これで自分のブランチをリモート(何度もいいますがGoogle Drive的なもの)に登録できました。

###自分のコードを書いたら
自分のコードを書き終えたらリモートに書いたコードを送信しましょう。
Google Driveにアップロードする感覚と一緒です。
バックアップを取りたい人は毎日帰るときに送信するようにしましょう。

最初に書いたんですがgithubの流れとしては、

> 1. コードをダウンロードする。
2. コードを改変する。
3. コードをリモート(Google Driveみたいなもの)に送る準備をする
4. コードを送信する

が基本です。

上記の3番の工程は`git commit`コマンドで行えます。
`git`コマンドは必ずダウンロードした共用フォルダ内で実行することを忘れないでください

```terminal
$ git commit -am "編集した内容に関するメッセージ"
```

新しくファイルを追加した場合は`git add`コマンドを`git commit`前に行なってください。

```terminal
$ git add -A
```

簡単に言えばあれです。
`commit`はメールの新規作成、`add`は添付ファイルの追加、みたいなもんです。
`commit`によって`"編集した内容に関するメッセージ"`と共に編集したコードが書かれたメールみたいなものが作成されます。

次に「メールの送信」しないとメールが向こうへ届きません。
この送信コマンドが`git push`です。
`push`を行う前に`git status`で送信する内容の確認を行うと良いかもしれません。

```terminal
$ git status
$ git push
```

これで編集したコードをリモートに反映させることができます。
Google Driveで言うところのデータのアップロード完了です。

###機能を完成させたら
機能を完成させ、次の機能をつくりたいと思った時はブランチをまた作り直しましょう。
ここで最初に必ず`develop`ブランチに戻ってから新しいブランチを作成するようにしましょう。

```terminal
$ git checkout develop
$ git checkout -b 新しいブランチ名
```