library(usethis)
use_git_config(user.name = "<あなたの名前>",
user.email = "<あなたのメールアドレス>")
4 バージョン管理
データ分析作業に再現性をもたせる次のステップは、バージョン管理です。 バージョン管理は、データ分析のプロジェクトにおいて、コードやデータの変更履歴を記録し、管理する方法です。 この章では、バージョン管理の基本的な考え方と、代表的なバージョン管理システムであるGitの使い方について説明します。
4.1 バージョン管理の必要性
データ分析で用いるソースコードやデータは日々更新(バージョンアップ)されていきます。 ある日の作業では、データ読み込みのプログラムを書いて、次の日にはデータの前処理と可視化のプログラムを書くという流れです。 またある日には、これまで使っていたデータを新しいデータに差し替えることもあるでしょう。 そんな中で、ある日突然、以前実行可能だったコードがエラーを吐いたり、以前正常に動作していたコードが動かなくなったりすることがあります。
バグとなるプログラムを書いてしまうことは誰にでもあることですが、そのような場合に、以前のバージョンに戻ることができると便利です。 別の場面として、複数人で共同作業を行う場合、いつだれがどのような変更を加えたのかを把握することも重要です。 分析に用いる解析手法の変更に気がつかず、誤ったコードを使って分析を行ってしまうことは避けるべきでしょう。
バージョン管理システムを導入しないプロジェクトでは、ファイルが煩雑になりがちです。 どのファイルが最新のものなのか、どのデータを使うのかがわからなくなることもあります。
バージョン管理は、このような問題を解決するための選択肢となります。 つまり、ファイルに対して、複数のバージョンを保存しておくこととと、共同作業を行う際に、誰がどのような変更を加えたのかを記録するのがバージョン管理の役割です。
本書では、データ分析のためにバージョン管理システムを導入しますが、バージョン管理本来の目的は、プログラム開発においても同じです。 プログラム開発では、データ分析と同じく、長期にわたるプロジェクトや多くの開発者による共同作業です。 ソースコードを管理する点は変わりません。 データ分析の場合、ソースコードの他にデータやドキュメントも管理する必要がありますが、バージョン管理システムはそれらを一元管理することができます。
4.2 分散型バージョン管理システム: Git
複数の開発者が共同でコードを管理・開発する際に便利な機能を提供するバージョン管理システムです。 バージョン管理システムには大別して2つの種類があります。 集中管理型は、ファイルの変更履歴を一つのリポジトリ(中央リポジトリ)に保存する方式です。 中央リポジトリはサーバー上に置かれるため、編集作業を行う際にはサーバーに接続する必要があります。
もう一つが分散管理型です。 分散管理型は、ファイルの変更履歴を各ユーザーの端末にリポジトリ(リモートリポジトリ)のコピーをローカルリポジトリとして保存する方式です。 各自の端末で行われる編集作業が行われる点は集中管理型と変わりませんが、リモートリポジトリのコピーをローカルリポジトリとして持つことで、オフラインでも作業が可能です。 リモートリポジトリに変更を反映する際には、リモートリポジトリに変更をプッシュすることで、他のユーザーとの共有が可能です。
分散管理型の代表として、Gitがあります。 Gitは、Linuxカーネルの開発者であるLinus Torvalds氏によって開発されました。
Gitが開発された背景には、Linuxカーネルの開発と、従来利用されていたバージョン管理システムであるBitKeeperの利用停止があります。 バージョン管理システムを模索する中、完全な分散型やブランチ機能を強化した新たなバージョン管理システムが必要とされました。 Gitの最初のリリースは2005年で、バージョン管理システムの中では比較的新しいものですが、現在では最も広く使われているバージョン管理システムの一つとなっています。
ここではGitのインストール方法を含めた詳細なGitの説明は行いません。横田紋奈 と 宇賀神みずき (2022) や 渡辺宙志 (2024) を参考にしてください。オンラインで読めるPro GitやRユーザー向けのHappy Git and GitHub for the useRもあります。
4.2.1 リポジトリ
Gitではファイルやディレクトリの状態を記録し、変更履歴を管理する場所をリポジトリと呼びます。 リポジトリには、プロジェクトに関連するコードやファイルが含まれます。
リポジトリは、性質の違いによりローカルリポジトリとリモートリポジトリに分けられます。 ローカルリポジトリは、自分のコンピュータ上に保存されているリポジトリです。 個々の開発者が自身の作業を管理し、変更履歴を保存するために使用されます。
リモートリポジトリは、ネットワーク上のサーバーに保存されているリポジトリです。 ネットワークを介して、複数の開発者がアクセス可能であり、共同作業(共有と同期)を行うために使用されます。
Gitリポジトリを使った開発の流れは、開発者個人がそれぞれのローカルリポジトリで作業を行い、リモートリポジトリに変更を反映するというものです。 そのため、リモートリポジトリはバックアップとしての役割も果たします。
4.3 バージョン管理の流れ
最低限必要なコマンドを紹介しますので、まずはバージョン管理の雰囲気をつかんでください。 Gitバージョン管理は次の3つのステップで行います。
- リポジトリの作成
- ファイルの追加
- ファイルのコミット
Gitには100を超えるコマンドがありますが、覚えるべきコマンドは限定的です。 上記のバージョン管理の流れでは、それぞれ数個のコマンドを使います。 つまり、一連のバージョン管理で用いるコマンドは指で数えられる範囲に収まります。
最初の作業は一度行えば、その後は実行する必要がなくなるので、実際は2つのステップとなります。
4.3.1 リポジトリの作成
これからプロジェクトを立ち上げる、あるいは既存のプロジェクトをGitで管理する場合、まずリポジトリを作成します。 git init
コマンドを実行すると、現在のディレクトリに.git
フォルダが作成されます。 このフォルダはGitリポジトリの中心的な役割を果たします。隠しフォルダとなっており、ユーザーが直接操作することはありません。
4.3.2 ファイルの追加: ステージングエリアへの登録
リポジトリにバージョン管理の対象とするファイルを追加するには、git add
コマンドを使います。 リポジトリにファイルがない場合、何かファイルを作成してみてください。 その後、git status
というコマンドを実行すると Untracked files
という箇所に作成したファイル名が表示されます。 この状態のファイルをリポジトリに追加するには、git add
コマンドを使います。
`git add <ファイル名>`
git add
したファイルは、ステージングエリアという仮想的な場所に追加されます。 ステージングエリアに追加されたファイルは、次にコミットする対象となります。
Untracked状態のファイルが複数ある場合、git add .
というコマンドを使うと、全てのファイルを一括で追加できます。
4.3.3 ファイルのコミット
作成・変更したファイルの状態を記録する作業をGitでは「コミット」と呼びます。 コミットを重ねることで、ファイルの変更履歴を残すことができ、必要に応じて過去の状態に遡ることができます。
コミットの対象となるのは、ステージングエリアに追加されたファイルです。 そのためgit add
を行う前にgit commit
を行うと、コミット対象のファイルがないというエラーが表示されるので注意してください。
git commit
コマンドを使って、ファイルの変更をコミットします。 コミットには、コミットメッセージと呼ばれる説明文を付けることができます。 作業後、コミットの履歴を見た際に、どのような変更を行ったかを把握するために重要な情報となります。 なぜその変更を行ったのか、どのような変更を行ったのかを記述します。
コミットを行う際には、氏名とメールアドレスの設定が必要となります。 2つの設定は、Gitのコミットログで誰がコミットしたかを示すために必要な情報です。
ターミナルを開いて以下のコマンドを実行します。 二重引用符で示した箇所は適宜変更してください。
git config --global user.name "<あなたの名前>"
git config --global user.email "<あなたのメールアドレス>"
設定が完了したかどうかは、以下のコマンドで確認できます。
git config --list
この出力でuser.name
とuser.email
が正しく表示されていれば、設定が完了しています。
上記の処理はRパッケージであるusethisを使ってRからも行えます。
コミットメッセージは、以下のような形式で記述します。
- 1行目: 変更内容の要約
- 2行目: 空行
- 3行目以降: 変更内容の詳細
Gitに不慣れな方は、コミットメッセージを書くことに障壁を感じるかもしれません。 しかし、難しく考える必要はありません。 ここで大事なことはコミットを残すことです。コミットメッセージは後から修正することもできますし、正解があるわけではありません。 簡単な情報であっても、コミットメッセージを残すことが大切です。
4.4 アプリケーションを利用したバージョン管理
Gitはコマンドラインツールですが、GUIアプリケーションを使うことで、より簡単にバージョン管理を行うことができます。 Rの統合開発環境であるRStudioやVS Codeでも、Gitと連携した操作が可能です。 分析作業から離れずにバージョン管理を行うことができるため、非常に便利です。 すべてのコマンドを実行可能なわけではありませんが、基本的な操作はGUIを通して行えます。
4.4.1 RStudio
ターミナルあるいはGitタブを使ってバージョン管理を行います。 ここではGUIで操作可能な方法を紹介します。 なおRStudioのGUIでは、GitとSVNによるバージョン管理をサポートしています。
.git
フォルダが存在するプロジェクトを開くと、RStudioはGitタブを表示します。 この画面がRStudioでのGUIによるバージョン管理処理の中心となります。 もしもGitタブが見つからない場合、メニューのTools、Global Options…から、Git/SVNにてEnable version control interface for RStudio projects
にチェックを入れてください。
Gitタブには、ファイルの差分やコミット履歴を確認するボタンが用意されています。 メインとなるのはStaged
、Status
、Path
の3列で構成される箇所です。 それぞれの列には次の意味があります。
Staged
: ステージングエリアに追加されたファイルStatus
: ファイルの状態Path
: ファイルのパス
Staged
はチェックボックスになっており、ステージングエリアに追加するファイルを選択できるようになっています。 これにより、git add
コマンドを使わずにステージングエリアへの登録が行えます。 Shiftキーを押しながらの選択で、複数ファイルの選択も可能です。
次のStatus
には、いくつかのアイコンが表示されます。 各アイコンの意味は下記の通りです。
アイコン | 状態 |
---|---|
? ![]() |
untracked バージョン管理の対象になっていない |
Modified ![]() |
リポジトリの状態から変更された |
Delete ![]() |
リポジトリにあったファイルが削除された |
Added ![]() |
新たにバージョン管理状態になった |
Unmerged ![]() |
リポジトリ間で差分が衝突している |
Renamed ![]() |
ファイル名が変更された |
4.4.2 VSCode
- リポジトリを初期化する
4.5 GitHub
ここまでで、Gitを使ったバージョン管理の基本的な操作を学びました。 次に、リモートリポジトリを利用して、複数人での共同作業を行う方法を紹介しましょう。 複数人と書きましたが、個人であってもリモートリポジトリを利用することで、バックアップ目的や異なるデバイスでの作業を行うために利用することができます。
GitHub は、Gitリポジトリをホスティングするウェブサービス(リモートリポジトリ)です。 世界中のさまざまなプロジェクトで採用されるリモートリポジトリであり、オープンソースプロジェクトの共有やコラボレーションに広く利用されています。 ウェブサイトの閲覧は誰でもできますが、主要な機能を利用する際にはアカウントの作成が必要です。
RパッケージのソースコードをGitHubで管理する開発者も多く、CRANで配布されるものだけでなく、CRANポリシーに適合しないなどの理由でCRANでは配布されないパッケージも豊富に存在します。 remotesやpakパッケージを使えば、これらのGitHub上で配布されるRパッケージのインストールも可能です。
GitHub上のリポジトリには、誰でもアクセス可能なパブリックリポジトリと、特定のユーザーのみがアクセス可能なプライベートリポジトリの2種類があります。 プライベートリポジトリは、リポジトリの所有者と共同作業者(コラボレーター)のみがアクセスできるため、機密情報を扱うプロジェクトにも利用できます。
GitHubにはここで取り上げる内容以外にも多くの機能があります。GitHub公式が提供するGitHub Skillsでは、実際のGitHubリポジトリを操作してGitHubの使い方を学ぶことができます。
4.5.1 ローカルリポジトリの紐付け
プロジェクトの章で作成したプロジェクト(rrr-demo
)をGitHubと紐付けます。 まずはGitHub上で新しいリポジトリを作成します。 ここでリポジトリ名を指定しますが、混乱を避けるためにローカルリポジトリのプロジェクト名と同じ名前にしておくことを薦めます。
作成したリポジトリのURLは https://github.com/<アカウント名>/<リポジトリ名>
となります。 ページにアクセスすると、次の図のような画面が表示されます。 この状態ではリポジトリにファイルは存在していませんが、 作成したリモートリポジトリをローカルリポジトリに紐付けるための手順が書かれています。 2つの方法が示されていますが、一つは新しいローカルリポジトリを作成する方法、もう一つは既存のリポジトリをリモートリポジトリとして指定する方法です。 今回は後者の方法に従い、既存のローカルリポジトリをリモートリポジトリとして指定します。
書かれた内容をコピーし、ローカルリポジトリのディレクトリで実行します。 このコマンドでは、リモートリポジトリを origin
という名前で登録しています。 origin
はリモートリポジトリのデフォルトの名前として一般的に使われています。
次に、ブランチ名の変更です。 GitHubでは、デフォルトのブランチ名として main
が使用されています。 これに合わせるために、ローカルリポジトリのブランチ名を main
に変更します。 そして、ローカルリポジトリで行った作業内容をリモートリポジトリに反映させるためにプッシュします。
git remote add origin https://github.com/uribo/rrr-demo.git
git branch -M main
git push -u origin main
GitHubとの
4.5.2 リモートリポジトリのクローン
新しいコンピュータなど、ローカルリポジトリを持っていない場合には、リモートリポジトリをクローンします。
git clone
git clone https://github.com/uribo/rrr-demo.git ~/Documents/projects2024/rrr-demo
変更の同期 git pull
, git fetch
クローンしたリポジトリはローカルリポジトリとして扱うことができます。
4.5.3 GitHub Issues
プロジェクトに関する問題やメモのために利用できます。
4.6 バージョン管理の流れ再び
コミット後のステップとして、以下が追加されます。
- リモートリポジトリの指定
- ファイルのプッシュ
git remote add
4.6.1 ファイルのプッシュ
コミットを行ったら、変更を確定させるためのプッシュを行います。 プッシュを行うことで、リモートリポジトリに変更内容が反映されます。
git push
4.7 .gitignore
Gitバージョン管理を行うリポジトリでは、バージョン管理に含めるべきではないファイルが存在します。 例えば、セキュリティ上重要な情報を含むファイルやキャッシュファイルなどです。 これらがバージョン管理に含まれると、セキュリティリスクが高まったり、リポジトリのサイズが大きくなるなどの問題が発生します。 実際に、GitHubなどのリモートリポジトリにデータベースの接続情報やAPIキーなどの機密情報が含まれていると、悪意のある第三者によって悪用される可能性があります。
Gitでは.gitignore
にバージョン管理の対象外とするファイルを記録することで、上記の問題の解決を図っています。 バージョン管理を行わないファイルの指定方法は、gitignore
にそのファイル名や名称のパターンを記述することで行います。 .gitignore
ファイルはリポジトリ内の任意の場所に配置することができますが、通常はリポジトリのルートディレクトリ、.git/
フォルダと同じ階層に配置します。
.gitignore
に記録するファイルはプロジェクトによって異なりますが、一般的にバージョン管理から除外される種類のファイルが存在します。 特にファイルやフォルダ名の先頭に .
が付いているものは、バージョン管理から除外することが一般的です。 こうしたファイルやフォルダは隠しファイル、隠しフォルダと呼ばれ、システムによって生成され、ユーザーが直接操作することは限定的です。 加えて、サイズが大きかったり差分管理が困難なバイナリファイルはバージョン管理の対象外となることが多いです。
.gitignore
の記載例を示します。.gitignore
では特定の正規表現を使って複数のファイルを指定したり、否定の表現(つまり管理に含める)を使った柔軟な指定が可能です。
Thumbs.db
.DS_Store
.Rproj.user
.Rhistory
.RData
.Ruserdata
*.pdf
*.log
README.html
Thumbs.db
や.DS_Store
は目にしたことがない方もいるかもしれません。 これらはWindowsやmacOSで生成されるファイルで、フォルダ内のファイルのサムネイルや表示方法を記録するファイルです。 プロジェクト内のコードには影響を与えないため、バージョン管理は不要です。
続いての.Rproj.user
から.Ruserdata
はRに関連するものです。 特に.Rproj.user
はRStudioのプロジェクト設定ファイルを含むフォルダでバージョン管理を行いません。 .Rhistory
や.RData
はRの履歴やデータを保存するファイルですが、ユーザーやセッションの度に更新されるものであるため、これらもバージョン管理を行いません。
*.pdf
、*.log
はPDFおよびlog形式のファイル一式を除外する指示です。ファイル名に関わらず、拡張子によって除外される複数のファイルを想定しています。 アスタリスク(*
)は任意の文字列を表し、*.pdf
は拡張子が.pdf
であるファイルをすべて指定します。
拡張子による指定という点で、その次の行 README.html
も同様ですが、*.pdf
や*.log
と異なるのはプロジェクト内のすべてのHTMLファイルを除外するわけではないという点です。 README.html
は特定のファイル名を指定しています。つまり対象外となるのは1つのファイルだけです。
.Rprofile
はバージョン管理に含めるか悩むところですが、 Rの設定や挙動を制御する内容が書かれているものであればバージョン管理するべきです。 プロジェクトに参加するすべてのメンバーが同じ条件でRを実行するために必要となる可能性があります。 一方で、.Rprofile
に個人の機密情報や認証情報が含まれるのであれば.gitignore
に追加しましょう。
クレデンシャルな情報を扱う必要があるのであれば、.Renviron
や.Renviron.site
を使って環境変数として設定することを検討してください。 これらの情報は手間がかかるかもしれませんが、セキュリティ上のリスクを軽減するためには必要な対応です。 第6章では、configパッケージを使った環境変数の管理について紹介します。
最後に、作成した覚えのないファイルやフォルダがGitバージョン管理の対象となっているときは、注意してそのファイルをバージョン管理に含めるべきかを検討してください。 著者の経験では、身に覚えのないファイルは一時的に生成されたものや成果物であることが多く、バージョン管理の対象外とすることが多いです。