オッラァ!(挨拶)…ラァ!(再挨拶)

どうも僕です。

今日はね、gitについて知ってるようで何も知らない系女子高生であるお前に向けて、gitについて最近ちょっとわかってきてる俺が、耳たぶが大根おろしになるほどの激情をもってして、この魔法のフライパン片手に、標高4,200メートルを誇る標高1,600メートルから、昨日よりズキズキと脈動せし臀部を強く右に(略

gitのチーム開発について多少なり教えていきます。

※本意気で書いてないです。この話題は語りつくそうとすると激しく消耗する気がするので。あと今日はなんか頭が痛いし。

◆まえがき

初歩の説明はしません。しょほほ…(泣)

gitの基礎は知ってる前提。gitをこね回しながらチームをリードせねばならなくなった人に向けて話す。

ただ、ここに書いてあることをお前の現場に適用できるとは思わんほうがいい。gitの運用方法は時と場合に依る部分が大きい。エッセンスだけ学んだらあとはハートでドライブしろ。

時と場合に依るゆえに、あまり踏み込んだ説明はしないでおく。

チーム開発でのgitについてですから、個人開発は好きにしなよ。masterだかmainだか知らねぇけどpushしまくれよ。

◆リモートリポジトリ

無論GitHubで問題ないんだけど、AzureDevOpsを試してみて欲しいような。5人まで無料。趣旨違っちゃうからここで使い方は説明しないけど。

新しいブランチを起こす際は、ローカルで起こさないこと。各gitリポジトリプロバイダ(GitHubやらAzureDevOpsやらGitLabやらGitBucketやら)の操作画面から切ってね。

◆A successful Git branching model

戦略的にブランチを管理せねば、割と破綻する。コンフリクト祭りになったりもする。

だからgit flowという名前の戦略をまず理解するべきかも。使うにせよ使わないにせよ。

以下を読んで来い。

A successful Git branching model を翻訳しました

ブランチ種別を把握してほしい。master(main)とdevelopとfeature。

masterブランチのことは、以下mainブランチって呼ぶ。

masterブランチが神。developブランチはmasterを直に触りたくないから間に挟める緩衝材。featureは開発ブランチ。featureをポコポコはやしてdevelopにマージしていく。

この切り方も賛否両論あるんで、真に受けすぎないこと。熱心なアンチがいたりもする。柔軟に取り込め。

◆開発とプルリク

ながれ

  • developあるいはmainブランチからfeatureブランチを切る。
    • ブランチ名には「feature/」ってプレフィックスつけるよろし。
  • featureをローカルに落としてそこで開発。
  • 終わったらfeature切った元のブランチのoriginをfeatureにmerge。
    • つまりgit fetchした後にgit merge origin/developとかする。
    • conflict解消のため。
  • push

featureブランチの更新がリモートに飛んで行ったので、使ってるgitプロバイダの画面からdevelopに向けてプルリクとかマージを作成。

▼でかfeature

でかい機能については、featureブランチから更にサブブランチを切ること。プルリクが見やすく、追いやすくなる。

あるいは「機能名/develop」やら「フェーズ名/develop」って名前のブランチを最初に起こせばよいよ。開発ブランチは「機能名/開発内容」とか適当に。

つまり「develop」から切った「機能名/develop」ブランチから「機能名/ 開発内容 」ブランチを切り、開発し、「機能名/develop」ブランチに対してマージをかける。最終的には、まずコンフリクト解消のために「develop」を「機能名/develop」に向けてマージしてから「機能名/develop」を「develop」に向けてマージしろ。

◆リリース

ブランチ戦略は、リリース戦略と密接に絡んでいる。「どういうリリースをしたいか」が「どういうブランチ戦略にするか」を100%左右している。

ある程度のプロジェクトであればまず環境が複数あることだろう。基本的には本番環境と検証環境。これがないと何にせよやってられん。本番環境オンリーはありえん。

「本番環境」というものと対応するgitブランチを考えたとき、そりゃ当然mainブランチになる。検証環境はdevelopブランチなのかもな。

あるいはリリースを特に慎重にしなければいけない案件では、mainブランチを検証環境で確認したのち本番環境にリリースするのかもしれない。その場合は「開発環境」みたいなのを用意してdevelopブランチあてがってもいいだろう。

「本番」「検証」「開発」環境があればまぁ助かる。

◆マージは確信と共に

リリースとブランチには関連性がある。つまり、ブランチに何かをマージする際には留意が必要となる。

どういうことか。

例えば「鼻から虹色のうどんが出てくる機能実装して」って言われてさ、無事開発終えて、developまでマージ。その後で「引き出しから出てくるワカメを煮る機能」を実装し、これまたdevelopまでマージした。

リリース日は半月後だったんだが、「うどん機能のリリース日はやっぱ後ろに倒して、ワカメ機能だけリリースしたい」っていう話になったと。

困るよね。うどん機能は既にdevelopにマージされちゃってる。「develop⇒master」のマージができない。その時に「うどん機能を消すコミット」を作るのは残念極まりないっていうか114514個のファイルに1919810行の変更入っててもう死ぬ。コミットも364364件あるのでrevertも無茶。

っていうことになるじゃん?できたとしてコミットログが汚物絵巻になる。

だから、本当にリリースするものだけをdevelopにマージせねばならん。リリース時期が直近であるものだけ。それまでは各featureブランチで留めるのも手。

あるいは「develop⇒master」のマージフローを経ずに、各featureブランチからdevelopとmasterそれぞれにマージをかける運用にしてもいい。

いろいろな開発中のfeatureを混ぜ合わせつつ検証環境に対して荒れた感じにリリースせねばならん時は、mainとかdevelopとか言わず、もう「検証環境と1対1のブランチ」を作ってしまえばいい。featureをぐちゅぐちゅ混ぜ合わせて検証環境にリリースするためのブランチ。

▼マージ用ブランチ

いま開発しているfeatureブランチに対して別のfeatureブランチをマージするのは危険。ふたつの機能が混ざっちゃって分離できなくなるから。でもコンフリクトのせいで検証環境用のブランチにマージできない。

そうなったらもう「merge用/機能」みたいにプレフィックスつけてブランチを起こせば良いよ。マージするためだけのブランチを作ってもいい。そこでコンフリクト解消すればよい。

元からあったコミットに新しく乗せていいコミットは、ひとつの機能に絞られていたほうが無難です。

◆余談:プルリク捌き

◆ブランチポリシー

少なくともAzureDevOpsには、ローカルからのpushをはじく為の仕組みとかある

ブランチ ポリシーを使用してコードの品質を改善する

よくあるのが、作業ブランチのcheckout忘れてdevelopで開発しちゃって、間違ってpushしちゃうやつ。そういう事故を減らせる。

◆gitコマンド

暗記重点。別にUI使ってもいいけど、どう考えてもコマンドのほうが楽だと思うぞ。

ただ、「開発終わり⇒ローカルで変更内容を確認⇒ステージング⇒コミット」までの流れはマウス操作で困らんし楽なのでそうしている。diffとかaddとかしてられん。

▼git fetch -p

手元に持ってるブランチを全体的にそこはかとなく最新にしてくれる。

-p は --prune の省略形。

ハイフンふたつがなぜかひとつにマージされてしまう。WordPress死ね。

▼git pull

checkoutしてるブランチをリモートの最新にしてくれる

▼git push

pushする。

▼git merge origin/master

マージ。

「origin/master」ってのはよしなに変えろ。

「あ、トチった。マージやめたい。帰りたい。」って思ったら

git merge --abort

しろ。

▼git reset –soft HEAD^

git reset --soft HEAD^

先頭のコミットを消しつつ、手元に変更を残す。

ぎっと・りせっと・やわらか・あたま^q^

って覚えればいいよ。

すでにpushしちまったコミットを消して直して再pushする場合、pushに「-f」をつけてあげなさい。force pushになるから。

複数の人が触っているブランチでforce pushしたら首がヘシ折れるほどウンコ投げつけられるかもしれないので注意。

▼git revert [commit番号]

いくとこまでいっちゃったコミットを打ち消したいやつ。

あるコミットを打ち消す感じのコミットを生成してくれる。

単にコミットができるので、revertコミットを更にrevertすることもできよう。

AzureDevOpsの画面上でrevertすることもできたり。

▼途中からブランチを切る

git checkout [commit番号] -b feature/ほげほげ

こんなん。

git revertを覚えたらgit revertで変更を打ち消したくなるものだけど、それよりもコミットタイムラインを眺めて「マージする前の状態」から新しくブランチを起こして対応するほうが早いことも多々ある。

よくお前ら「gitはコードの差分をもとに差分を算出している」っていう勘違いしてますが、そういうことではないです。言い換えると「マージ元とマージ先のコードの違い」を起点にして差分の判断をしているわけではない。

差分を判断するための起点はコミット。コミットした日時が新しいものほど優先される。コミットの積み重ねでコードを変更している。

▼git cherry-pick [commit番号]

局所マージ。あるコミットだけをマージできる。いまチェックアウトしているブランチに対して、指定したコミットを混ぜ込む。

リモートにしか存在しないコミットは使えない。事前にfetchとかしておかないと「そんなコミット手元にないよ」とか言われるかも。

▼git stash

変更のせいでチェックアウトできないンゴぉぉぉ!!!でもまだこの変更はコミットしたくないンユ゛ュュュゥゥ!

git stashしろ。先頭を取り出したいときは「git stash pop」でOK。

途中に挟まってるstashを取り出したいときは、取り出し方をググれ。

▼git rebase

コミットログを魔改造するやつ。

整理整頓が好きなのでpush前によく使うが、説明が面倒なのでググれ。ふたつのコミットを混ぜてひとつにできたりするぜ。ログが綺麗になるぜ。でも事故ると割と危ないぜ。

◆CI/CD

git操作をトリガにしてテストやらビルドやらデプロイを自動的に動かすことができる。

ローカルでビルドしたDLLをftpで配置しようとするのをやめろ。手順書を複数人でなぞりながら秘伝の謎シェルスクリプトファイルを実行するのをやめろ。なんかの操作が終わるのを指咥えながら眺め続けるのをやめろ。

令和ぞ。

プルリクマージしたらリリースまでやってくれる世界にしようや。そこまでいかんでも、CI/CDツールに命令するだけで終わる世界にしようや。過去にビルドした資産とか丸わかりだし、過去のリリースを再デプロイとかできるし、リリースからコミット辿れるし、もうこれないと生きていかれない。

AzureDevOpsにはパイプライン/リリースパイプラインが標準搭載されてるから、試せ。

◆結

そんな感じ。言及してないことも沢山あるけども。

あくまで参考情報みたいなもんだから、各案件にあった運用をしていけばいいじゃん。

お前だけの開発フローをその手に掴むんだ。