チーム開発においてGit初心者が踏みがちな地雷まとめ

morimorihogeです。とりあえずE2までクリアしましたが、資源が乏しいです。 弊社ではバージョン管理システムにGitを使っています。 数ヶ月以上一緒にやっているある程度ツーカーなメンバーだけのプロジェクトなら問題無いのですが、案件によっては協力会社の方が一時的にJOINしたり、新規参入メンバーの参加などで、これまでGitを使ったことがない、または本格的なチーム開発でGitを使ったことがない人が参加することもあります。 Gitは自由度の高いシステムですが、その分概念を覚えることが必要なため、導入の敷居が高い方だと思います。そして、仕事で開発をしている場合はどうしても概念の勉強などよりも結果を早く出すことが求められるため、Gitのことをよく理解しないまま間違ったコミットや変更をgit pushしてしまい、リポジトリを壊してしまったり、復旧が面倒なミスをしてしまうことが起こり得ます。 本記事では僕がここ3〜4年ほどまともにGitを使ってチーム開発を続けてきて発生した「やっちゃった」事例を紹介しようと思います。Railsアプリ開発を前提としていますが、Rails以外でも応用は利くと思います。 前提環境(弊社における基本運用方針) GitリポジトリサーバにはGitlabを使っており、ブランチ運用方針は原則git-flowを用いますが、案件によっては社内開発用とお客様確認用環境のブランチを分割して運用したりすることもあるため、厳密にgit-flowとは限りません。 また、masterブランチは本番環境リポジトリになるためGitlabの設定でプロジェクトの責任者以外からはprotectするようにしていますが、そもそも弊社ではプロジェクトの開発チームが1〜3名ということも多いので、protectの意味がないこともあります。merge requestについても同様で、少人数プロジェクトではオーバーヘッドの割に効果は無いと考えているため、基本的には使っていません(プロジェクトによって使っているものもある)。 最後に、masterブランチ、developブランチに対してそれぞれJenkinsで自動テストを回しています。自動テストはテストのcoverageが低くてもrakeタスクが起動しないレベルの破壊的変更程度なら検知できるので、とりあえず設定しておいて損はないと思います。 事例一覧 あるある事例を見ていきましょう。 プロジェクト独自のリポジトリ運用ルールに従わないで作業してしまう 仕事で開発していると、諸々のしがらみやお客様側の特殊な要求条件などの問題から、綺麗にgit-flow(またはその組織が通常採用しているメジャーなリポジトリ運用方式)に乗らないことがままあります。 既に走り出したプロジェクトに後からJOINする場合、必ずそのプロジェクトでのリポジトリ運用方針を確認しましょう。 Git運用は色々なケースが考えられるので一概には言えないのですが、以下の点辺りは確認しておくべきだと思います。 コミットコメントの規則(日本語OK/英語のみ、Redmineなどのチケット番号の記載有無などなど) featureブランチのdevelopへのmergeルール(勝手にmergeしてよい/merge request必須など、rebase派/merge派) プロジェクト独自のルール(developにpushしたらstaging環境にcap deployするなど) 自動テストなど、Git連携するものの把握 git push -fでリモートブランチの過去を改変してしまい、他のメンバがpushもpullもできなくなった 多分一番よくやる奴だと思います。push -fに至るまでの経過は色々なケースが考えられますが、原則他のメンバがcheckoutしている可能性のあるリモートブランチに対してpush -fしてはいけません。 リモートブランチに対してpush -fが許容されるのは多くの場合「自分しか利用していないリモートブランチだけ」です。 push -fはリモートリポジトリに既に公開されている(== 他のメンバも手元にpullしている)コミット履歴を改変してしまうので、他のメンバがpushしたコミットを削除してしまう可能性があります。Gitのエラーメッセージやググったサイトに「push -fすればいいよ」と書いてあっても従ってはいけません。 自分で判断できなければ判断できるプロジェクトメンバに相談するのが一番良いと思います。 git-flowを使った具体的な例で言えば、masterやdevelopはpush -fしてはいけないブランチ、featureブランチは一人で開発している場合、かつdevelopにmergeする前においてのみpush -fしても大丈夫です。 具体的なケースとしては、バックアップがてら毎日の作業途中のfeatureブランチをサーバにpushしておき、最終的なdevelopブランチのmerge前にsquash等でコミット内容を整理したいといったことが挙げられるでしょう。 開発環境に便利だからドットファイルやdatabase.ymlを追加・編集してpushしたらテストサーバが起動しなくなったり、他メンバの環境が動かなくなった 開発に慣れてきた頃にやりがちだと思います。ここで言うドットファイルとは「.ruby-version」や「.gitignore」、「.idea(RubyMineの設定ファイルディレクトリ)」などがあります。 他にもRailsなら「Gemfile.lock」、「db/schema.rb」については原則リポジトリに置くべきファイルですが(hachi8833の記事参照)、運用方針の都合などであえてリポジトリに配置していないこともあるかもしれません。 また、サーバ環境に依存するファイルである「config/database.yml」「config/environments/(production|development).rb」なんかも一開発者の個人判断で編集・追加・削除すると危険です。 この手の環境依存系のファイルを修正する際は、修正する前にプロジェクトメンバに一声かけて、影響がないかどうかを確認した上で修正しましょう。特に、本番環境に詳しい人のチェックはしてもらった方が良いです。 日本語ファイル名のファイルであばばばば Mac-Linux環境間で起こります。Mac環境の人はgit configでcore.precomposeunicodeを有効にしましょう。 $ git config –global core.precomposeunicode true 使い終わったremote branchがサーバ上に残り、branchが増えていく 手動でmerge運用をしていると、mergeし終わったfeatureブランチを消し忘れてしまい、大量のリモートブランチが残ってしまうことがあります。 直ちに問題になることはないと思いますが、リポジトリの見通しを良くするためにも使い終わったbranchは削除しましょう。 $ git branch -d unused_branch $ git push origin :unused_branch まとめ そんなわけでいくつか実際に起こった事例をベースに書いてみました。ここに書いた以外にも色々な事例があるかとは思いますが、どんなケースでも重要なのはチーム開発においては「郷に入っては郷に従え」ということです。 はてブホッテントリに上がってきたりするような記事ばかり追いかけていると最新の環境や思想、ツールが目に入りがちですが、実際の現場では歴史的事情やメンバ(社内外問わず)のスキルレベルの問題から新しいものを使えないこともあります。 より良いとされている方法があっても、チーム開発ではメンバ全体で共有されていなければ開発の障害になってしまうこともあるので、これからチーム開発を始める人は気をつけると良いと思います。 ちなみに個人で開発している場合はここに書いてきたことは当てはまりません。どんどん新しいものを試してノウハウを溜めて、良さそうなものならチームに提案して改善していけると良いですね。 個人的にはGitは細かく見ていくと複雑で人類には早すぎるシステムだと思っています。なるべくイレギュラーなことはしないように、一般的な手順だけをするようにした方が地雷は踏みにくいと思います。