Gitをちゃんと使う　Github CLIを使う

# Github操作をコマンドラインで使う
１人pullリクエスト開発をいざやってみると、１人でやってても早速問題が。
レポジトリの持ち主のアカウント(prod)と、開発用のアカウント(stg)を使い分けて、prodからstgにフォークしたレポジトリで開発をするのですが、prodとstgで差分が、、
git flowを学びそれに会うブランチ構成をprod側で追加したので、その分がstgとずれたわけです。

長期的に開発をする際に元レポジトリとフォーク先レポジトリの差分管理はどうするのかなぁと気にはなってたのですが、解決を後回しにするのもなぁということで、TOBEの方法を学びました。
その中でGithub CLIの利用が必須になったので、そこらの方法からまとめます。

## Github CLIの導入
Githubの提供するCLI環境。
意外と最近リリースされた、、のかな、、？ベータ版は2020.2?新しめではありますが、十分以上に信頼できそうな感じ。
https://github.blog/jp/2020-09-18-github-cli-1-0-is-now-available/

導入はubuntuだとレポジトリを追加する方法が紹介されています。
https://cli.github.com/
https://github.com/cli/cli/blob/trunk/docs/install_linux.md

レポジトリ追加式は、レポ管理が放棄された際に/etc/aptの設定忘れずに消さないと行けないからちとめんどくさくもありますが、、まぁ仕方なし。
ubuntu20.04だと、標準レポにgitsomeというパッケージでghの導入ができるのだけれど、これはGithub CLIとは別物、、かな。
https://packages.ubuntu.com/bionic/misc/gitsome
https://github.com/donnemartin/gitsome
そもそも非常に古く、インストール時に古い文法のアラートが出るくらい。
。。素直にレポジトリ追加して使いますか。。

## Github CLI(gh)を使ってみる
考え方としては、一回以下のコマンドでgithubにログインした状態を作って、その上で各コマンドを実行するのですね。

### まずは自分のアカウントにログインする
```
$ gh auth login
```

ログイン方法は、その場でブラウザを立ち上げてアカとパスを入れる方法か、事前にAPIキーをgithubで取得しておいて、それを使う方法があるようです。
私の環境だと開発ごとに個別でdockerコンテナを作るので、そいつからブラウザを立ち上げさせるというのもかなりや奴しく鳴るので、素直にAPIキーを使います。
こんな感じになります。

APIキーの発行
https://docs.github.com/ja/github/authenticating-to-github/creating-a-personal-access-token
ただし、キーの発行の際にはghで使う権限を選ばないといけないので、一回gh auth login空打ちして、そのメッセージに従ってapiキーを作る、という手順にしたほうがわかりやすい気がします。

APIキーを使うghログイン

```
$ gh auth login --with-token < <keyを書いたファイル>
$ gh auth status # どこにログインしてるかの確認
```

今回は、これでstgのアカウントにログインした前提で書いていきます。

ちなみにブラウザで認証させるときはどうしてるのだろう。
クッキー引っこ抜くのかな、、まぁ後日余裕があったら勉強がてら調べますが。

### Forkしてみる
大前提、自分がどのアカウントで作業しているのかを明確にイメージするのが必須ですね。
これを勘違いするとおかしなことになる。

stgにログインした状態で、prodのrepositoryをフォークする場合。

```
$ gh repo fork prod/<repository>
```

これで、stg上に、prodのレポジトリがフォークされる、と。
すでにフォーク済みの場合は、何もしない。このコマンドで同期かけたりはしてくれたりはしないのですね（そりゃそうか）。
また、実施時に「ローカルにクローンもする？」と聞かれるので、なんも考えんとyを押してると、カレントディレクトリにフォークしたプロジェクトが配置されます。

この際、普通にgit cloneしたときと非常に大きな違いが。

```
# git cloneした場合
$ cat .git/config
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = https://github.com/<stg アカウント>/<repository>
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
        remote = origin
        merge = refs/heads/main

# ghのforkのおまけでcloneした場合
# remoteに、upstreamというものが増えている
$ cat .git/config
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = https://github.com/<stg アカウント>/<repository>
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
        remote = origin
        merge = refs/heads/main
[remote "upstream"]
        url = https://github.com/<prod アカウント>/<repository>
        fetch = +refs/heads/*:refs/remotes/upstream/*
```

フォーク元のprodを'upstream'という名称で、remoteとして登録してくれます。
これが、非常にありがたい。

## Forkしたリポジトリの更新（同期）
まさに紹介されてまして。
https://docs.github.com/ja/github/collaborating-with-issues-and-pull-requests/syncing-a-fork

これをpushすれば、github上のフォークレポジトリも、prodの原本に追従できます。
ただ、、ブランチごとに追従させないといけないので、それが厄介。

また、main以外のブランチに対して同期をかける時は、.git/configで該当ブランチremoteが想定外の方向を向いている（stgを向いてると思ったらprod向いてたり）とかがあるので、そこは注意を要する。

## Pull Request

```
$ gh pr create -B develop -b "Comment"
```

-Bオプションが重要で、これ付け忘れるとmainに対してpull requestしてしまう。
うっかりこれ受領しちゃった、、、（１敗）。

受ける側は、prodでログインし、

```
$ gh pr list
$ gh pr merge <対象のpull request番号>
```

とするのだけど、これでpull requestで指定されたブランチに対してマージかけてしまう。。。
要注意。

ちなみに、やっちゃった更新の上書きは、、

```
$ git reset --hard <過去のコミット>
$ git push -f

```

危なっかしいなぁ、、、

## 他の機能は、、
やりながら勉強するとします。
しかし、やはりcliを用意してくれるのは非常にありがたい。
RPAでボタン押させたり、Seleniumでボタン探したりみたいな泥にまみれた作業はほんとに嫌なので。。