■はじめに
この投稿は私が所属するプログラミングコミュニティの勉強会のために作成しました。
Qiita読者の皆さんにもお役に立てれば幸いです。
読み物として読む場合は、途中のハンズオンは飛ばしてください。
対象者
- ソースコードのバージョン管理の概念と重要性は理解している
- 実際にローカルリポジトリにcommit、リモートリポジトリにpushはしたことがある
- チーム開発で円滑にソースコードを共有する方法を模索している
- コンソール画面やLinuxコマンドには不慣れ
目的
リモートワークでも円滑なチーム開発ができるようになること。
手段
- Gitのコマンドを知る
- Microsoft Visual Studio Code(VSCode)でGitを使う
- GitHubで小規模なチーム開発の流れをハンズオンでやってみる
前準備
- Gitが端末にインストールされている
- VSCodeが端末にインストールされている
- 以下の拡張機能が入った状態
- Japanese Language Pack for Visual Studio Code
- Git Graph
- Git Lens
- Git History
- 以下の拡張機能が入った状態
- GitHubのアカウントがある
心構え
- コンソールコマンドが不慣れな人はより慎重に!
- 何かがおかしくても、GitやGitHubが言ってくる英語のエラーコードを頑張って読もう!
- お互いに教えあって進めていこう!
筆者について
GitおよびGitHubは独学となります。
業務ではSVNでバージョン管理を経験しました。
SVNでは個人で好き勝手にリポジトリを持てないため細かい単位でのコミットの運用というのができませんでした。そこで独自にgitでバージョンを管理し、本番のSVNにコミットするときはgit-svnという機能を仲介して履歴は保ったまま、疑似分散開発っぽいことを挑戦したことはあります。ただ何かと苦しみを伴ったため途中でやめた記憶があります。
CUIかGUIか
gitをCUIで使うか、GUIで使うかは、バージョンを管理するという目的を達成できるならばどちらでもいいと考えています。
ただし、他の人と会話する際にコマンド名とそれが何を意味するのか、そしてそれが自分が使用するGUIのどの操作に当てはまるのかを抑えておくとスムーズに会話ができると考えます。CUIを使わないにしても、両者の共通言語としてコマンド名がすぐに思い出せる状態にしておくことは重要と考えています。
よって、この記事では、コマンドとその意味、そしてVSCodeでそれを実現する方法という流れで記載します。
VSCode拡張以外にもGUIで使う方法はたくさんあります。自分の手に馴染むものを探してみるのもいいですね。
- SourceTree https://www.sourcetreeapp.com
- GitKraken https://www.gitkraken.com
■Gitとはなにか
説明を行う上で、どうしても説明が前後してしまう単語がありますが、分からない単語も後から出てくるものとして読み進めてください。
また、ここでは本当に概要しか説明していません。ここでの学習を起点に自分なりに調べるなどして理解を深めてください。
コミットとバージョン
ローカルリポジトリにおける変更を確定し、バージョン管理上に乗せることをコミットといいます。
コミットを行うと一つのコミットに対して数字の羅列のような値(ハッシュ値)が割り振られます。これがGitにおけるバージョンです。
コミットしておけば、後からそのバージョンに戻すことも容易です。機能追加していたらいつの間にか動かなくなってしまい、もとにも戻せなくなった。そんな経験はないでしょうか。開発中は区切りのいい単位でコミットを行う癖をつけましょう。
ローカルリポジトリとリモートリポジトリ
Gitは分散型バージョン管理システムです。
なぜ分散型と呼ばれるかというと、共有リポジトリの他に自分自身しか触らないリポジトリを持つことができるからです。
共有リポジトリをリモートリポジトリ、自分自身しか触らないリポジトリをローカルリポジトリといいます。
前述したコミットはローカルリポジトリに対して変更を確定するものでした。
この状態では自分の端末が壊れた際にローカルリポジトリも一緒になくなってしまいます。
リモートリポジトリ(GitHub)にローカルリポジトリの内容をpushすることでそのような事故にも備えることが可能です。
また自分の端末の外側にリポジトリがあるということは、複数人が同じリポジトリを参照して共同開発する環境が作りやすいことを意味します。これを応用したものがGitHubによるチーム開発です。
ディスカッション(ハンズオン)
具体的な説明に入る前に、現段階の知識で良いので、Gitを使っててよかったという体験談や、Gitを使ってなかったせいでこのようなことが起きた、Gitってまだよく分からないけど、こういう困ったこと解決できますか、などをディスカッションしてみましょう。
次からは具体的なgitコマンドを元に解説を進めます。
■Gitコマンド
Gitで行うこと、簡単な説明、Gitコマンド、VSCodeでのやり方の順番で説明します。
今回の学習は、あくまで知識の足がかりと考えて、詳細は自身で調べることをお願いします。
コミット対象候補にする(ステージング)
なぜステージングという考えが必要なのでしょうか。
例えば10ファイル編集中に、10ファイルすべてを一度にコミットせず、分割してコミットしたほうが、後からログをたどる際に分かりやすいシーンがあると思います。
これを実現しやすくする考えがステージングです。
コマンド
git add
VS Code
プラスボタンを押すことでステージングが可能です
ローカルリポジトリにコミットする
コミットという操作はローカルリポジトリのバージョンを上げる行為です。
あくまで自分の端末内だけの更新であるため、GitHub上には登録されないので注意してください。
コマンド
git commit
VS Code
フォームにコメントを入力後、⌘+Enter(Ctl+Enter)を押すことでコミット可能です。
最新の変更を取り込む
GitHub上の最新の変更を、自分のローカルリポジトリに取り込みます。
コマンド
git pull
VS Code
ソース管理と書かれている場所の右端にあるメニューからプルを選択します。
ローカルリポジトリの作成
説明は割愛します。
最初のうちは、GitHubでリモートリポジトリを作り、それをクローンしてローカルリポジトリを作るというやり方がわかりやすくていいと思います。
コマンド
git init
VS Code
VSCodeからinitができるかはわかりません。
リモートリポジトリのコピーを作成する
GitHub上のリモートリポジトリのコピーをローカルリポジトリとして作成します。
コマンド
git clone
VS Code
cloneもVSCodeから可能なようですが使ったことはありません。
GitHubでリモートリポジトリを作成した後、ローカルリポジトリを構成するために指定されるコマンドがあるので、そこまではコマンドラインでやるほうが楽だと思います。
もちろんVSCodeから単に既存のリモートリポジトリをcloneするだけならお手軽に使えると思いますが、その場合も自分がどのディレクトリにいるかはちゃんと意識する必要があるので注意してください。
ローカルリポジトリの変更状況の確認
コマンド
git status
VS Code
青枠で囲まれた部分がgit statusと同等の情報を出しています。
ローカルリポジトリの変更差分の確認
コマンド
git diff
VS Code
ソース管理タブでファイル名をクリックすると変更差分の確認ができます。
今は新規ファイルなので全部が変更差分として表示されています。
変更履歴の確認
コマンド
git log
VS Code
VSCodeの拡張機能を使います。
左がGitLens、真ん中がGitGraph、右がGitHistoryです。
好みのものを使いましょう。
拡張機能なしでもログを確認可能ですが、拡張機能が何かと便利なのでほぼ出番はないと思います。
ファイルの削除
コマンド
git rm
VS Code
VSCode上から削除すればよしなにやってくれるのか、調査中です。
ファイルの移動
コマンド
git mv
VS Code
VSCode上からリネームや移動すればよしなにやってくれるのか、調査中です。
リモートリポジトリの登録
コマンド
git remote add origin https://github.com/user/repo.git(例)
このコマンドは origin という名前で https://github.com/user/repo.git(例) というリモートリポジトリをローカルリポジトリに設定するという意味です。GitHubからリポジトリを作成している際はすでに実行済みのコマンドだと思います。
VS Code
やり方調査中です。
リモートリポジトリにローカルリポジトリの変更をアップロードする
git commitしただけではGitHubにアップロードされていません。git pushしましょう。
コマンド
git push <リモート名> <ブランチ名>
VS Code
バージョン管理の対象から外す
詳細は割愛しますが.gitignoreファイルを編集することで実現します。
なぜバージョン管理の対象から外すという概念が必要なのでしょうか。
例えばパスワードが書かれたファイルはバージョン管理すべきではありません。
OS独自の隠しファイルなどは別のユーザにとっては不要なファイルです。
そのようなファイルを除外するときに.gitignoreファイルを使います。
変更を元に戻す
コマンド
git checkout -- <ファイル名>
VS Code
プラスアイコンの左の矢印が戻っているアイコンをクリックします。
ステージングしたファイルをもとに戻す
コマンド
git reset HEAD <ファイル名>
VS Code
間違ってコミットしてしまった
コミットそのものを取り消すという手段もあるようですが、最初のうちは、素直に正しいファイルでもう一度コミットするほうががわかりやすいと思います。
リモートリポジトリを表示
コマンド
git remote
VS Code
拡張機能GitLensの機能でリモートリポジトリを確認可能です。
新しいブランチを作成する
コマンド
git branch <ブランチ名>
VS Code
VSCodeの左下の枝分かれしたアイコンの場所をクリックすると、ブランチを選択するフォームが開きます。
ここで新しい分岐の作成をすると新しいブランチが作成できます。
ここで設定するブランチ名は適当なものですが、ブランチ名はそのブランチで何をやるかわかり易い名前にしましょう。
現在のブランチを確認する
コマンド
git branch
VS Code
左下の枝分かれしたアイコンの場所の文字が現在のブランチです。
ブランチを切り替える
コマンド
git checkout <既存ブランチ名>
VS Code
ブランチを作成するとVSCodeの左下の枝分かれしたアイコンの場所の文字が作成したブランチ名になっています。これは新しく作成したブランチに移動したことを意味しています。
もう一度左下をクリックすると、もともといたブランチ(master)と新しく作成したブランチが選べるようになっています。もともといたブランチに切り替えたいときはクリックすることで切り替えることができます。
ブランチを作成して切り替える
コマンド
git checkout -b <新規ブランチ名>
VS Code
VSコードではブランチを作成して切り替える動作がデフォルトの動作のようです。
ブランチを今いるブランチにマージする
2回目のコミットのmasterブランチからdev_branch_1を切り出しました。この状態からmasterブランチに3回目のコミットを行いました。
この状態は、dev_branch_1がmasterブランチよりも古いということです。
どういうときに、このようなことが起きるでしょうか。
これはチーム開発の際に、別のチームメンバが自分よりも先に機能をmergeした際に起きます。このようなときにmasterの最新の機能を自分のbranchに取り込みたいというシーンが出てきます。
また、同一ファイルのバージョンが自分のブランチよりも進んでいた際、masterの最新を取り込むことが必須となる(自分のブランチをmasterにmergeできない)ことがあります。
このように、チーム開発では、現状の最新を取り込むという行動が重要になってきますので慣れていきましょう。
なお、ここではマージを紹介しますが、場合によってはリベース(ブランチの切り出しポイントを先にずらす)やプル(リモートリポジトリをfetchしてmerge)という方法もあります。
おそらく、ブランチ開発の第一関門はここではないかと考えています。コンフリクトやエラーが起きて当たり前と考えて、GitやGitHubのメッセージをよく読み、どのような対処が必要か判断できるようになりましょう。
素直にマージできない理由は大きく2つだと思います。
- あるファイルのバージョンに対して古いバージョンのファイルをマージしようとしている
- マージ先のブランチの変更をマージ元に取り込んでから再度マージを行います
- また、このマージ元に取り込む際にコンフリクトが発生することがありますが、あわてずに
- バージョンに問題はないが、マージ元とマージ先で同じファイルの同じ場所を編集している
- 後述するコンフリクト解消作業を行います
おそらく文章だけでは難しいので後ほど実際に動かしてみて試しましょう。
コマンド
git merge <ブランチ名>
VS Code
dev_branch_1に対してmasterをマージするという選択をしました
今回、dev_branch_1は切り出してから何も変更していなかったため、fast-forwardマージが行われました。
fast-forwardマージとは何でしょうか。マージの種類については以下などを参考にしてください。
https://backlog.com/ja/git-tutorial/stepup/04/
コンフリクトを解消する
ブランチをマージする際、マージ元ファイルとマージ先ファイルの同じ行に変更があった場合、gitはどちらの変更を採用すべきかの判断をユーザに委ねます。だいたい以下のような感じになっています。<<や==や>>はどこからどこまでがどの変更可を表す記号のため、コンフリクト解消作業ではこの記号を消しましょう。また、自分の変更とマージ元の変更の関係性を調査して、どちらを残すのか、両方残すのかを判断しましょう。
<<<<
自分の変更
====
マージ元の変更
>>>>
編集が終わったら git statusで状態を確認します。
コンフリクトが解決していたら、git add / git commitでコンフリクト解消作業は終了です。
一時的に変更を退避する
一時退避とは何でしょうか。ある機能を開発中にコミットするまでに至っていないがブランチを切り替えたいシーンがあります。このときに一時退避機能を利用します。一時退避を使用せずにブランチを切り変えるとブランチ変更前のファイルに対する変更がブランチ切り替え先に引き継がれることになるようです。
コマンド
git stash
VS Code
ここまで学習した機能を使いまくってみよう(ハンズオン)
プログラミングと同じで、Gitを理解するのは、いかに量をこなすかだと思います。学習した機能を使ってどのようなことが起きるのか何度も試してみてください。慣れてきたら、コマンドの方を試すのもおすすめです。
■ブランチモデル
ブランチをどのように分けて開発していくかは、プロジェクトにより様々な考え方があります。いちばん重要なことは、プロジェクト内でルールを決めて全員がそれに従うことです。どんなに素晴らしいやり方を考案しても、ルール通りに皆が動けなければ意味がありません。ネットでよく見かけるキーワードはGit flow と GitHub flowだと思います。
Git flow
(参照: https://nvie.com/posts/a-successful-git-branching-model/ )
GitHub flow
ものすごく単純に説明すると、Git flowの図のmasterとfeatureだけで運用している感じ。
■ディスカッション(ハンズオン)
世の中にプロダクトの完成版をリリースつつ、顧客に次のバージョンアップ版を評価(試験など)をしてもらいつつ、更に次の開発を続けるというシーンを想像して、どのようにすれば円滑に開発が進むか、ブランチを考えてみましょう。正解は一つではありません。
次の模擬チーム開発でも運用できるか、チームで運用するにはどのような工夫、事前準備が必要か、実際に運用するときはどのようなコミニュケーションが必要かまで考えられるとなおいいです。
■GitHubによるリモートチーム開発(ハンズオン)
ここからはGitHubによるチーム開発の説明をします。
チームのリポジトリの作成とメンバの招待
organizationアカウントの作成
個人アカウントに誰かを招待することでチーム開発は可能です。しかし、チーム開発なのに個人のアカウント配下に人を集めるというのが若干違和感を感じませんか。私は感じました。GitHubにはorganizationアカウントという組織で使うアカウントが用意されているので、それを使ってみましょう。
Create organizationsをクリック
Freeプランを選ぶ
Organization account nameを入力し、My Personal accountを選ぶ
ここでメンバを招待できますが後からできるのでこのままComplet setup
organizationアカウントが完成しました。
Create a new repositoryでリモートリポジトリが作成できます。
リモートリポジトリを作成します
ここからは個人アカウントのリモートリポジトリと同じです。
骨組みのコードをアップロード
チーム開発といってもファイルがゼロの状態から全員が一斉にコードを書き始めるのは困難です。まずは骨組みのコードを代表者がpushするのがいいと思います。
Hello World的な突貫で作ったファイルを数個でも構いませんし、既存の自作プログラムでも構いません。ただ、今回は練習なのでシンプルで動作確認しやすいものが適しています(複雑すぎると練習として気軽に手を加えることが難しいため)。
issueの作成
プロジェクトを達成するためにやらなければいけないことをissueに挙げましょう。
今回は練習なので内容は気にせず、issueを発行したらお互いにどのような見え方になるのか、どういう情報が記載できるのか、どういう情報が記載されていると他のメンバにもわかりやすいかなどを考えてみましょう。
issueタブでNew issueボタンを押下します。
issueの内容を記載し Submit new issue を押下します。
projectの作成
今どのようなissueがあり、だれがどのissueに取り組んでいるかを見えるようにしたものが、projectです。同じようなことを実現するツールはasanaやtrelloなどがありますが、今回はGitHubのprojectを使ってみましょう。
Projectsタブから Create a project を押下します。
Templateを選択します。複数のテンプレートがありますが、自分たちのチームのやり方に合うのを選ぶと良いでしょう。
例ではAutomated kanban with reviewsを選んだのでカラムが5つできました。
右端にissueがあることが分かります。
このissueはドラックアンドドロップでカラムに移動することができます。
アイコンが!マークになってissue担ったことが分かります。
拡張機能ZenHubの紹介
ZenHubはGitHubのProjectを更に高機能にしたもので無料で使えます。Crome拡張機能です。
チーム開発を管理する際のサービスはtrelloやasanaなどがあります。ZenHubも選択しに入れてみてはいかがでしょうか。
このようにガントチャートっぽい見え方ができたり、その他分析用のグラフなどが豊富にあります。
プルリクエスト
プルリクエストは、自分の変更をリポジトリに取り込んでもらえるよう依頼する行為です。
レビュアーを選択し、レビューを受ける起点にもなります。
ブランチをpushすると自動的に Compare & pull request というボタンが出現するので押下します。
レビュアーを指定し、Create pull request ボタンを押下します。これでプルリクエスト完了です。
レビューとコメント
プルリクエストを受けたレビュアーは対象のファイルをレビューし、適宜GitHubのコメントでやり取りを行いましょう。やり取りが完了したらレビュー完了です。レビュアーの全員がレビュー完了したらマージを行います。
ソースコード中のプラスボタンでコメントを入れることができます。
コメントを入れると以下のようなスレッドが作られます。どのようなやり取りが行われたか分かりやすいですね。
例の画像は本人のためApproveができませんが、レビュアーはレビューが終わって問題なければApproveを選択します。
マージ
もしかしたら、コンフリクトを起こしていてマージできないかもしれません。コンフリクトの解消は、プルリクエストを行った本人が行うのが最もわかりやすいと思います。コンフリクトを起こしていたら、レビュー依頼前に解消して、再度プルリクエストを出すようにしましょう。
コンフリクトが起きていなければ Merge pull requestボタンを押下
マージコメントを入力しconfirm mergeでマージ完了です。
マージが終わればブランチを削除しても良いでしょう。削除しなくても問題はありませんがたくさん溜まってくると消したくなります。
masterのファイルを確認すると、無事マージされていることが確認できました。
デプロイ
ホスティングサービスは色々ありますが、今回はvercelを使ってみます。vercelはReactのフレームワークのNext.jsを作っている会社が運営するホスティングサービスで、Next.jsと一緒に使うと何かと便利です。
githubのアカウントがあればログイン可能です。
vercelとGitHubを連携すると、自動的にデプロイが可能になるほか、プルリクエスト契機にも暫定的なデプロイをしてくれます。これにより、レビューの際に実際の動作を確認しながらレビューが可能です。
■疑似リモートワークしてみよう(ハンズオン)
チームでルール作り、コミニュケーション手段の確立を行い、疑似リモートワークしてみよう。
相手が常に応答できるとは限らない非同期コミニュケーションと、相手の即レスポンスが可能な同期コミュニケーションをうまく使いこなそう。
■終わりに
資料は読みやすいように今後ブラッシュアップしていきます。
以上です。