はじめに
はじめまして。よっしーと申します。
今回は過去の事例でお客様にソースコードを丸ごと納品するケースが有ったので、納品の際にZIPでソースコードを送付するのは嫌だと思って考えた納品方法に関してお話しします。
普段はAWSにアプリケーションをデプロイするという事例が多いのですが、そうでなかったときにうまくgitを活用できないかを考えてみました。
皆さんお客様にソースコードを納品する場合はどのようにしていますでしょうか?
ZIPファイルを作成してメール(or ZIP転送サイト等)、または、お客様のサーバーにFTP通信して転送していますでしょうか?(これもZIPかもですが)
このブログを見に来ている皆さんはgitでコードを管理していると思いますので、gitでそのまま渡したいなと考えてる方も多いのではないでしょうか?
でも見られたくないコミットもいっぱいあるはず!笑
お客様が別で納品用のリポジトリを用意してくれる前提ではありますが、gitでの納品の方法を考えてみました。
gitの単純な操作、開発時のgitのブランチ運用は前提知識として知っているものとして進めます。
特にcherry-pickに関しては前提知識として知っておいてください。
2つのリポジトリを手元でどう管理するか
案1:2つのリポジトリをそれぞれクローンして、開発用のリポジトリのコードを丸ごとコピーして、納品用のリポジトリにペーストして差分を管理していく。
これでも問題ないです。ただ、せっかく2つのリポジトリがあってgitの機能を活かせるのに勿体ないです。
案2:1つのローカルリポジトリに対して、2つのリモートリポジトリ(開発用リポジトリ、納品用リポジトリ)を設定して納品用のリポジトリにソースコードをcherry-pickで効率よく配置する
今回私が提案したい案はこれです。
開発用のリポジトリで作成したコミットを利用できると楽になりそうです。
わざわざコピーしなくても、今まで作ったコミット(差分)を適用し続けるだけで最新のソースコードをアップロードすることができます。
gitで納品する利点
案2にあるように、納品用のリポジトリに最新のソースコードを適用していくことの利点は以下と考えています。
- git管理をしているので、履歴管理ができる(納品者、納品日、前回納品時との差分(=修正内容)、等)
- 前回との差分がまとまって1コミットになり差分が見やすい
- 開発時の詳細なコミットメッセージや、1つ1つのコミットの修正内容までは残らない(地味に重要)
- メール送信等で直接的なソースコードの受け渡しを必要としない
利点を整理したところで、実際どのような方針で操作していくかを見ていきましょう。
基本方針
上記の案2を進めていくにあたり以下のリポジトリ管理を基本方針とします。
■ 開発側のリポジトリ:よくある開発フローに合わせます。
ここでは一旦、mainブランチ、developブランチ、featureブランチと分けて以下のように運用することを想定します。
- featureブランチで機能開発を行う
- featureブランチをdevelopブランチにmergeする
- 納品時にはdevelopブランチをmainブランチにmergeする
こうすることでmainブランチにはdevelopブランチの修正コミットだけmergeされているという状態になります。(下図参照)
■ お客様のリポジトリ(納品用リポジトリ):上記のmainブランチのコミットのみをcherry-pickして、mainブランチと全く同じ状態を保ちます。
上記2つのリポジトリが出現していますが、簡単にcherry-pickして操作することはできなさそうです。
それを実現するために、ローカルリポジトリで複数のリモートブランチ(上記の2つのリポジトリと同等と考えていただいたら良いです)を同居させる方法を以下手順でお伝えします。
操作手順
リモートブランチに各リポジトリを設定
ここからは実際のgitの操作を伴い、説明していきます。
上記で述べたように一度ローカルリポジトリに複数のリモートブランチを設定する方法をお伝えいたします。
いつもはgit cloneでリポジトリを複製していると思いますが今回は以下のような手順でリモートリポジトリと接続します。
■ 例
開発用リポジトリ: https://hoge.com/development.git
お客様納品リポジトリ: https://fuga.com/delivery.git
だった場合の想定
- まず、開発用ブランチのリモートリポジトリの設定
リモートのURLの名前は origin ではなくdevelopmentとしてcloneします
1234$ git clone https://hoge.com/development.git --origin development$ git remote -vdevelopment https://hoge.com/development.git(fetch)development https://hoge.com/development.git(push) - 次に納品用のリポジトリの設定
123456$ git remote add delivery https://fuga.com/delivery.git$ git remote -vdevelopment https://hoge.com/development.git(fetch)development https://hoge.com/development.git(push)delivery https://fuga.com/delivery.git(fetch)delivery https://fuga.com/delivery.git(push) - 両者のリポジトリの状態を最新化する
1$ git fetch --all
これでローカルのリポジトリで両者のリポジトリを操作できる準備が整いました。
開発する
基本方針で述べたように、開発側のリポジトリは以下のような開発手順で開発します。
2. featureブランチをdevelopブランチにmergeする
3. 納品時にはdevelopブランチをmainブランチにmergeする
ここで注意すべきことは、いつも皆さんoriginに対してpushを行っていると思いますが、開発用のリポジトリの設定はdevelopmentと名付けているので以下のようにしましょう。
1 |
$ git push development feature-XXX # feature-XXXブランチをdevelopmentのリポジトリにpushしたいと仮定 |
いつものように git push development feature-XXX と打ってしまうとoriginがない!と警告が出ますのでそこで気づけるとは思います。
上記の1~3の流れを簡単にコマンドをまとめると以下です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ git checkout main # まず初めにmainに移りましょう $ git checkout -b develop # developブランチを作成 $ git checkout -b feature-A # featureブランチを作成 # ソースコード修正 $ git add . # 修正内容を反映 $ git commit -m "ファイルAを加える" # 修正内容をコミットする $ git push development feature-A # featureブランチをdevelopmentリモートブランチに反映 $ git checkout develop # developブランチでfeature-Aをmergeする準備 $ git merge --no-ff development/feature-A # マージコミットがわかりやすいように--no-ffオプションを付与 $ git push development develop # developブランチをdevelopmentリモートブランチに反映 $ git checkout main # mainブランチでdevelopをmergeする準備 $ git merge --no-ff development/develop # マージコミットがわかりやすいように--no-ffオプションを付与 $ git push development main # mainブランチをdevelopmentリモートブランチに反映 |
上記コマンドを実行した結果が以下になります(先ほどお見せした図と同様になりますが)。
お客様用のリポジトリにコミット
ここまで来たらあと少しです。
開発用のmainブランチにmergeされたコミットをcherry-pickします。
mergeされたコミットをcherry-pickするには少し特殊なオプションを付ける必要があります。
1 2 3 |
$ git branch -f main delivery/main # mainブランチを一度deliveryのmainに移動 $ git cherry-pick -m 1 development/main # -m 1 オプションを付けることでmergeで作られたコミットをcherry-pickできる $ git push delivery main # mainブランチをdeliveryリモートブランチに反映 |
ここで重要なことは、developmentのmainブランチのコミットのみを変更点として受け取ってるので間のコミットは見られることがありません(コミットがまとまったという感覚に近い)。
また、deliveryのmainを下手に修正していない限り、コンフリクトするリスクは0です。
このようにdevelopmentリポジトリと、deliveryリポジトリのmainを同期し続けることでお客様に最新のコードを提供し続けることができます。
注意点
deliveryリポジトリはcherry-pick以外での更新は基本的にお勧めしません。
つい修正を直接入れたくなったりしますが、ぐっとこらえてdevelopmentリポジトリの更新を常にdeliveryに反映させるようにしないと要らぬコンフリクトのリスクが増えてしまいます。
そういった都合から、deliveryリポジトリからdevelopmentリポジトリに対する逆輸入みたいなcherry-pickは存在しません。
おわりに
最後までご覧いただきありがとうございます。
お客様に対する納品がただ単に大容量のZIPファイルを転送する方法ではなく、今の時代にそったgit管理で行う方法を紹介しました。
納品時だけなので使う機会も少ないですが、このような操作ができるということを知っておくと、gitでできることの幅も広がると思いますので、1つの武器として認識いただければ幸いです。
お客様との調整が可能ならぜひgitでの納品を試してみてください。
ではまた。