gitのコミットメッセージを日本語にした話［bash関数でgitコマンドの入力を楽にしよう］

こんにちは、CAMPFIREエンジニアのishimizuです。

これまで20年近くエンジニアをしてきて今年大きく開発スタイルを変革した事がありましたので経験談を踏まえてまとめていこうかなと思っています。

#### 突然ですが、皆さんgitのコマンドは何をよく使っていますか？

webエンジニアに限らずエンジニア稼業をしていれば、当然毎日使うgitコマンドですが、`git commit`や`git push`は欠かせないと思います。
私も毎日`git push`や`git commit`を打ちまくっています。`git merge`や`git cherry-pick`も人よりはよく使うかも知れません。
`git rebase`とかはよく分からないので使わないようにしています。
>ブランチの歴史がおかしくなったら1から作り直して必要なコミットを古いものからcherry-pickして新たに歴史作るほうが絶対に早いし安全です

`git revert`も止むをえない時以外は使わないですね。実装中にコミット単位でrevertすることは普通はないですし、（あってもミスやバグのコードはrevert叩くより普通に削除して書き換えたほうが早いですね）
stagingやQAなどのマージ後にrevertするならgithubのマージコミットからrevertPR作ってチェックアウトしたほうが安心な気がします。

他の方のプルリクレビューをすることが多い日は`git checkout`と`git pull`もよく使うと思います。


この業界で働いていれば毎日とんでもない回数打ってると思うこれらのコマンド、ふと疑問に思ったことないですか?

#### gitのコマンドなんかイケてなくない?

`git checkout`とかいろんな機能が混じってて使いにくいし、ブランチ名の命名規則がある場合とか楽にしたいなとか思うことありますよね。

手元のブランチリストを取得する`git branch`は、ある程度開発が進むととんでもない数のブランチ名がズラッと並んで今の作業ブランチが何なのか分からなくなったりしますよね。

#### 基本はどんなコマンド?

##### push
pushについてはだいたいこんなコマンドだと思います。
```
$ git push -u origin working_branch:working_branch
```
↑長い、いきなりpush実行されるのなんかコワイ[解決編](#安心してpushできるようにするコマンド)
> オプション設定でoriginを省略したりブランチ名を省略したりできるようですが、自分は怖い感じがして使わないようにしています。
[参考](https://qiita.com/westhouse_k/items/167276ece3b9562eee3e)

##### checkout
chckoutについても
```
# リモートからチェックアウト
$ git checkout -b remote_branch origin/remote_branch

# 手元のブランチ切り替え
$ git checkout local_branch

# 手元でブランチ新規作成
$ git checkout -b new_local_branch

# 何故かファイルの変更を元に戻す機能もある（ファイルと同じ名前のブランチあったらどうなるんじゃろ?）
$ git checkout abc.txt
```
こんな感じで、機能が多すぎますね。どちらにしろダラダラ長いし同じブランチ名を何度も打ったり、リモートのcheckoutのときと手元のブランチの切り替えやブランチの新規作成でコマンドが違ったりcheckoutをファイルの復帰の意味にも使えたり使いにくいと思う人も多いのかなと思います。[解決編](#ブランチ切り替えの汎用コマンドgcbを定義する)

> *最近（2020年〜）は本家で`git switch`と`git restore`という便利なコマンドが実装されたらしいです。 [参考](https://qiita.com/yukibear/items/4f88a5c0e4b1801ee952)
(2020/8/16のGIT2.23より 知らなかった！)

##### git branch
特にブランチの一覧を返す`git branch`は皆さんの手元でもこんなふうになるのではないでしょうか?
```
$ git branch #メッチャいっぱい出てくる、、。
  is18xxx_change_texts
  is18xxx_convert_po_****
(中略)
  ishimizu-qiitaman/issue21xxxx
* ishimizu-qiitaman/issuexxxx64
  ishimizu-qiitaman/issue21xxxx
  ishimizu-qiitaman/issue21xxxx
  ishimizu-qiitaman/issue2xxxx6
  ishimizu-qiitaman/issue2xxxx_add_new_year_holydays2023
(中略)
  ishimizu-qiitaman/issue2xxxx_avoid_deadlock_****
  master
  qa/csv-****
  qa/po-****
(中略)
  revert-21xxxx-revert-18xxxx-is180xxx_po_xxxxxxx
  revert-21xxxx-revert-21xxxx-ishimizu-qiitaman/issue21xxx
# 43個ありました
```
↑*印のところがカレントブランチですが、場合によっては1画面で今のブランチ名が見えないこともありますね。
二度と使うことのないrevertPRのブランチとかも残りっぱなしのことも多いかと思います。（掃除しろって話かもしれませんが）
皆さんのワークディレクトリも同じ状況じゃないですか?[解決編](#git-branchの表示を抑制したい)

> 弊社の開発部ではブランチ名の命名規則は特に無いのですが自分は昔から開発単位でgithubのissueに仕様を書くチケット駆動開発にしていてissue番号と分かりやすい英語のテキストを並べたブランチ名にすることが多いです。
最近VSCodeのgithub拡張でissueベースでブランチを作ると{githubのユーザー名}/issue{issue番号}の形式でブランチ名を作ってくれるのが気に入って{githubのユーザー名}/issue{issue番号}_{英語の名前}のような感じのブランチ名にするのがお気に入りです。
例：ishimizu-qiitaman/issue2xxxx_add_new_year_holydays2023
ブランチ名の頭にissue番号を入れておけば`git branch`で並べるとカレントブランチの前後に最近関係したブランチ名が並ぶことが多いので分かりやすいです。 

_願わくば`git branch`で最近使ったものだけ出てきてbashのhistoryコマンドのように数字を打つだけで過去のブランチに切り替えたりできるようにしたい、、。_

*そういうコマンドを作れば出来ます。
[ブランチ切り替えの履歴を残す](#履歴を残す)
[ブランチの切り替え履歴をhistoryコマンドのように表示したい](#ブランチの切り替え履歴をhistoryコマンドのように表示したい)


### デフォルトでイケてないgitのコマンドをなんとか楽にして、毎日打つコマンドの文字数を減らしたい

そこでここ数年、自分は~/.bash_profileにgit関係のショートカットコマンドを大量に登録してgitのコマンド入力を省力化することを細々進めています。

上述の`git branch`を効率化するコマンドも作ったのですが、それは以下で[解説](#git-branchの表示を抑制したい)するとして。

#### 今年作ったコマンドで一番便利になったと感じているのはコミット時のコマンドをラッピングしたものでそれを使うと思わぬ副作用があり、長年英語のコミットメッセージを使う習慣を辞めて日本語のコミットメッセージを使うようになり、かなり業務効率が改善したという話です。


##### `git commit`をラッピングしたコマンドgciを.bash_profileに定義する
コマンドの定義はこのような感じです。

```bash ~/.bash_profile
# `gci コミットメッセージ`でコミット実行できる
gci() {
  # カレントディレクトリがgit配下で無ければ何もしない
  if ! `is_git_dir` ; then
    echo "not a git directory"
    return
  fi
  BR_NAME=`br_name`
  # $1が日本語の場合は単語の区切りスペースがないためダブルクオテーションなしでも1変数で受け取れる
  COMMIT_MESSAGE=$1
  # カレントブランチがコミットしちゃいけないブランチであればその旨明記して何もしない
  if [[ $BR_NAME = 'master' || $BR_NAME = 'production' || $BR_NAME = 'staging' ]]; then
    echo "$BR_NAME is not allowed to commit locally"
    return;
  fi
  git commit -m '$COMMIT_MESSAGE'
}

# 以下gciが呼んでる関数とエイリアス
# 現在のブランチ名を返すエイリアス
alias br_name="git branch | grep '*' | sed -e 's/* //'"

# カレントディレクトリがgit配下であればtrue
is_git_dir() {
  git rev-parse 2> /dev/null
}

```

これで何が変わったかというと
英語のコミットメッセージの場合今回の短縮コマンドを使っても
```
$ gci "commit message"
```
とダブルクオテーションでくくるのが必須になってしまいます。英語の場合単語の区切りがスペースであるためダブルクオテーションが無いとbashの関数は引数が2つ送られてきていると誤解し$1が"commit"の部分だけになってしまうからです。
ダブルクオテーション打つの地味に面倒じゃないですか。

ですが

日本語コミットメッセージにするとこのようになります
(コメントアウト部分にishimizuの黒魔術コマンドがいくつか含まれますのでこのまま参考にしないで下さい、[下で](#おまけ) 関数定義は紹介します)
```bash
<< CMT
 gcb qiita_test_branch # ブランチの作成
----------------------------
Do you want to create new branch qiita_test_branch? (y/n) # ブランチ名が間違えてないか対話的に確認するようにしています
y
git checkout -b qiita_test_branch && push_br_history master # 直前に居たブランチを履歴ファイルに保存します
Switched to a new branch 'qiita_test_branch'
 echo abcde > aaa.txt # ダミーファイルの作成
 git add aaa.txt 
CMT
$ gci CAMPFIRE社アドベントカレンダーQIITA記事12/15のためのコミットメッセージです。この記事は日々消耗するgitのコマンドをbashの関数を使うことで楽になって皆で幸せになろうという趣旨のもと執筆されました #日本語コミットメッセージです。
git commit -m 'CAMPFIRE社アドベントカレンダーQIITA記事12/15のためのコミットメッセージです。この記事は日々消耗するgitのコマンドをbashの関数を使うことで楽になって皆で幸せになろうという趣旨のもと執筆されました' #解りやすく実行時のコマンドを出力しています
[qiita_test_branch 5c36b88176] CAMPFIRE社アドベントカレンダーQIITA記事12/15のためのコミットメッセージです。この記事は日々消耗するgitのコマンドをbashの関数を使うことで楽になって皆で幸せになろうという趣旨のもと執筆されました
 1 file changed, 1 insertion(+)
 create mode 100644 aaa.txt
<< CMT
 gpush #カレントブランチのpushコマンド
----------------------------
Are you sure you want to push qiita_test_branch ? (y/n) #push行為が間違えていないか対話的に確認するようにしています
y
git push -u origin qiita_test_branch:qiita_test_branch #解りやすく実行時のコマンドを出力しています
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 508 bytes | 508.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
remote: 
remote: Create a pull request for 'qiita_test_branch' on GitHub by visiting:
remote:      htps://github.com/campqiita-xyz/campqiita-N/pull/new/qiita_test_branch
remote: 
remote: GitHub found 10 vulnerabilities on campqiita-xyz/campqiita-N's default branch (x critical, y high, z low). To find out more, visit:
remote:      htps://github.com/campqiita-xyz/campqiita-N/security/dependabot
remote: 
To github.com:campqiita-xyz/campqiita-N.git
 * [new branch]            qiita_test_branch -> qiita_test_branch
Branch 'qiita_test_branch' set up to track remote branch 'qiita_test_branch' from 'origin'.
CMT
```
日本語の長いコミットメッセージもダブルクオテーションを付けずに記述できるのはマジで最高です。

実はこのようにしてもう一つ良い点がありまして、プルリクエストの作成時にgithubのPR本文のタイトルに日本語のコミットメッセージがそのまま表示されるようになるのです。もともと英語のコミットメッセージでもその様になっていると思いますが、人にレビューしてもらうのにわざわざ日本語文を打つ手間がなくなり非常に楽になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/851627/3f63251d-b242-fdea-30b0-4946226d7db0.png)

##### そもそもなぜコミットメッセージを英語にするのが好ましいと考えられてきたのか。

おそらく文字化け対策や外国人エンジニアとのやり取りを念頭に入れてとのことかと思いますが、自分も元はほとんどのプロジェクトで英語のコミットメッセージを書くようにしていました。[参考](https://anond.hatelabo.jp/20160725092419)
* git commit -m "add ナントカ"
や
* git commit -m "modify ナントカ",git commit -m "change ナントカ", git commit -m "fix ナントカ"

みたいなのは毎日のように書いていました。modifyとfixとchangeの使い分けもよく分かりません。
不勉強で変な単語やスペルミスのままコミットログが残ることも多々ありました。一時期海外で仕事していたこともありましたのでそういう時は英語のコミットメッセージが望ましいのは当然ですが。

 ##### 時は進み今はもう令和ですよ。そしてここは日本です。
 昔のUNIXやDOSの環境で直接OSのCUIコンソールにコマンドを打つ時代じゃあるまいし、WindowsでもMacでもターミナルの多言語化は標準でされていますし、それどころかnodeやyarnの標準出力で見慣れない絵文字が出てくる時代です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/851627/2668b8f9-f6e9-c462-21f5-e99fe7e7f4ba.png)

日本人のエンジニアである我々がわざわざ不慣れな英語でコミットメッセージを残す必要なんか無いのではないかなと思うのは私だけではないのではないでしょうか。弊社でも外国人エンジニアは在籍していますが、彼らは日本語を自然に使いこなすので特に社内のプロジェクトで英語コミットメッセージに拘る理由はないような気がしています。

コードのライフサイクルに重要なコミットメッセージを英語にする必要はあまりないのではないかなと思います。

### さあみなさんも先入観を取っ払って日本語コミットメッセージにして楽になりましょう。

#### おまけ
ishimizuが普段使っててかなり便利になってるコマンド群を紹介します。

##### 共通コマンド

bashで実行時に(y/n)の対話的な確認ダイアログを出すコマンド
どんなコマンドを作るにもこういうのはあったほうが良いです。bashのコマンドは確認せずに実行になるのが普通なので自作の関数を使う場合何を実行しようとしてるのか何を実行したのかの確認出力を出すコマンドは定義しておくと便利です。
```bash ~/.bash_profile
# 定型文で(y/n)の入力を促すメッセージを出力
confirm_msg() {
  MESSAGE=$1
  echo "----------------------------"
  echo "$MESSAGE (y/n)"
}
# コマンド入力を待機してyが打たれればtrueになる関数
confirm() {
  read input
  if [ -z $input ] ; then
    test 0 = 1
  else
    test "$input" = 'y'
  fi
}
# 引数のコマンドを出力してそのまま実行するコマンド
echo_execute() {
  COMMAND=$1
  echo $COMMAND
  eval $COMMAND
}
# 第一引数のメッセージを表示してyが入力されれば第二引数のコマンドを実行する
# `confirm_and_execute "Are you sure to touch new file?" "touch new_file.txt"` のようにするとyが入力されるとnew_file.txtが生成されるようなコマンドになる。
confirm_and_execute() {
  MESSAGE=$1
  COMMAND=$2
  confirm_msg "$MESSAGE"
  if `confirm` ; then
    echo_execute "$COMMAND"
  else
    echo "invalid input"
    return
  fi
}

```

##### 安心してpushできるようにするコマンド
`git push`の時、思わぬブランチがpushされると面倒なことが起こりますし、引数無しで`git push`実行すると何が起こるかわからないから普通は毎回pushするブランチ名やリモートリポジトリの名前を書く必要がありますが、だいたい今作業中のブランチを同じ名前でoriginにpushすることが多いと思うので引数無しでpushするとカレントブランチがpushされるようなコマンドを作りました。（pushする前に確認ダイアログが出ます。）
```bash  ~/.bash_profile
# 引数がなければカレントブランチを、引数があればそのブランチをpushします。pushの実行前に何をしようとしてるか確認が出るので安心です。
# masterやproductionなどをpushしようとすると警告を出して中断します。
gpush() {
  if ! `is_git_dir` ; then
    echo "not a git directory"
    return
  fi
  BR_NAME=$1
  BR_NAME=${BR_NAME:-`br_name`}
  if [[ $BR_NAME = 'master' || $BR_NAME = 'production' || $BR_NAME = 'staging' ]]; then
    echo "$BR_NAME is not allowed to push directly"
    return;
  fi
  confirm_and_execute "Are you sure you want to push $BR_NAME ?" "git push -u origin $BR_NAME:$BR_NAME"
}
```

##### git merge --no-ff masterを毎日使いたい
長期間に渡る開発してるとmasterの取り込みが疎かになって気づいたらPRがmasterと競合してたり、知らぬ間にmasterで機能追加があって考慮が漏れたまま進んでしまったりあるあるだと思いますが、masterの取り込みはこまめにしたいものです。
いちいちmasterに入ってpullするのは面倒なので、fetchとmergeを一度に出来たり、ブランチ名省略したらデフォルトでmaster取り込みになるコマンドがあればどんなに便利かと思い作りました。
```bash  ~/.bash_profile
# 引数のブランチをfetchするコマンド
gfetch() {
  if ! `is_git_dir` ; then
    echo "not a git directory"
    return
  fi
  BR_NAME=$1
  BR_NAME=${BR_NAME:-`br_name`}
  echo_execute "git fetch -u origin $BR_NAME:$BR_NAME"
}
# 'gmerge' だけでmasterをfetchしてno-ffでマージまでします。引数を指定すれば指定ブランチをfetchしてカレントブランチにマージします
gmerge() {
  if ! `is_git_dir` ; then
    echo "not a git directory"
    return
  fi
  BR_NAME=$1
  BR_NAME=${BR_NAME:-master}
  gfetch $BR_NAME
  echo_execute "git merge --no-ff $BR_NAME"
}
```

##### git-branchの表示を抑制したい
これは一行のaliasでだいたい解決します。（上下7行分のブランチ名を出す）
```bash  ~/.bash_profile
alias gbr="git branch | grep -7 -w '*'"
```

#### gitのブランチの切替時に履歴を残して履歴から短いコマンドで過去のブランチに移動したい

##### 履歴を残す

```bash  ~/.bash_profile
# ブランチの履歴をhistoryファイルに残す
# gitのリポジトリパスからユニークなhistoryファイル名を生成
# ファイル名のフォーマットは「/home/uername/{sha256に基づく短縮乱数文字列}-{リポジトリ名}.git_br_history」となる
ghistfile() {
  GITDIR=$(git rev-parse --show-toplevel)
  echo -n "$HOME/"$(echo -n $GITDIR | shasum -a 256 | sed "s/^\(........\).*$/\1/")"-`basename $GITDIR`.git_br_history"
}
# 引数にブランチ名を渡すと時刻とブランチ名をhistoryファイルに書き込む
push_br_history() {
  if ! `is_git_dir` ; then
    echo "not a git directory"
    return
  fi
  BR_NAME=$1
  if [ $BR_NAME = 'master' ] ; then
    return
  fi
  BR_STACK+=( $BR_NAME )
  date +%s >> `ghistfile`
  echo $BR_NAME >> `ghistfile`
}
# 履歴の書かれたhistoryファイルを読み込んでブランチを切り替えた時刻とブランチ名をグローバル変数に配列として読み込む
export BR_HIS_DATE
export BR_HISTORY
read_br_history_file() {
  if ! `is_git_dir` ; then
    echo "not a git directory"
    return
  fi
  BR_HIS_DATE=()
  BR_HISTORY=()
  C=0
  while read LINE || [ -n "${LINE}" ]; do
    if [ `expr $C % 2` -eq 0 ]; then
      BR_HIS_DATE+=( "$(date -d @$LINE "+%Y/%m/%d %H:%M:%S")" )
    else
      BR_HISTORY+=( "$LINE" )
    fi
    C=$((C+1))
  done < `ghistfile`
}


```

##### ブランチ切り替えの汎用コマンドgcbを定義する
履歴を残しながらブランチを切り替えるコマンドgcbを定義（ブランチの切り替えは必ずこのコマンドを使用する）

このコマンドには以下の機能がある
>・引数のブランチ名のブランチが手元にある場合→そのままcheckoutする
・引数のブランチ名のブランチが手元に無いがリモートにはある場合→リモートからcheckoutするかたずねてyならcheckoutする
・リモートにも手元にも存在しないブランチ名が引数に指定された場合→ブランチを新規作成するかたずねてyならブランチを作成する
```bash  ~/.bash_profile
# `gcb {ブランチ名}`でブランチ切り替えに関わる全ての作業を実行する
gcb() {
  if ! `is_git_dir` ; then
    echo "not a git directory"
    return
  fi
  BR_NAME=$1
  BR_NAME=${BR_NAME:-master}
  CUR_BRANCH=`br_name`
  if [ "$BR_NAME" = "$CUR_BRANCH" ] ; then
    echo "already on $BR_NAME"
    return;
  fi
  # 手元に同名ブランチがある場合履歴を残しながらそのままチェックアウト
  if `br_exists $BR_NAME` ; then
    echo_execute "git checkout $BR_NAME && push_br_history $CUR_BRANCH"
  else
    # リモートに同名ブランチがある場合履歴を残しながらリモートからチェックアウト
    if `br_exists_on_remote $BR_NAME` ; then
      confirm_and_execute "Do you want to checkout $BR_NAME from remote?" "gco_remote $BR_NAME && push_br_history $CUR_BRANCH"
    else
      # 存在しないブランチ名なら確認して履歴を残しながら新規ブランチ作成
      confirm_and_execute "Do you want to create new branch $BR_NAME?" "git checkout -b $BR_NAME && push_br_history $CUR_BRANCH"
    fi
  fi
}

# gcbが呼んでる関数
# ローカルブランチに引数のブランチ名が存在するか確認
br_exists() {
  BR_NAME=$1
  test "`git branch | sed -e 's/\*//' | sed -e 's/ //g' | grep -x $BR_NAME`" = "$BR_NAME"
}

# リモートブランチに引数のブランチ名が存在するか確認
br_exists_on_remote() {
  BR_NAME=$1
  test "`git branch -r | sed -e 's/origin\///' | sed -e 's/\*//' | sed -e 's/ //g' | grep -x $BR_NAME`" = "$BR_NAME"
}

# リモートブランチと同名のブランチをチェックアウトする
gco_remote() {
  if ! `is_git_dir` ; then
    echo "not a git directory"
    return
  fi
  BR_NAME=$1
  echo_execute "git checkout -b $BR_NAME origin/$BR_NAME"
}

```

##### ブランチの切り替え履歴をhistoryコマンドのように表示したい
履歴をhistoryファイルに残す必要があるので普段からブランチの切り替えに専用のコマンドを使用する必要があります。
[履歴を残す](#履歴を残す)
[ブランチ切り替えの汎用コマンドgcbを定義する](#ブランチ切り替えの汎用コマンドgcbを定義する)

このコマンドには以下の機能があります
>・引数なしで実行するとブランチ切り替え履歴を新しい順に表示する
・引数に履歴番号を指定すると対応するブランチに切り替える
・引数に負の数を指定すると○個前のブランチに切り替える

```bash ~/.bash_profile
br_history() {
  if ! `is_git_dir` ; then
    echo "not a git directory"
    return
  fi
  # historyファイルを読み込んで$BR_HIS_DATEと$BR_HISTORYに配列として読み込む
  read_br_history_file
  BR_INDEX=$1
  # 引数が指定されてる場合
  if [ -n "$BR_INDEX" ]; then
    # 負数なら配列の最後から負数分戻った履歴のブランチに移動
    if [ "$BR_INDEX" -lt 0 ]; then
      gcb ${BR_HISTORY[$((${#BR_HISTORY[@]} + $BR_INDEX))]}
    else
      # 正数ならそのインデックスの値のブランチに移動
      gcb ${BR_HISTORY[$BR_INDEX]}
    fi
    return;
  fi
  # 引数がなければ新しいものから順に履歴を表示する（一度表示したものは$DISPLAYED_BRに残して表示していない）
  DISPLAYED_BR=()
  for ((i = ${#BR_HISTORY[@]}-1; i >= 0 ; i--))
  do
    if ! [[ " ${DISPLAYED_BR[@]} " =~ " ${BR_HISTORY[$i]} " ]]; then
      echo "$i => ${BR_HIS_DATE[$i]} ${BR_HISTORY[$i]}"
      DISPLAYED_BR+=( "${BR_HISTORY[$i]}" )
    fi
  done | less # とりあえずlessで全て表示します
}
# ghで履歴が呼べるようにaliasで定義します。
alias gh='br_history'
# gh-popで一つ前のブランチに戻れます。
alias gh-pop='br_history -1'
```
##### これでこれまでやりたかったgitブランチの履歴を少ないコマンドで表示して自由自在に行き来できるようになりました。
```
$ gh # 引数なしでブランチ履歴表示
189 => 2022/12/12 17:15:35 ishimizu-qiitaman/issue2xxxx_fix_abc_bug
188 => 2022/12/12 17:15:27 ishimizu-qiitaman/issue2xxxx_project_histories
185 => 2022/12/12 17:11:18 qa/pj-history
184 => 2022/12/12 17:10:24 qa/kengen
183 => 2022/12/12 17:04:26 qiita_test_branch
182 => 2022/12/12 16:47:19 abcdefghijk/redirect-project-on-comment-page
177 => 2022/12/09 12:29:16 ishimizu-qiitaman/issue2xxxxx
176 => 2022/12/06 18:29:05 ishimizu-qiitaman/issue2xxxxx_fix_column_type
174 => 2022/12/06 12:43:46 is18xyz_remove_old_contoller_and_routing
...以下略 同名ブランチは表示されない...

$ gh 189 # 履歴番号189のブランチに切り替え
git checkout ishimizu-qiitaman/issue2xxxx_fix_abc_bug && push_br_history prev-branch
Switched to branch 'ishimizu-qiitaman/issue2xxxx_fix_abc_bug'
```
良い！

実に良い

最後にもう一つ地味に役立ってるコマンドがあります。

##### プルリクエスト作成URLを表示するコマンド
新しいブランチを作って初回にpushした直後にgithub内でプルリクエスト作成するURLが表示されます。
こういうやつです。
> hts://github.com/campqiita-xyz/campqiita-n/compare/issue2xxxx_project_branch

ですがこのURL二度目以降のPUSHでは表示されない上ちょっと経つと自分のブランチのPRのURL探すのは微妙に面倒だったりしますね。
そういうときのためにいまのブランチのプルリクエスト作成URLを表示するコマンドを作りました
```bash ~/.bash_profile
alias git_url="git remote -v | grep push | sed -e 's/^.*git@\(.*\):\(.*\)\.git.*$/https:\/\/\1\/\2/'"

pr_url() {
  if ! `is_git_dir` ; then
    echo "not a git directory"
    return
  fi
  echo "`git_url`/compare/`br_name`"
}

```
####  ここまで読んだあなたならブランチ名に命名規則がある場合どういう関数を作れば便利になるか分かりますよね?

興味があればgcbを改造するかラッピングしてやってみて下さい。
[ブランチ切り替えの汎用コマンドgcbを定義する](#ブランチ切り替えの汎用コマンドgcbを定義する)
```bash ~/.bash_profile
my_gcb() {
  $ISSUE_NO=$1 # 引数にissue番号を取る場合
  echo "input branch name text"
  read input # 対話的に英文のブランチ名を取得する場合
# あとは$ISSUE_NOと$inputをつなげてgcbに渡せばよいです

}
```
このコマンドは自分もまだ作ってません。続きはあなた次第
#### 可能性は無限大です。
> githubの自分の担当issueから候補を取得して選ぶようにしても良いし、
issueのタイトルをgoogle翻訳に投げて得られた英文を_でつなげてブランチ名の候補にするのも良いかも知れません。

とにかく毎日打つコマンドは極力繰り返しを減らして楽になりましょう。bashはとっつきにくい言語で自分も嫌いですが、どんな環境でも動きますし、一度作ればずっと使えるコマンドを作ることが出来ます。

弊社では私達と一緒に働ける方の求人を募集しています。bashやgitに限らずrubyやvue.jsでお金の流れの新しい世界を一緒に作っていきませんか?

https://campfire.co.jp/careers/