Gitリポジトリの一括プルを自動化したバッチファイルの作成と説明 ~ git pull -pと開発ブランチへのpull動作の自動化 ~ 

# Abstract
- 毎回[``git pull -p``]をコマンドで実行し、複数ある作業元となるブランチを個々でPullしていた状態は、無駄な時間がかかる上にミスを誘発する状況であった。
- その為バッチファイルを作成し一連の動作を自動化することにより、作業時間の削減とさらなるエラー防止を図った。
- 現在の状態ではコードに無駄がある。しかし解解決法が分からず、修正できていない。
# 背景
- 毎回[``git pull -p``]を使用するのが面倒だった。
- pullを忘れたことによる問題が多発した。
  - masterブランチやdevelopブランチをpullする前に分岐し、古いバージョンをテスト版として配布してしまった等 

<hr>

- 2023.03.22で変更した理由。
    - checkoutで反映している為、バッチファイル実行後[masterブランチ]に移動してしまう問題があった。
    - 元のブランチに手動で戻るのが面倒なので、``checkout``を使用する前にカレントブランチの名前を変数に格納し、最後そのbranchに自動で戻るようにした。

# 本文
## コード
```bat
@chcp 65001 @rem バッチファイルの文字コードをがUTF-8にする
@rem 230322_git pull UpStream-p & master and Develop branchs apply.
@rem リモートリポジトリから、全てのbranchを削除も反映してpullする
@rem Develop_fix、Develop_feature、develop、masterのローカルリポジトリを最新にする

cd Development_folder_exists_behind
git pull UpStream -p @rem fork元からpullする。削除も反映する

@ for /f "usebackq" %%i in (`"git symbolic-ref --short HEAD"`) do set now_branch=%%i @rem カレントブランチの名前を変数に格納する
@echo "現在のbranchは [ "%now_branch%" ] です。" @rem @echoにしない場合「現在の～」が2つ出力される

git checkout -B Develop_fix UpStream/Develop_fix
git checkout -B Develop_feature UpStream/Develop_feature
git checkout -B develop UpStream/develop
git checkout -B master UpStream/master

git checkout %now_branch% @rem checkoutコマンド使用前に取得したブランチに移動する

@rem 通常時は実行結果を確認しない
@rem pause
```

### コードの背景
- このリポジトリのコラボレーターであるが、forkリポジトリを使用している状態である。
- ``@echo off``を使用せず``@``を多用しているのは、コマンドは出力してほしい為。
- ``@rem pause``はエラーが起きた時、コメントアウトを解除してエラーを表示できるようにする為。
  - 確認したい際に「pause」を打ち直すのが面倒くさい。
  - コマンドを覚えていない為、毎回調べることになる。

### コードの説明
#### ``@chcp 65001``
##### 内容
- バッチファイルの文字コードを``UTF-8``として明示する。
- 日本語の使用がコメント文のみであったとしても、これを使用しないと想定外の挙動を起こすことがある。
- 参照 : <a href="https://nayutari.com/batch-utf8">UTF-8のバッチファイルが文字化けする時の対処3選</a>

#### ``for /f "usebackq" %%i in (`"git symbolic-ref --short HEAD"`) do set now_branch=%%i``
##### 内容
- カレントブランチの名前を 変数:now_branchに格納する。
- [ループ処理でコマンドを実行するコマンド](#[ループ処理でコマンドを実行するコマンド]),[カレントブランチの名前を取得するコマンド](#カレントブランチの名前を取得するコマンド),[変数に格納するコマンド](#変数に格納するコマンド)の組み合わせコマンドになっている。

###### [ループ処理でコマンドを実行するコマンド]
```bat
for /f "usebackq" %%i in (`"git symbolic-ref --short HEAD"`) do set now_branch=%%i
```
↓
```bat
for /f "usebackq" %%[アルファベット１文字] in (`"[実行したいコマンド]"`) do [コマンド]
```
- [変数名]:``now_branch``に [実行したいコマンド]:``git symbolic-ref --short HEAD``の結果を格納する。
    - ``"usebackq"``オプション
        - コマンドの出力をfor文で取り扱い可能にする為のオプションである。
        - これがない場合、```(`ファイル名`)```での取り扱いになり、ファイル内のテキストを操作するコマンドとなる。
            - ``"usebackq"``を消した場合の実行結果
              > ```
              > D:\In_front_of_the_development_folder\Development_folder_exists_behind>for /F %i in (`"git symbolic-ref --short HEAD"`) do set now_branch=%iファイル `"git symbolic-ref --short HEAD"` が見つかりません。
              > ```
              - このように``git symbolic-ref --short HEAD``をコマンドではなくファイル名として認識してしまう。
     - ``%%i``
       - このfor文はC#のforeach文と似た構造になっている。
       -  コレクションの要素(コマンド実行結果)を取得する変数。
       -  [実行したいコマンド]をiに格納し、[実行したいコマンド]の出力に対して[コマンド]を実行できるようにする。

###### [カレントブランチの名前を取得するコマンド]
```git
git symbolic-ref --short HEAD
```
- > *Gitにおける``symbolic ref``という概念は、``refs/head/master``みたいなコミットオブジェクトの参照を指す*
引用 : <a href="https://blog.hifumi.info/2015/03/28/show-current-branch-name/">Gitリポジトリのカレントブランチ名を取得する</a>

- ``--short``オプションで``symbolic-ref``から、ブランチ名のみを切り出し取得している。

###### [変数に格納するコマンド]
```bat
do set now_branch=%%i
```
↓
```bat
do set [変数名]=[格納内容]
```
- 変数の初期化と代入を行う。
- [実行したいコマンド]:``git symbolic-ref --short HEAD``の出力結果が格納されている%%iを、do setで宣言した[変数名]:``now_branch``に代入する。
- これらにより、カレントブランチの名前が``now_branch``に格納される。

#### cd Development_folder_exists_behind
##### 内容
- このコード以降のコマンドを実行したいフォルダである、
カレントフォルダ(batファイルが存在するフォルダ)の階層に存在しているフォルダに移動する。
  - ``Development_folder_exists_behind``はクローンしたフォルダであり、
このbatファイルが存在するのはローカルリポジトリではなく、
一つ前の階層のフォルダ。
#### git pull UpStream -p
##### 内容
- プルーンオプションを使用してUpStreamからすべてのブランチをpullする。
  - プルーンオプション(``-p``)は、リモートリポジトリの削除も反映させる。

#### git checkout -B [ローカルブランチ名] [追跡元となるブランチ名]

##### 内容
- ``git checkout -B master UpStream/master``<br><br>
  - **「ローカルブランチ:``master``を削除し、
追跡元となるブランチ:``UpStream/master``を追跡した、
ローカルブランチ:``master``を作成する」**<br><br>
    - ``-B``オプションにより、
元々存在している[ローカルブランチ](*2_ローカルブランチ)を削除し、再度リモートブランチを追跡する同じ名称のローカルブランチ（``master``）を作成している。。
      - 削除の工程を挟む為、プルしたいブランチが編集されていてもエラーが生じず反映することができる。<br><br>
      - 注:
        - ここで``checkout``しているブランチは、UpStreamで保護されているブランチであり、コミットしてはいけない物。
        - 変更されてはいけない物の為、自身が編集していてもそれを無視し削除して問題がない。

###### 実行結果
```
D:\In_front_of_the_development_folder\Development_folder_exists_behind>git checkout -B master UpStream/master
Switched to and reset branch 'master'
branch 'master' set up to track 'UpStream/master'.
Your branch is up to date with 'UpStream/master'.
```
###### 実行結果翻訳
```
ブランチ「master」に切り替わり、リセットされる。
ブランチ 'master' を追跡するように設定する 'UpStream/master'です。
あなたのブランチは 'UpStream/master' で最新になります。
```

# 課題点
- [リモート追跡ブランチ(*1)](#1_リモート追跡ブランチ)から、[ローカルブランチ(*2)](*2_ローカルブランチ)にマージする為に「checkout -B」を使用している事。
  - 毎回[ローカルブランチ](*2_ローカルブランチ)``master``を削除し、
[リモート追跡ブランチ](#1_リモート追跡ブランチ)``UpStream/master``を追跡した``master``ブランチを再度作成するという行動には無駄があると考える。
  - 一度にリモートリポジトリからローカルブランチにpullしたい。
(fetch->mergeを一括で行いたい)

# 注釈
##### *1_リモート追跡ブランチ
- VSCode上の画面でここにある物
  - <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119123/38017171-c5da-5dc7-1912-7b2a1b8f02e7.png" alt="リモート追跡ブランチとは何か?_VSCode上の画面" title="リモート追跡ブランチとは何か?_VSCode上の画面" width="250px"> 
##### *2_ローカルブランチ
- VSCode上の画面でここにある物
  - <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3119123/03fb4973-2227-b42b-ffc8-976a9ac7a343.png" alt="ローカルブランチとは何か?_VSCode上の画面" title="ローカルブランチとは何か?_VSCode上の画面" width="250px"> 


# 参考資料 & 謝辞

## 2023.03.18 投稿時分

- <a href="https://www.r-staffing.co.jp/engineer/entry/20201023_1">第17話 ローカルリポジトリに残ってしまうリモート追跡ブランチを一気に削除する prune オプション【連載】マンガでわかるGit ～コマンド編～</a>
  - 『わかばちゃんと学ぶ Git使い方入門』
  - リモートで削除されたブランチがローカルで溜まっていてそれを削除する方法を探していた時に参考にさせていただきました。<br><br>
- 共同開発者が使用していたバッチファイルのコード(非公開)
  - バッチファイルで自動化する手法に気づかせていただきました。
  - バッチファイルの記述方法は此方から参照しています。
<hr>

- <a href="https://www.javadrive.jp/command/bat/index4.html">コメントの記述(REM)</a>
  - バッチファイルの中でコメントを使用する方法
  - REMコマンドの使い方<br><br>
- <a href="https://qiita.com/yunano/items/f3133ea64efed762df2f">git checkout解説</a>
  - <a href="https://qiita.com/yunano/items/f3133ea64efed762df2f#%E6%96%B0%E3%81%97%E3%81%84%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%9D%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%B8%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88">新しいブランチを作ってそのブランチへ切り替え</a>の部分を特に参考にさせていただきました。<br><br>
- <a href="https://www.javadrive.jp/command/bat/index2.html">エコー機能のON/OFFを切り替える(ECHO)</a><br><br>
- <a href="http://teqspaces.com/Git/4">Git_git pullしてリモートリポジトリからローカルに取得する</a>
  - fetchとpullの仕組みをまだ理解していなかった為、確認させていただきました。

- https://chat.openai.com/chat
  - 記事の校閲をして頂きました。ChatGPTさんありがとうございます。

- フールプルーフについて
  - ChatGPTさんの校閲で削除していますが、記事を記載する際に参考にしていました。
    - <a href="https://resilient-medical.com/human-error/fail-safe-fool-proof">フェイルセーフとフールプルーフ～意味の違いと事例</a>
    - <a href="https://anzeninfo.mhlw.go.jp/yougo/yougo39_1.html">職場の安全サイト_フールプルーフ</a>
    - <a href="https://shikaku-dou.com/foolproof/">フールプルーフ_資格試験に合格するためのIT用語辞典</a>
  - フェールセーフ : エラーやミスが発生しても被害を最小限にとどめる仕組みにする事。
  - フールプルーフ : そもそもエラーや人的ミスが起こせない仕組みにする事。

## 2023.03.22 更新分
- <a href="https://somachob.com/bat-set/">バッチファイルで変数を使う方法</a>
    - 変数の扱い方の記事として最初に読み参考にさせていただきました。
    - シンプルに描かれていて理解しやすかったです。<br><br>
- <a href="https://www.kodaruma.com/2020/12/windows.html">[小ネタ]Windowsバッチでコマンドの実行結果を変数に格納する方法</a>
    - コマンドの実行結果を変数に格納する方法と、変数を使用する方法の参考にさせていただきました。<br><br>
- <a href="https://qiita.com/usamik26/items/8aa6c3aed4b9c7dba5ca">カレントブランチ名を取得するコマンド</a>
    - ブランチ名を取得するコマンドとして最初に参考にさせていただきました。<br><br>
- <a href="https://qiita.com/plcherrim/items/67be34bab1fdf3fb87f9">.bat（バッチファイル）のforコマンド解説。</a>
    - 上記参考のコマンドを使用した際、カレントブランチだけでなく所持しているブランチと``*``が実行結果に含まれていました。
    - 必要なのは「カレントブランチ名」だけなので実行結果を編集する必要があり、その方法を調べている時に参考にさせていただきました。<br><br>
- <a href="https://qiita.com/kawanet/items/a57e9ff21a205a45ce8a">gitでカレントブランチ名だけを取り出す</a>
    - 上記のコマンドは、自分が必要としていた結果を取得するコマンドではなかった為、最終的にこちらの記事のコメントで記載されていたコードを参考にさせていただきました。<br><br>
- <a href="https://blog.hifumi.info/2015/03/28/show-current-branch-name/">Gitリポジトリのカレントブランチ名を取得する</a>
    - 「カレントフォルダ」「カレントブランチ」という用語を知らなかった為、「現在居る～」と表記していました。
    - こちらの記事を拝見し「カレント～」という用語を知り修正いたしました。
    - ``symbolic ref``コマンドの意味の説明を参考にさせていただきました。<br><br>
- <a href="https://nayutari.com/batch-utf8">UTF-8のバッチファイルが文字化けする時の対処3選</a>

<hr>

###### 余談
- この記事の内容を全てChatGPTさんに渡し「この内容に合うタイトルを提案してください」と問いかけたら、全て英語に翻訳されました…
  - 何度か質問内容を変更して聞いたのですが、記事の内容を置いてから日本語で質問すると英語で返答されてしまいました。
  - 「# Abstract」が先頭にあり、
尚且つコードやURLの部分で英語が多かった為に、英語判定されてしまったのだと考えられます。<br><br>
- [フールプルーフ]の考え方を[フェールセーフ]と勘違いしていました。
  - 記事に使用したい言葉が誤用でないか確認した時に覚え間違いに気が付くことができました。