自分の昨今の開発では、ほとんどGit(GitHub)を使っている。今回はそのあたりの情報やポリシーを整理してみた。Gitの話とGitHubの話は多少混ぜている。
触れていること
- コミット(メッセージ/履歴)
- ブランチ(命名/管理)
- マージ
- PR
触れていないこと
- PRテンプレート
- GitHub Actions
- リポジトリとBTS(詳細)
- Slack通知などの情報共有やチーム運営
開発的にはこういったリポジトリ管理より実際のコードや案件の問題に向き合うほうが重要性が高く、このへんはてきとうでいいという考え方もある。わからなくはないし、実際それで回っていることは多い。ただ、微妙なことはあった。
- チーム開発(=1人ではない。もし1人で開発してても、将来引き継ぐ可能性が高い)
- アプリ開発(=ライブラリ等ではない。特に、外部公開はしない)
- デプロイ先は基本的に1つである(=複数バージョンを同時公開する可能性は低い。あったとしても先行試験などで+1つ程度)
- スキルにある程度バラつきがある
- ブランチ名: てきとう
- ターミナルで補完が効けばいい
- それなりに短い期間で削除される前提
- コミットメッセージ: てきとう
- wipとかfixでいい
- マージ: Squash Merge
- タイトルに概要を書き、詳細はPRの説明欄からコピペする
- 情報は可能な限りBTSではなくコード内、コミット履歴、リポジトリ内のドキュメントにまとめる
- ブランチ運用: GitHub Flow
- いいコミットメッセージを書こうという習慣の話がある
- whyをかく、prefixを合わせる、1コミットに1つの意味にする
- 結果としてPRのレビューが楽になる(という主張)
- Semantic Commit Messages
- これはこれでよい心掛けだけども、全部Squash Mergeするなら雑でもいい
- コストをかけない
- コミットが意味をもつ単位でやれるならアリ
- バージョンアップ作業やリファクタリングで、一つずつやることを確実に積み重ねていくような場合
- OSSで開発をしていて、外部に見せるという前提があるのなら、ありかもしれない
- GitHubでサポートされているマージは3種類ある
- Create a merge commit
--no-ff
non-fast-forward
- マージコミットが作成される
- Squash and merge
--squash
- コミットを圧縮して、新しいコミットを作成してマージする
- Rebase and merge
- (使ったことがない)
- Create a merge commit
- 結論として、マージはほとんど Squash Merge でいいのでは?
- 履歴が整理される
- PRの単位でまとまっていればよい
- ほんとに
--no-ff
で履歴を残したい?- 「XXX実装(実際にはいろいろ微妙に足りてない)」「wip」「レビュー反映」「修正」みたいなコミットを残したい?
git blame
で履歴をたどりたい?- PRの単位でよくないか?
- Squash Merge 時のコミットメッセージに情報を残す方が簡潔でよくないか?
- GitHubのPRの変更内容をコピペするのがおすすめ(PRテンプレートを使用する想定)
- 大きめの機能実装ブランチをつくっていて、そこにはSquash Merge, mainにはMerge Commitならわかる
- 例:
main <-(merge commit) feature-big-change <-(squash merge) change-1, change-2, change-3
- ただその場合でも、基本的には「そもそもPRを細かくしてtopic branch を小さくしてそれぞれmainにマージすればいいので、そのブランチ運用自体をやめませんか?」とは思う
- 例:
- バージョン管理システムとして履歴は可能な限り残し、使い手がフィルターするという考え方もある
- 可能な限りすべての情報を残すことで、その人/そのプロジェクトが考えていたことが残る
- 特に長く続くリポジトリにおいて、可能な限り多くのメタ情報が残る方がよいというポリシーもある
- ただ、それらメリットは個人的にはあまり大きく感じない
- 多すぎる情報がノイズになる
- チーム開発で習熟度にバラツキがある環境おいて、Gitの履歴を辿る操作を多くの人は使いこなせない
- なぜか常に開発者1人が触る topic branch の開発で、常に1commitに整理して force-push する行動をみかけることがある
- ローカルで rebaseなり--amendなりでコミットを整理してからpushしているということだけども
- PRでSquash Merge するなら、この作業は不要になる
- コミットを見せたくないという意思の場合、基本的には小出ししにしてもらい、プロジェクトの方針で是正した方がよい
- 「コミットを1つにして履歴を残さないようにしている」ということ自体は致命的な問題にはならないとは思う。そういう意味では放置でもいいのだけど、技術的に変な行動を習慣にしてないか?という意味で、割れ窓的な危うさも感じる。
- mainブランチはforce-pushを防ぐために保護しよう
- ブランチは好きに作成し、好きに消せる
- PRはブランチを削除しても残る
- PRをマージした時に一緒にブランチを削除するとよい
- PRをマージせずクローズしたり、hgリポジトリ移行でゴミとして残りがち
- ブランチが残っていても直接問題にはならないが、デッドコードや閉じられてないチケットのように、情報が整理できていないという信号になってはいる
- ブランチの名前はそもそもなんでもよい。てきとうでもいい
feature/xxx
hotfix/xxx
というprefixをつけるパターンがあるが- これは元々git-flowというブランチモデルがあったときの名残
- GUIクライアントなどではディレクトリ風に表示してくれたりもするが、使わないことも多いので不要では
- Redmineのチケット (例:
t100111
など)をつけるパターンがあるが- コミットメッセージに
refs #100111
など
- コミットメッセージに
- これは元々hg(Mercurial)かつRedmine連携があったときの名残
- いまはGitHubを使用しているので、洗練された使いやすいWebUIがある
- コミットも個別にWebUIで見れるし、PRやIssueに簡単に紐付けられる
- なので、いまはこの命名規則を使う理由が減っている
- ターミナルでの補完のことを考えると、てきとうに開発中の内容を書くの方がわかりやすい
<sprint-number>-<some_feature>
という命名もまあまあ悪くなかった- とはいえ最終的にはブランチは削除するのが基本とすると、やはりてきとうでもよい
- GitHubでは
BPR-100111
みたいにPrefixを設定することで、外部のBTSなどにリンクを作成できる #100111
などは、GitHubのリンクになる- そのため、
#100111
はGitHubのリソースを示し、Redmine/Jira/BacklogなどはPrefixを使用すべき- 過去の名残や習慣かなにかで、外のBTSのリンクを
#10011
のように記載していることがある。これはただの形骸化なので、やめるべき- これが対応できないのは、技術というよりは、チームの運用の問題にみえる
- 過去の名残や習慣かなにかで、外のBTSのリンクを
- Git-Flow: (main - develop - topic) + hotfix
- GitHub-Flow: main - topic
- かつては Git-Flow でちゃんとやろう的な風潮もあったが、アプリ開発としてはGitHub-Flow で十分
- ブランチが多段になって扱いが難しくなりコンフリクトが発生する可能性が上がる
- GitFlowをまともに運用するなら、コミットが独立していないと意味がない
- OSSのライブラリのプロダクト等で複数(パッチ)バージョンが存在するならよいかもしれないが
- hotfixはmainから生やした使い捨てブランチでよいのでは
- リリースはmainから生やしたtagでよいのでは
- 直接mainブランチ指定でもよい
- お客様の運用的にGitFlowから変えられないこともあるが、可能な限りはGitHub-Flowを推奨してなるべく変えてもらう
- Git-Flowにした場合でも、mainブランチへのマージがただの儀式になってる
- 同じ儀式ならtag発行の方がまだ気が楽
- 開発で触るコード(リポジトリ)に対して、BTSの情報は遠いという感覚がある
- 1クリックかかるというのもあるし、BTSのチケットやwikiの情報は実情として雑多なメモだったりして、整理されてないこともある
- 整理されていない生の情報でも流しつつ作業する、という意味ではBTSの意義はあるのだけど
- 1クリックかかるというのもあるし、BTSのチケットやwikiの情報は実情として雑多なメモだったりして、整理されてないこともある
- コード(リポジトリ)は残るが、BTSは消えることがある
- なので、なるべくBTSよりリポジトリに集約したいという気持ちはあったが
- まあBTSが参照できなくなるような状況になっている時点で、会社ごと変わってリプレイスしたりとかなので、そういう意味ではなにをどうしようが手遅れではある
- 1つのプロジェクトに対して複数のリポジトリを持つ場合、情報をBTSに集約したいという話
- それはわかる
- そもそもリポジトリを分割しすぎない方がよいとは思うが(モノレポ)