【git苦手な人の為の】gitの環境構築

本当にgitが苦手なので、いつもよくわからなくなる環境構築についてまとめておくことにしました。

##環境
OS：AmazonLinux2
プライベートなリモートリポジトリを利用するGitHubアカウント向け

##認証の設定がないとできないこと
リモートリポジトリに対しての下記のgitコマンドは、https又はsshそれぞれの方法で認証の設定を事前に行わないとユーザー名とパスワードの入力を求められる。
その時に入力しても良いけど、毎回面倒なので設定しておくべき。

```bash
git [clone|fetch|pull|push] xxx...
```

##httpsで通信する場合の認証

**①アクセストークンの作成**
下記から作成できる。

https://github.com/settings/tokens

**②サーバーへ情報登録**
色々やり方はあるけど環境変数に登録しておく方法がいちばん楽そうかも。

```bash
export GIT_USER=<username>
expoft GIT_EMAIL=<mail>
export GIT_TOKEN=<token>
export GIT_REPOSITORY=<organization or workspace>/<repository>
export GIT_BRANCH=<branch name>

git config --local user.name ${GIT_USER}
git config --local user.email ${GIT_EMAIL}
```
**③リポジトリのクローン**
`-b`は特定のブランチを指定してcloneするオプション、消せばmasterがクローンされる

```bash
git clone -b ${GIT_BRANCH} https://${GIT_USER}:${GIT_TOKEN}@github.com/${GIT_REPOSITORY} <localbranch name>
```

3ステップ！
でも毎回ユーザー名とトークン入れるの面倒。
認証情報をキャッシュすれば入力の手間を省けるらしい。

https://docs.github.com/ja/github/getting-started-with-github/caching-your-github-credentials-in-git


##sshで通信する場合の認証

**①キーペアの作成**
既存のものが無ければ作成する。`-t`は暗号化形式を指定するオプション。

```bash
ssh-keygen -t rsa
```
対話式で3回入力を求められるが、全部そのままエンターでも大丈夫。
1.ファイル名 2.パスフレーズ 3.パスフレーズ再入力

`-f`オプションで事前にファイル名を指定できる。
`-C`オプションで`""`と指定するとユーザー名と端末名の入力が省略される。書き換えても可。鍵には関係ないコメントとして扱われる。

尚、もしファイル名を指定した場合、sshではデフォルトの名前の秘密鍵を参照する為通信に失敗する。
~/.ssh/configに鍵の名前の登録が必要。

```ssh
Host github
  HostName github.com
  IdentityFile ~/.ssh/<秘密鍵の名前>
  User git
```

尚、公式には下記のように記載があるけど、既述のもので認証に問題なかった。

```bash
ssh-keygen -t ed25519 -C "your_email@example.com"
```
https://docs.github.com/ja/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent

**②GitHubへ公開鍵登録**
作成されたキーペアのうち`.pub`を下記画面から登録する。

https://github.com/settings/keys

**③接続確認**
通信できるか試してみる、下記だとできている。

```bash
[testuser@testsrv ~]$ ssh -T git@github.com
Hi <account name>! You've successfully authenticated, but GitHub does not provide shell access.
```

**④リポジトリのクローン**
GitHubのリポジトリのページで「Code」からSSHを選択して表示されるパスをcloneする。

```bash
git clone git@github.com:<organization or workspace>/<repogitory name>.git
```
一応これでできたけど、公式ドキュメントではssh-agentを使うようになっているので、必要なら使用を検討すると良さそう。

https://docs.github.com/ja/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent

ssh-agentについては下記ページがとてもわかりやすい。ForwardAgentについても載っててとても参考になった。

https://laboradian.com/how-to-use-ssh-agent/

##git configについて
httpsのところで実行した`git config`によるユーザー等の定義は、他にも色々な設定ができる。

特に意識しなくても、ローカルリポジトリとリモートリポジトリを紐付けたりして作業しているなら、リポジトリ内の`.git/config`に勝手に色々な設定が追記されていくようだが、リポジトリ外のディレクトリでリモートリポジトリに対しての操作を行おうとするとエラーになる為、gitを使用するユーザーに対して設定をしておくのが良さそう。

特に何も設定せず作業していたら、ファイルはこんな感じになっていた。

```bash
[testuser@srv <localrepogitory name>]$ cat .git/config
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
[remote "origin"]
	url = git@github.com:<workspace>/<remoterepogitory name>.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master
[branch "develop"]
	remote = origin
	merge = refs/heads/develop
[branch "feature/fix_xxx"]
	remote = origin
	merge = refs/heads/feature/xxx
[branch "feature/zzz"]
	remote = origin
	merge = refs/heads/feature/zzz
[user]
	email = <mail>
	name = <username>
[branch "feature/ccc"]
	remote = origin
	merge = refs/heads/feature/ccc
[branch "feature/vvv"]
	remote = origin
	merge = refs/heads/feature/vvv
[testuser@srv <localrepogitory name>]$ git config --list
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.url=git@github.com:<workspace>/<remoterepogitory name>.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
branch.develop.remote=origin
branch.develop.merge=refs/heads/develop
branch.feature/xxx.remote=origin
branch.feature/xxx.merge=refs/heads/feature/xxx
branch.feature/zzz.remote=origin
branch.feature/zzz.merge=refs/heads/feature/zzz
user.email=<mail>
user.name=<username>
branch.feature/ccc.remote=origin
branch.feature/ccc.merge=refs/heads/feature/ccc
branch.feature/vvv-conf.remote=origin
branch.feature/vvv.merge=refs/heads/feature/vvv
```
httpsのところで行った`git config`には`--local`オプションがついていたが、これがリポジトリ単位での設定となる。
リポジトリ単位ではなくユーザー単位で設定を行うには`--global`オプションを付ける。

```bash
git config --global user.name "<user name>"
git config --global user.mail <email>
```

ユーザー単位の設定は下記ファイルに反映される。

```bash
[ec2-user@testsrv <カレントディレクトリ>]$cat ~/.gitconfig
[user]
	name = <name>
	mail = <mail>
```
この他、システム全体に設定を行う`--system`オプションなどがあり、それぞれのオプションの使い道は下記が参考になった。

https://qiita.com/C_HERO/items/c35e679f0b03a5f06469


##プロンプトをカスタム
通常プロンプトは下記のような表示で、gitが使いづらい。

```bash
[ec2-user@testsrv <カレントディレクトリ>]$
```
**git-prompt.shを使おう**

gitをインストールしていれば、大体サーバーのどこかにあるはず。
探した結果下記のように。

```bash
[ec2-user@testsrv ~]$ find / -name git-prompt.sh 2> /dev/null
/usr/share/doc/git-2.23.4/contrib/completion/git-prompt.sh
/usr/share/git-core/contrib/completion/git-prompt.sh
```

たぶん同じものなんだろうけど、上の方のスクリプトを使うことにして、これを~/.bash_profileに登録。
スクリプトの処理でいい具合に取得した情報を環境変数$PS1に登録するとプロンプトに反映できるという仕組み。

**＄PS1のデフォルト**

```bash
[ec2-user@testsrv ~]$ echo $PS1
[\u@\h \W]\$
```
\uはユーザー名、\hはホスト名、\Wはカレントディレクトリという。
\$はroot以外は$表示にしますよ、という事らしい。
gitを使用するにあたって実現したいことは下記。


**カレントブランチ名表示**
`__git_ps1`という関数でブランチ名を取得している。`%s`が`[]`で囲まれているのはブランチ名を`[]`で囲いたいから。
そのため`$(__git_ps1 [%s])`


```bash
export PS1='\u@\h:\W$(__git_ps1 [%s])\$'
```

**ブランチ名に色をつけたい**
`\[\033[31m\]\W`とすることでカレントディレクトリは赤、同様に\[\033[33m\]以降のものは黄色にする、という書き方。
これだけで良いと思いきや、`\[\033[00m\]`という無効化指定も明示的に入れないと、全体が黄色になってしまったので追記。
`\033`はエスケープシーケンス、無いとプロンプトに33mとか表示されてしまう。

```bash
export PS1='\u@\h:\[\033[31m\]\W\[\033[33m\]$(__git_ps1 [%s])\[\033[00m\]$'
```

**ステータスを表示**
何を表示させたいかは好みによるけど、今回は下記を~/.bash_profileに登録

```bash
#add/commitされていない変更が存在する場合*を表示
GIT_PS1_SHOWDIRTYSTATE=true
#git管理されていない新規ファイルが存在する場合%表示
GIT_PS1_SHOWUNTRACKEDFILES=true
```

##sshとhttps、結局どちらで通信するのが良いか

ここにこんな記載がありました。

https://docs.github.com/en/github/getting-started-with-github/set-up-git
>Connecting over HTTPS (recommended)

なぜ推奨なのかは不明。
ここにも色々記載あり。

https://docs.github.com/en/github/getting-started-with-github/about-remote-repositories
>The https:// clone URLs are available on all repositories, regardless of visibility. https:// clone URLs work even if you are behind a firewall or proxy.

proxyやfirewallがある場合でも難なく使えるという事ですが、推奨の理由それだけ？

>SAML SSOを使用しているOrganizationにアクセスしているなら、認証を受ける前にOrganizationにアクセスするための個人アクセストークンの認可もしなければなりません。

Organizationを利用している場合は管理者がトークンを作成し、それを使用しなければ通信できないからよりセキュア、という事？
sshでも公開鍵追加するの管理者だから同じ事のような。

通信の体感速度も一緒（GitHubActionsとか使うとまた違う？）
sshに不便を感じているわけでもないので、いつか理由が分かる日まで状況によって使い分けしようと思う。