GitとGitHubを分かりやすく! 組織開発で生かすツール選択とプロジェクト進行を解説
分散型バージョン管理システムのGitと、そのホスティングサービスとしてプルリクエストなどの機能をもつGitHubは、ソフトウェア開発環境として広く普及しています。本記事ではGitやGitHubの考え方や使い方の基本を解説するとともに、実際のプロジェクトにおける開発の進め方を簡単に紹介します。
この記事を読み始めているということは、GitやGitHubに興味をお持ちのことでしょう。Gitはバージョン管理システム、GitHubはGitのホスティングサービスで、いずれもソフトウェア開発を中心に利用されています。近年では、2018年にGitHubの運営会社がMicrosoft社によって買収されたことでも話題になりました。
この記事では、GitやGitHubの基本的な使い方や考え方を解説します。また、実際の開発プロジェクトでの実践的な利用についてもひと通りの進行を例示します。最後に、応用的ないくつか新しい動きやアイデアを紹介しています。GitおよびGitHubの導入にお役立てください。
- GitとGitHubが注目される理由とは?
- 組織開発におけるGitHubの利用形態
- GitとGitHubを利用できる環境を整える
- Gitの第一歩: リポジトリの作成と新規ファイルの追加
- GitHubを中心としたプロジェクト進行
- GitHubをもっと活用しよう!
GitとGitHubが注目される理由とは?
GitとGitHubは、さまざまな開発現場で使われています。例えば、OSS(オープンソースソフトウェア)開発です。OSSとは、ソースコードを公開した状態で開発されるソフトウェアのことで、商用ソフトウェアの多くが何らかの形でOSSに依存していると言われています。OSS開発ではGit/GitHubが欠かせない存在となっており、近年のソフトウェア開発を根底から支えているといっても過言ではありません。
また、特にアジャイル開発のようなスピード性が求められる開発手法で広く活用されていますが、運用の柔軟性が高いため規模の大小を問わずさまざまな開発手法に適合しやすく、利用者がますます増加することも予想されます。
このような潮流において、MicrosoftによるGitHubの買収はまさに必然の出来事だったと言えるかもしれません。GitHubには新たな機能が続々と追加されており、ソフトウェア開発で最も広く利用されるバージョン管理システム体系として、重要性を高めています。
バージョン管理システムとは
Git/GitHubが最近よく使われるシステムだということはお分かりいただけたと思いますが、そもそもバージョン管理とはいったい何なのでしょうか。
ソフトウェア開発で新しい機能を追加したりバグを修正したりすると、プログラムのソースコードにさまざまな変更が加えられます。その際に、以前の実装に戻したくなったり、どの時点でバグが混入してしまったか調べたりするため、変更履歴(だれが、いつ、どのように変更したか)を残しておく必要があります。
変更履歴を残す最も単純な方法は、変更のたびにバックアップを別のファイル名で保存して残していくことです。しかし、ファイル名の命名規則がなかなか守られなかったりして、変更ごとに増えていくたくさんのバックアップをきちんと管理することは困難です。バージョン管理システムは、そうした変更履歴の管理を効率よく確実に行ってくれるものです。
バージョン管理の基本概念
一般的なバージョン管理システムでは、「いつ誰がどんな変更を加えたか」といった情報を記録できます。これらの記録をリポジトリ(変更履歴などを貯めておく保管場所)に追加することをコミットといい、コミットを積み重ねて(つなげて)履歴を残していきます。これにより、いつどんな変更を行ったのかを特定したり、指定したコミットの状態に戻したりできます。
またコミットの流れを分岐させて、作業を並行して行うこともできます。この枝分かれしたコミットの流れのことをブランチといいます。本流となるブランチをメインブランチなどと呼び、そこから枝分かれして開発ブランチやバグ修正ブランチなどを作成することがあります。
バージョン管理システムには、大きく分けて2つのタイプがあります。それは、集中型と分散型です。何を集中あるいは分散させるかというと、リポジトリです。
集中型バージョン管理システム
集中型の場合、リポジトリをサーバーに設置しておき、各人が作業を行ったらサーバー上のリポジトリに対してコミットを行います。特定のコミットの状態が必要なときには、サーバー上のリポジトリからダウンロード(チェックアウト、アップデート)します。ローカルで扱うファイルは、チェックアウトした分だけになります。
分散型バージョン管理システム
それに対して分散型の場合、リモートにあるリポジトリを各開発者ごとにクローン(複製)し、各人のローカルのリポジトリにコミットを行います。
修正した内容をリモートリポジトリに反映させるには、ローカルリポジトリをプッシュし、リモートリポジトリにマージします。他の人によってリモートリポジトリの状態が変更されていた場合は、リモートリポジトリからプルすることで、ローカルリポジトリに変更を反映できます。
Gitは、この分散型バージョン管理システムに分類されます。
GitとGitHubの違い
GitとGitHubは混同されがちですが、両者は全く異なるものです。
Gitはバージョン管理システムの本体です。ローカルで行った作業のコミットにはGitを使用します。つまり、Gitを使うには、自分のコンピュータにGitというソフトウェアをインストールする必要があります。
それに対してGitHubは、Gitのホスティングサービスの1つです。Gitのリモートリポジトリを管理する役割のほか、プルリクエスト(pull request)やイシュー(issue)といった複数人で開発するためのコミュニケーション機能や、たくさんの開発補助機能を提供しています。GitHubは主にWebブラウザから操作します。
ソフトウェア開発以外でも利用できる
Gitで管理できるのは、プログラムのソースコードだけではありません。ソースコードのようなテキストファイルであれば、Gitで管理できます。例えばMarkdown形式で記述された仕様書や議事録、論文や記事の執筆原稿をGitで管理しているという話はよく聞きます。論文のように複数人で共同執筆する際には、あわせてGitHubを使うことでコミュニケーションも円滑になり、作業がより効率的になります。
ただし、バイナリファイル(ExcelやWord、動画や画像など)はバージョン管理できません。正確には、ファイルごとの追加や削除といった変更は記録として残せますが、変更内容は管理の対象外となります。
Git/GitHubの優位性
GitやGitHubでできることについてはお分かりいただけたと思いますが、他のバージョン管理システムに比べてどんなところが優れているのでしょうか?
もちろんGitやGitHubにもデメリットはあります。例えば集中型のシステムに比べると、覚える手順や概念などが多いため、学習コストを要する傾向があります。またリポジトリを丸ごとローカルに持つため、規模が大きくなると手元で扱うファイルサイズも大きくなりがちです。
しかし、こうしたデメリットを考慮しても、GitとGitHubの組み合わせには次のような優位性があります。
オフラインで作業が可能
集中型のバージョン管理システムではリポジトリがサーバー上にあるため、コミットするにはオンライン状態でなければなりません。
Gitはリポジトリをローカルに持っているため、オフラインでも作業を継続し、コミットすることができます。
ブランチの作成が容易
集中型でも、機能開発ブランチやリリースブランチなどを作成することはありますが、個々人の作業用にブランチを作成することはありません。リモートにあるブランチに対してコミットすることになるので、他に影響を与えないよう注意しながら作業する必要があります。
一方、Gitはリポジトリを各自で持つことにより、ブランチの作成が容易になり、本流ブランチに与える影響を考えずに作業を継続できます。
コミットのタイミングの自由度が高い
集中型の場合は、他に影響を与えないようにコミットする必要があるため、コミットするまでに変更が溜まってしまいがちです。
その点、Gitでは、各コミットによって生じる他への影響を考えずにコミットできるので、作業の意味ごとにコミットを分割することができます。これにより変更の流れが追いやすくなり、バグが混入した時期や箇所の特定がしやすくなります。
GitHubによって補強される機能
こういったGitの特徴から広く利用されていることがうかがえますが、さらに大きな理由としてGitHubの存在は外せません。Gitの持つ優れた特徴をGitHubが補強したことによって、多くの開発現場に普及しました。
GitHubにはプルリクエストという機能があります。これを使用すると、マージする前に変更内容を自分以外の誰かにレビューしてもらえます。マージ作業まで1人で行うとバグを見落としたり、変更の正しさを必ずしも十分に確認できないことがあります。プルリクエストは、バグの混入を防ぐために有効な機能です。
ほかにも、プロジェクトに関わる問題を投稿して作業者をアサインするイシュー機能や、プロジェクトに関する情報をまとめるWiki機能など、開発に必要な情報を集約する機能が豊富にあります。
トラブル対策などの情報が豊富に得られる
最後に見落としがちな点ですが、GitとGitHubはとても普及しているため、情報が豊富にあります。操作で何か困ったことがあったとしても、Web上には似たような問題に対処した人が残した情報がたくさん転がっています。問題解決方法が簡単に見つかることは、利用していく上で非常に重要なことです。
組織開発におけるGitHubの利用形態
バージョン管理システムを利用するにあたって、チーム内での運用方法を決めておく必要があります。本章では、GitやGitHubでよく使われるワークフローについて解説し、GitとGitHubの導入方法まで紹介します。
適切なワークフローを選択する
Gitを使い始める前に、リポジトリの管理方法であるワークフローについて簡単に紹介します。Gitのワークフローはいくつか提唱されていますが、ここではその中でも有名な2つを紹介します。プロジェクトの規模や作業の単位などによって、どのようなワークフローを採用するのが良いのか考えましょう。
Git-flow
1つ目は、Git-flowです。デスクトップアプリケーションのように、特定のバージョンごとにリリースするプロジェクトで利用されます。急なバグ修正用や機能開発用などで作成するブランチのルールが、比較的厳密に決められています。複数のブランチが常に並行して動くことになるので、運用もやや複雑です。
このフローは「A successful Git branching model」というブログ記事で提唱されました。次の図はこのブログの図をもとに、時系列を横にして英語の表記を日本語にあらためたものです。
GitHub Flow
もう1つは、GitHub Flowです。WebサイトやWebアプリケーションのように、デプロイが頻繁に発生するプロジェクトで利用されます。どんな作業でも、本流となるブランチからトピックブランチと呼ばれる作業用ブランチを作成し、そこで個々の作業を行います。
トピックブランチをマージするにはプルリクエストを利用し、レビュアーからのレビューを受ける必要があります。また本流ブランチはいつでもデプロイ可能な状態にしなければなりません。
どちらのワークフローも、必ずしも提唱されたルールに厳密に従う必要はありません。現場の規模や環境に合わせてルールをアレンジし、最適な運用方法を採用するのが望ましいでしょう。
GitとGitHubを利用できる環境を整える
ここまでGitとGitHubがどういったもので、どのように利用していくかを見てきました。概要が理解できたところで、実際に使えるように自分の環境に導入してみましょう。プラットフォーム(OS)として、WindowsとMac(macOS)を対象とします。
Gitのインストール
まず、Gitをインストールします。下記のWebページにアクセスし、各自のプラットフォームのリンクをたどると導入方法が説明されています。
Windowsでは、環境にあったインストーラーをダウンロードして、実行すればよいでしょう。
Macの場合は、開発環境(Xcode)を入れていれば、標準でGitもインストールされています。最新版を利用したい場合には、リンク先の「Binary installer」からインストーラーをダウンロードしたり、Homebrewを入れていればターミナルから次のようにインストールできます。
$ brew install git
端末を開いてインストールを確認
インストールが完了したら、Gitのコマンドを実行してみます。Windowsでは、Gitに同梱されているGit Bashを開いてください。Macではターミナルを開きます。以降、どちらも単に「端末」と呼びます。
Git Bashを初めて利用する場合、Windowsの「スタートメニュー」→「全てのアプリ」→「Git」と選択してください。Macのターミナルは、Launchpadを開いて「ターミナル」を検索すると見つかります。
端末を開いたら、次のように打ち込んで($は入力する必要ありません)Enterキーを押してください。
$ git --version
インストールが成功していれば、入力した次の行にGitのバージョン番号が表示されるはずです。
git version 2.34.1.windows.1
GitHubアカウントの作成
次に、GitHubでアカウントを作成します。次のWebページにアクセスし、右上の「Sign up」をクリックしてください。
メールアドレスの入力、パスワードやユーザー名の指定など、求められる項目で順に「Continue」ボタンを押していき、最後に「Create account」ボタンをクリックします。認証画面に遷移するので、最初に入力したメールアドレスに送られてきたパスコードを入力します。
あとはアカウントに関する質問が続き、自分が使用する環境に合わせて項目を選択して完了させます。プランの選択画面では、ひとまず本記事のレベルであれば「Free(無料)」でかまわないでしょう。
SSHで接続できるように設定
GitのコマンドラインとGitHubとのファイルのやりとりでは、SSHを使用すると便利です。そのため、ローカルでSSHキーを作成し、公開鍵をGitHub上に登録しておく必要があります。具体的な方法はGitHubの公式ドキュメントに解説されているので参照してください。
▶ 新しい SSH キーを生成して ssh-agent に追加する - GitHub Docs
また、本サイトに掲載している「今日からはじめるGitHub」という記事でも「環境の構築(2) SSHの鍵を取得する」から「環境の構築(3) GitHubのアカウントを作成する」で解説しています。
GUIのアプリケーションツールもある
Git/GitHubを利用できるクライアントツールはたくさんあります。自分の経験や現場の環境に合わせて適切にツールを選択することで、開発効率が高まるでしょう。
先ほどインストールしたGitに付属するgit
コマンドは、基本的なCLI(Command Line Interface)のツールで、端末からコマンドを打ち込んで操作します。ある程度はコマンドを覚えておく必要があり、慣れないうちはハードルが少し高く感じるかもしれません。
そのほかに、画面をクリックして操作するGUI(Graphical User Interface)のアプリケーションも利用できます。感覚的に扱いやすく、ブランチの情報などが視覚的に表示されて状況を把握しやすいことがメリットです。一方で、利用できる機能がよく使う操作に絞られていることもあります。
代表的なGUIアプリケーションにはGitHubが公式で配布するGitHub Desktopや、SourceTreeなどがGit公式サイトの「GUI Clients」で紹介されています。
また、開発者向けテキストエディターの定番であるVisual Studio Codeには、Git GraphなどGit関連の拡張機能があります。
結局はコマンドラインで操作して学ぶ
このようにGUIアプリケーションもありますが、最も基本的なGitのツールは、コマンドライン(CLI)のgit
コマンドです。数多くのオプションが用意されており、きめ細かな操作をしたいときに使い勝手が良いです。また、一度慣れてしまえば操作が格段に早くなるメリットもあります。
前述のようにWindowsならGitBash、Macならターミナルから操作します。
以上を踏まえると、経験の浅いうちはGUIアプリケーションをメインに使用し、必要に応じてCLIアプリケーションを補助的に利用するとよさそうに思えます。しかし、Git操作の基本を習得するには、コマンドを通じて1つ1つの操作に集中した方が効果的でしょう。
そこで、本記事ではコマンドラインをメインに使用していくことにします。Git/GitHubに慣れてくれば、必要に応じてGUIアプリケーションもすんなり操作できるようになるでしょう。もちろん現場では、使用するツールが指定されていることもあるでしょう。その場合は、本記事の記述が自分の環境のどこに対応するのかを意識してみてください。
Gitの第一歩: リポジトリの作成と新規ファイルの追加
本格的な運用方法を見ていく前に、まず手始めにローカルでリポジトリを作成し、そこでコミットしてみましょう。
ローカルでリポジトリの作成
まず作業用のフォルダとして、ドキュメント(書類)フォルダ以下にgit_trial
というフォルダを作成し、ここにリポジトリを作ってみることにします。端末を開き、以下のようにドキュメントフォルダに移動します。そこでgit_trial
フォルダを作成し、そのフォルダに移動します。
$ cd ~/Documents/ // Documentフォルダに移動 $ mkdir git_trial // git_trialというフォルダを作成 $ cd git_trial // 作成したフォルダに移動
次に、以下のコマンドでこのフォルダにリポジトリを作成します。
$ git init
すると、git_trial
フォルダ内に.git
という名前の非表示設定のフォルダが作成されます。環境によってはエクスプローラやFinderでgit_trial
フォルダを開いても、何もないように見える場合があります。
その場合、端末でls
コマンドに-a
オプションを付けて実行すれば、次のように表示されます。
$ ls -a . .. .git
この.git
フォルダにコミット情報が蓄積されていきますので、誤って消してしまわないように注意してください。
デフォルトブランチ名について
リポジトリの作成時に初めて作成されるデフォルトブランチは、初期設定ではmasterという名前になります。一方で、GitHubでリポジトリを作成すると、デフォルトブランチの名前はmainとなります。いずれも設定は後から変更できます。現場でのルールに従うのが良いでしょう。
ファイルの追加
次に、ファイルを追加してみましょう。テキストエディター(メモ帳やテキストエディットなどのアプリ)を開き、ファイル名をREADME.md
としてgit_trial
フォルダに保存します。内容は何も書かなくてOKです。
ファイルが用意できたら、このファイルをインデックスに追加します。インデックスとは、コミットするファイルを登録する場所のことです。インデックスに追加することを「ステージする」とも言います。ステージしない限り、その変更をコミットすることはできません。
例えば下の図のように、ワーキングツリー(リポジトリで管理しているフォルダー)にAとBという変更が行われたファイルがあるとします。Aの変更だけをコミットしたい場合は、Aだけをステージしてコミットすれば良いのです。
変更したファイルをインデックスへ追加するには、以下のコマンドを実行します。
$ git add README.md
ファイルが追加されているか、次のコマンドで確認してみましょう。
$ git status No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: README.md
このように表示されるはずです。
ファイル追加の記録をコミットする
では、README.md
の追加をコミットしてみます。コミットには、必ずコミットメッセージを含めましょう。今回は単にファイルを追加するだけなので「READMEファイルを追加」とします。
$ git commit -m "READMEファイルを追加"
-m
の部分はオプションと呼ばれるもので、「-m
に続く部分をコミットメッセージとしてコミットする」という意味になります。このオプションを付けずにgit commit
のみで実行すると、コメント入力用のエディタ(初期設定ではvi)が起動します。コミットには必ずコメントを残さなければなりません(メッセージを残さずにコミットしようとすると、そのコミットは中止されます)。
コミットが済んだら、コミット履歴を確認してみます。
$ git log commit ec508d(中略)56e9c (HEAD -> master) Author: engineer-hub <engineer@enghub.co.jp> Date: Tue Feb 8 16:15:11 2022 +0900 READMEファイルを追加
コミットが増えていくと、この履歴が上に積み重なっていきます。
コミットメッセージには思いやりを
コミットメッセージは、単に変更内容を書くだけではなく、変更した理由や意図が読み取れるように心がけましょう。単に「バグを修正」と書いただけでは、どんなバグをどう直したのかが分かりません。次のように具体的に書くようにします。
メソッド〇〇で使用している型変換関数に脆弱性があったため、対策済みの関数に変更
絶対的な「正しい書き方」はありませんが、後から見る人への思いやりを持って書くように心がけましょう。
現場のルールを確認
コミットメッセージの書き方は、現場によってはルール化されていることもあります。例えば「バグトラッキングシステムの番号を先頭につける」とか「変更内容を表すプレフィックスをつける」などです。
どのようなルールにしても、後から見たときにどのような変更があったのかを明確にするためのものです。まずは各現場でルールがあるかを確認し、あればそれに従うようにしましょう。
管理しないファイルを.gitignoreに登録
プロジェクトファイルの中には、Gitによる管理の対象から外したいファイルがあると思います。例えばOffice系のファイルを開いたり、プロジェクトをビルドしたりすると生成される一時ファイルや、実行ファイルなどです。このようにバージョン管理が不要なファイルは、初めからGitの管理対象から外しておきましょう。
そのために使用するのが、.gitignore
ファイルです(ignoreは無視するという意味)。
無視したいファイルを登録する
.gitignore
ファイルは単なるテキストファイルです。テキストエディタで.gitignore
という名前のファイルを作成し、以下のように無視したいファイル名を記述して保存しましょう。
ignore_me.txt
動作を確かめるために、実際にignore_me.txt
というファイルを作成しましょう。そして以下のコマンドで状況を確かめてみます。
$ git status On branch master Untracked files: (中略) .gitignore
ignore_me.txt
ファイルがUntracked files(まだステージされてない未追跡の新しいファイル)にリストされてない(無視されている)ことが分かります。
なお、上記のように.gitignore
ファイル自体は管理対象に入ります。無視したいファイルも開発の進行に伴って変更される可能性がありますから、当然といえば当然です。
ファイルの種類ごとに登録する
.gitignore
に追加できるのは、個別のファイル名だけではありません。例えば拡張子が「exe」のファイルを全て無視したい場合、*.exe
と記述すると実行ファイルは全て無視されます。
*
(アスタリスク)はワイルドカードと呼ばれる種類の文字列で、任意の長さの任意の文字列を意味します。つまり、末尾が「.exe」である実行ファイルを全て無視することになります。
.gitignoreに登録したのに無視されない?
.gitignore
を使って無視対象ファイルを登録していると、登録したはずなのに無視されないことがたまにあります。登録した名前が単純に間違っているの(ミスタイプ)でなければ、すでにGitの管理対象として追跡されている可能性が高いです。
そのような場合は、次のコマンドを実行することで、リポジトリの追跡対象から除外できます(この後で「除外した」という変更をコミットする必要があります)。
$ git rm --cached (管理対象になっているファイルの)ファイル名
--cached
オプションを付け忘れると、ファイルが消えてしまうので注意してください。
GitHubを中心としたプロジェクト進行
具体的な実作業の流れに沿って、GitHubを中心としたプロジェクト進行を見ていきます。
組織アカウントを利用したリポジトリ管理
会社などの組織でGitHubを利用したプロジェクトを進行していく場合、組織(organization)アカウントを利用するのが便利です。組織アカウントを使用しない場合、チームの誰かが個人アカウントでプロジェクトのリポジトリを所有し、チームメンバーがそのリポジトリに対して操作することになります。しかし、リポジトリごとにメンバーのアクセス権限を設定する必要があり、リポジトリの数が多くなると管理が煩雑です。
▶ GitHub アカウントの種類 - GitHub Docs
組織アカウントは、一般的には企業単位で作成することが推奨されています。社内の開発チームなどの単位は、組織アカウント内の「チーム」で作成し、チームごとにリポジトリのアクセス権限を設定します。
また、組織アカウントで管理するリポジトリでは、メンバーごとに役割(role)を割り当てることが可能です。例えば、コードを書くことはないが、プロジェクトを閲覧してディスカッションに参加する「Read」、プロジェクトの一般的な管理をする「Maintain」、プロジェクトに積極的にプッシュする「Write」など、全部で5つの役割が用意されています。
これらを割り当てることで、リポジトリ内での各自の役割分担が明確になります。
GitHubでの実作業のシナリオ
ここからはGitHubでの実作業を見ていきます。具体的な作業の中で理解していただくために、次のようなシナリオで進めていきます。リポジトリの運用方法は、「組織開発におけるGitHubの利用形態」の章で説明した「GitHub-flow」の作業フローに従います。
▶ ある日のWebアプリケーションの開発チームの一員の作業
- GitHubのイシュー機能でバグの報告があり、自分がその対処にアサインされる
- 問題の箇所を確認し、作業に取り掛かる
- 途中で編集の競合(コンフリクト)などにも対処しつつ、修正を行ってプルリクエストでレビューを依頼
- レビューで問題がないことが確認されたので、mainブランチにマージ
※以降のスクリーンショットは、本記事用に作成したリポジトリで操作を行っているため、一人二役の表示となっています。
イシューで機能追加の要望を受ける
今日の作業を確認しようとGitHubのトップページを開くと、ダッシュボード左側の「Recent Activity」にお知らせが表示されていました。イシューやプルリクエストなどで自分に関わるアクションがあったときに表示されます。メールでの通知を有効にしている場合、登録したメールアドレスにも通知が届きます。
リンクをクリックして詳細を確認してみると、開発中のプログラムのソースコードにバグが発見されたと報告されており、Assigneesには自分1人がアサインされていました。
バグの内容は、OKまたはキャンセルをクリックしたときに表示されるメッセージが逆になっているとのことです。内容を把握し、修正作業に取り掛かったことを他のメンバーに伝えるために、このイシューのコメント欄にメッセージを残しておきます。
リモートリポジトリからクローン
ローカルにリポジトリがない場合は、リモートリポジトリをローカルに複製する必要があります。これをクローン(clone)といいます。開発チームに参加して最初に行う操作になるでしょう。
リポジトリをクローンするには、クローンしたいリポジトリのGitHubページにアクセスし、「Code」をクリックして「SSH」のタブを開きます。テキストボックスにアドレスが表示されているので、コピーボタンを押してコピーします。
端末を開き、リポジトリをクローンする先(ローカルのダウンロード先)に移動し、git clone
というコマンドの後ろにペーストして、実行します。
$ git clone git@github.com:[ユーザー名]/[リポジトリ名].git
一方で、これまでチームでの開発を行っていたのであれば、ローカルにリポジトリがすでにあるはずです。その場合は、最新のリモートリポジトリの状態をローカルに取り込む必要があります。これをプル(Pull)といいます。端末でローカルリポジトリのディレクトリに移動し、git pull
コマンドを実行します。
$ git pull origin main
ここでorigin
とはリモートリポジトリのことだと考えてください。
ファイル修正のコミットとリモートへの反映
今回は修正用のトピックブランチとして、swap_ok_cancel_message
という名前のブランチを作成し、このブランチに切り替えます。
$ git branch swap_ok_cancel_message $ git checkout swap_ok_cancel_message Switched to branch 'swap_ok_cancel_message'
いまローカルにあるブランチや、編集中のブランチの確認は、git branch
コマンドで行えます。
$ git branch main * swap_ok_cancel_message
main
とswap_ok_cancel_message
というブランチがあり、*
(アスタリスク)がついている後者が現在作業中のブランチです。
ブランチが作成されたので、イシューの報告で指摘されている「Utils.py
」というファイルを確認します。現在の状況は以下のようになっています。
(中略) if isOK: message="破棄しました" else: message="保存しました" (中略)
逆になっている「保存しました」と「破棄しました」というメッセージを、テキストエディターで以下のように修正しました。
(中略) if isOK: message="保存しました" else: message="破棄しました" (中略)
保存したら、以下のコマンドでコミットします。
$ git commit -am "OK/キャンセル時のメッセージが逆だったので、入れ替えました" [test 925d1cd] OK/キャンセル時のメッセージが逆だったので、入れ替えました 1 file changed, 2 insertions(+), 2 deletions(-)
git commit
の後の-am
というオプションは、更新のあった管理対象のファイルをインデックスに追加し、メッセージを付けてコミットするという意味です。
コミット前にブランチを切り替えたい場合
一通り修正作業などが終わった後、コミットせずに別のブランチに切り替えたいことがあります。しかし、切り替え先のブランチのファイルと競合していると切り替えできません。
そのようなときは、ブランチを切り替える前にgit stash
コマンドを使用します。これにより、加えられた変更を一時的に保存し、変更を加える前の状態に戻すことができます。
$ git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: README.md $ git stash Saved working directory and index state WIP on master: 7f18fcc hogehoge $ git status On branch master Your branch is up to date with 'origin/master'. nothing to commit, working tree clean
別のブランチでの確認が終わり、作業を行っていたブランチに戻ってきたら、git stash pop
コマンドを使用すれば変更を加えた後の状態に戻せます。
$ git status On branch master Your branch is up to date with 'origin/master'. nothing to commit, working tree clean $ git stash pop On branch master Your branch is up to date with 'origin/master'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: README.md no changes added to commit (use "git add" and/or "git commit -a") Dropped refs/stash@{0} (8a8bf6f9737468caf278bd414fbfce0585e65f93)
git stash
で一時的に保存した状態を残しておきたい場合は、git stash pop
コマンドの代わりにgit stash apply
コマンドを利用します。保存しているstashは、git stash list
コマンドで一覧表示できます。
コンフリクトに対処する
プルリクエストを作成してレビューしてもらう前に、以下のコマンドでリモートのmain
ブランチの状態を取り込みます。修正作業を行っている間にmain
ブランチに変更が加わっている場合があるためです。
$ git pull origin main
これを実行したところ、以下のようなメッセージが表示されました。
Auto-merging Utils.py CONFLICT (content): Merge conflict in Utils.py Automatic merge failed; fix conflicts and then commit the result.
コンフリクト(競合)が発生しているという表示です。Utils.py
を開いて確認したところ、以下のようになっていました。
(中略) if isOK: <<<<<<< HEAD message="保存しました" ======= message="保存しましt" >>>>>>> 24da43ee986623acd574ccb9beee15c1bad99aa2 else: message="破棄しました" (中略)
誰かが気を利かせて、すでに同じ場所を修正してくれていたようです。しかし、ミスタイプがあって自動マージできない状態でした。このようなことが起こるため、勝手に担当以外の場所を修正してはいけません。
また、このコミットは、別のコミットにまとめられてしまっています。このような場合、後から「いつ誰が修正したのか」「そもそも修正されたのか」といったことを知るのが面倒になります。それを防ぐためにも、複数の作業を1つのコミットにまとめないように心がけましょう。
Utils.py
の「<<<<<<< HEAD
」と「=======
」の間にあるのが現在のブランチの状態、「=======
」と「>>>>>>> 24da4...99aa2
」の間にあるのがmain
ブランチの状態です。もちろんトピックブランチの修正の方が正しいので、こちら側を残して保存します。
コンフリクト発生時に追加された「<<<<<<< HEAD
」「=======
」「>>>>>>> 24da4...99aa2
」は、自分で削除します。修正が終わったら、「コンフリクトを修正」というコメントを付けて、コミットしておきましょう。
どうしてもコンフリクトを解消できないとき
作業に慣れないうちは、どうしてもコンフリクトを解消できないこともあると思います。「もうどうしようもなくなった」と感じたら、クローンからやり直してみるという手もあります。
手元にあるファイルはバックアップとして別の場所にコピーしておき、ローカルリポジトリのフォルダごと削除してしまいます。そして同じ場所にクローンし直し、必要な変更をそのリポジトリに対して行います。
半ば強引で、良い方法とは言い難いですが、このようなやり方も頭に留めておくと良いかもしれません。
プルリクエストを作成して、レビューを依頼する
コンフリクトが解消されたら以下のコマンドを実行し、リモートリポジトリに反映させましょう。
$ git push origin swap_ok_cancel_message
GitHubのリポジトリページを開くと、「swap_ok_cancel_message had recent pushes ...」というメッセージの右に「Compare & pull request」ボタンが表示されています。
これをクリックしてプルリクエストを作成する画面を開きます。まずマージ先のブランチが正しく設定されているかを確認します。「base:main
」となっていればOKです。
次に、変更内容のタイトルと、メッセージを書き込みます。メッセージには、報告のあったイシューの番号を「#1
」のように書くことで、リンクすることもできます。レビュアーに見てもらいたい箇所が分かるように書きましょう。
レビュアーは、ReviewersやAssigneesから指定できます。一通り設定ができたら「Create pull request」をクリックして完了です。
その後、レビュアーにチェックをしてもらい、OKをもらえました。マージはGitHub上で行えますが、自分自身でマージするか、決まった担当者が行うかは現場のルール次第です。
ルールに従ってマージまで済ませました。以上で、一連の作業は終わりです。
一連の作業を確認してみよう
最後に、ブランチがどのように分岐してマージまで行われたかを、Network graphで確認してみましょう。リポジトリページの「Insights」というタブをクリックし、左のリストにある「Network」をクリックすると表示されます(Networkグラフが見れるのはリポジトリの公開設定がPublicの場合のみ)。
これは次のような流れを表しています。
main
ブランチから枝分かれした2つのブランチがある- 水色の
swap_ok_cancel_message
ブランチ - 緑色の
hoge_fuga_piyo
ブランチ
- 水色の
- 先に、気を利かせて修正してくれた
hoge_fuga_piyo
ブランチがmain
ブランチにマージされた swap_ok_cancel_message
ブランチで修正を行ったあと、main
ブランチの状態を反映した
このため、コンフリクトが起きた- 修正して
main
ブランチにマージできた
このようなグラフで確認できる機能をもったGUIアプリもあります。下の画像は、今回の一連のコミットをVSCodeの「Git Graph」という拡張機能で表示したものです。
グラフの横にコミットメッセージなどが表示されていて、全体の履歴が確認しやすいです。自分に合ったアプリを見つけてみましょう。
セキュリティ意識を高めよう
GitHubは情報漏洩事件の舞台になることがあります。近年では次のような話題が記憶に新しいでしょう。
これらはGitHubの公開リポジトリから情報が流出した事例ですが、GitHubに落ち度はありません。ユーザーがGitHubの公開設定や自分の扱っている情報についての意識を持っていれば、起き得なかったのです。
リポジトリの公開設定を意識する
基本的なこととして、GitHubのリポジトリには「Public」と「Private」の2種類の公開設定があります。限られたメンバー以外はアクセスできないPrivateに対して、Publicは文字通り全世界に公開されることを意識しましょう。
なお、Freeプランでは、Privateリポジトリで使用できる機能に制限があります。Privateのままで使いたい制限機能がある場合は、有料版に切り替える必要があります。
重要な情報を含むファイルをリポジトリに追加しない
組織開発では、顧客情報や個人情報などといった慎重に扱うべき情報を含むプロジェクトもあるでしょう。もちろん.gitignore
に登録していればリポジトリに追加されることはありませんが、うっかり登録を忘れてしまう可能性は低くありません。
こういった情報を扱う場合、次のような対策が必要です。
- 無闇にプロジェクトのフォルダ内に置かない
git add --all
コマンドは使わない
(--all
は、追加、削除、更新のあったファイルを全てステージするオプション)
GitHubをもっと活用しよう!
最後に最近話題の新機能など、もっとGitHubを活用できる情報をいくつか紹介します。
GitHubの基本的な機能を活用するだけでも、チームでの開発効率は格段に向上します。しかしGitHubには、近年の開発方法の発展に合わせて、さまざまな機能が次々と追加されています。
CI/CDを効率化するGitHub Actions
最近よく聞くようになったCI/CDとは、継続的インテグレーション(Continuous Integrations)と継続的デリバリー(Continuous Delivery)の略語です。つまり「開発→統合(インテグレーション)→デプロイ(デリバリー)」という開発サイクルを効率化する開発手法を意味します。
リポジトリで共同作業を行っていたとしても、それだけではコードがビルドできるのか、意図通りに動作するのかは分かりません。そこで、そのような検証を自動的に行うのがCIです。決められたタイミング(コミットをマージしたなど)でビルドを実行し、事前に用意しておいたテストコードで動作検証を行う、ということを継続的に行うのです。
一方で、ビルドしたソフトウェアをリリースするのにも一般的に手間がかかるものです。そこで、ビルドの手順を自動化しておき、継続的にソフトウェアを提供できる状態にしておくのがCDです。CI/CDを実施し開発サイクルを効率化することで、ユーザーの要望をいち早くフィードバックできます。
CI/CDを実現するため、これまではGitHubのリポジトリと別に独自に環境を構築する必要がありました。しかしActionsの登場により、GitHub内で完結するようになり、開発の効率化がますます進みました。
GitHub上でパッケージを公開する
▶ GitHub Packages: Your packages, at home with their code
GitHub Packagesは、リポジトリからリリースしたソフトウェアを、パッケージとしてデプロイできる機能です。npmなどのパッケージ管理ツールを通じてGitHub上にパッケージを公開できます。普段使用しているパッケージ管理ツールを使って、非公開のパッケージとして社内用に展開するといったことも可能になります。
さらにActionsと組み合わせることで、ブランチへのプッシュをトリガーとして、ビルド、テスト、リリース、デプロイまで全てを自動化できます。
開発環境をCodespacesでクラウド共有する
GitHub Codespacesは、クラウド上にホストされた開発環境です。CPUコア数やストレージ容量、その他の環境設定などを、リポジトリごとに共通化できます。
エディタとしてVisual Studio Code for the Webを利用できるので、コードをローカルに展開する必要もなく、多くの作業がブラウザ上で完結します。VSCodeの拡張機能なども設定で共通化しておけば、新しく異動してきた人もすぐに同じ環境で開発を始めることができます。
CopilotでAIとペアプログラミング
▶ GitHub Copilot · Your AI pair programmer
2021年6月にテクニカルプレビューが公開されて話題になったGitHub Copilotは、ソースコードをAIが自動生成してくれる機能です。本記事執筆時点でもまだ標準機能ではありません。利用するにはサイトから利用申請を行って、招待される必要があります。
この機能では、実装したいプログラム内容をコメントとして書き、続けて関数名などのコードの一部を入力すると、AIが勝手にそのコード内容を提案してくれます。例えば、以下のようなコードを記述します。
#誕生日から年齢を計算する def calc_
すると、以下のように続きのコードを提案してくれます。
#誕生日から年齢を計算する def calc_age(birthday): today = datetime.date.today() age = today.year - birthday.year if today.month < birthday.month: age -= 1 elif today.month == birthday.month: if today.day < birthday.day: age -= 1 return age
このAIは、GitHubの一般公開されたソースコードから学習を行っており、非常に低い確率ですが学習元のコードをそのまま提案することがあるそうです。その場合、もとのライセンスを確認しないまま再利用することになり、意図せずライセンス違反を起こしてしまうおそれがあります。
あくまで試験的な機能なので、標準機能としてリリースされ、ライセンス表記に関する問題が解消されるまでは、補助機能としての利用に止めるのが無難でしょう。
OSSの開発にも参加しよう!
GitHubには、数多くのOSSプロジェクトがリポジトリを公開しています。普段自分が活用しているOSSの開発に、GitHubを通じて貢献することもできます。
OSS開発への参加と聞くとハードルが高そうに感じますが、例えばドキュメントの誤字修正程度の報告も立派な貢献です。実際に初めてOSS開発に参加してみたというレポート記事も、ネット上には多くあります。
そういった方々の経験を参考にしながら、自らOSS開発への貢献を始めてみることも、GitHubユーザーとしては意義深いことでしょう。
記事制作:榎本孝之(リブロワークス)
編集:はてな編集部