LaTeX文書置き場としてのGit/GitHub最速チュートリアル

# 概要

+ LaTeX文書[^1]置き場としてはGoogle DriveやDropboxよりもGitHubがおすすめ
+ [以前の記事](https://qiita.com/Nmatician/items/7d989973e498210bac0e)ではGitHubの使い方にはあまり触れなかった
+ ブランチやプルリク等の機能は無視した単なる物置としてのGit/GitHubの運用法を紹介

[^1]: ここでは，LaTeXで作成されたPDFとそのソースをまとめて「LaTeX文書」と呼ぶこととする．

# 対象読者

+ LaTeXについてはよく知っているがGit/GitHubについてはあまり知らない
+ LaTeX文書を書き，それをソースごと公開しようと思っている
+ CUIにさほど抵抗はない（具体的にはPowerShellやWSLを使えと言われたら使える程度）
+ GitをCUIで使用できる環境を整えることができる（あまり古くないバージョンのWindows10ならOK）
+ 多少は英語が読める（サイトが英語でも文句を言わない程度）

# 本記事に書いてあること

+ 単なる物置としてのGit/GitHubの使い方
+ `.gitignore`の使い方

# 本記事に書いていないこと

+ LaTeX文書の書き方
+ WSLの導入法
+ ターミナルまわりのいろいろ（例えば[このへん](https://qiita.com/yoshi-2015/items/90e463a264b041b4f5e3)を読んでおくとよいかもしれない）
+ Git/GitHubの詳細な解説
+ Git/GitHubが有するスバラシイ機能
+ GUIベースでのGit/GitHubの使用方法[^2]
+ VSCode等のテキストエディタからの操作
+ Windows10以外のOSでの運用
+ 説明なしで登場する（した）用語の意味

[^2]: GUIベースでやるならそもそもWSLを導入する必要もない．しかし，個人的にはCUIベースの方が使いやすいであろうと思うのでGUIベースでの運用法は紹介しない．

# 背景と導入

以前このような記事を投稿し．LaTeX文書はGitHubに置いてソースごと公開せよという主張を述べた．

https://qiita.com/Nmatician/items/7d989973e498210bac0e


しかし，そこではGit/GitHubの使い方に関してはほとんど触れず，
たとえソースを公開しようと思っても何をどうしたらよいのかははっきりと伝わってはいなかった．
しかも，「単なる物置としてGitHubを使う」という運用はGitHubの運用としては相当異端であり，調べても必要な情報を見つけるのは容易ではない．
そこで，本記事ではLaTeX文書置き場として，学習コストが比較的高いブランチやプルリク等の機能はすべて無視したGitHubの運用法を紹介する．


# 知識の整理

筆者個人としては，使うツールや行う操作が一体どういうものなのかということを，
難しくなりすぎない範囲で理解すべきであると考えている．
しかし，「最速チュートリアル」ということを考えれば，この部分は余計だろうと考える人もいるかもしれない．
そのような人は，この項は読み飛ばし，[環境構築](#環境構築)から読み始めてほしい．

## ライセンス

### ライセンスとその意義

著作物の利用は，無断で行ってよいことが法律等で規定された場合を除き，著作者の許可が必要である．
しかし，著作者が「このくらいは別にいいだろう」と考えてるものに対していちいち許可を取るのは不合理である．
そのような場合，あらかじめその著作物にその旨を明記しておくと都合がよい．これを**ライセンス**という．

本記事で扱う文脈では，主にソースコードの再利用に関して問題になることが多いだろう．
ライセンスがなくては，そもそもコピーしてよいかとかバグを修正したり機能を追加したりしたうえで
再配布してもよいかなどといったことも
いちいち許可を取らなくてはならない．「バグ修正や機能追加なら大歓迎だから勝手にやってくれよ」と思うのであれば，
その旨を明記しておくことで利用者が安心して行えるのである．

### ライセンスの選択

ここで重要なのは，自分が公開するソースコードのライセンスはどうするか，ということである．
今までライセンスなどということを考えたことはない人の中には「とりあえず好きに使ってくれていいや」と思う人も多いであろう．
そのような人はMITライセンスを選択することを推奨する．
MITライセンスに関しては，例えば

https://qiita.com/yyama2/items/20bdf5e914c20025498a

のような解説がある．MITライセンスで公開されているものの利用に関しては，例えば

https://www.catch.jp/oss-license/2018/11/14/use_mit_license/

といった解説がある．

ライセンスの選択で重要なのは，よく知られているものを**そのまま**使うということである．
特段の理由がない限り，改変したライセンスやオリジナルのライセンス等は用いるべきではない．
何をやっていいのかが不明瞭になる上に，そもそもライセンス本文は改変が許可されていない場合もあるからである．

## WSL

Windows Subsystem for Linux（WSL）は，Windows上でLinuxを動かすための互換レイヤーである．
現在WSL2が最新であり，特に理由がない場合にはWSL2を導入することが推奨される．
ここでは，GitをCUIで動かすためのWindows上の実用的な環境であるという理由で導入する．

## Git

Gitは，ソースコード等のテキストベースのファイルの変更履歴を追跡するための分散型バージョン管理システムである．
テキストベースのファイルのみを管理するのが望ましいが，PDFのようなバイナリファイルも管理できないわけではない．
ここでは，ファイルをいい感じに管理してくれるツール程度に思っておけばよい．
ファイル名に日付をつけたり，ファイル名末尾に「最終版」とか「提出版」等の識別子をつけて管理していたのを自動で行ってくれるものと考えると理解しやすいであろう．

### Gitによるファイル管理の仕組み

#### リポジトリとワークツリー

Gitがファイル（やディレクトリ）の状態を記録しておく場所を**リポジトリ**という．
リポジトリには，ローカルマシン上に存在する**ローカルリポジトリ**と外部サーバー上に存在する**リモートリポジトリ**の2種類がある．
さらに，リモートリポジトリには誰でも閲覧できる**パブリックリポジトリ**と自分だけ（あるいはチームのメンバーだけ）が閲覧できる**プライベートリポジトリ**が存在する．なお，リモートリポジトリに対する操作はパブリック・プライベート関係なく自分が所有するリポジトリに対してのみ行える．


Gitがローカルマシン上のファイルを管理している状況を考えよう．
あるディレクトリをGitの管理対象にすると，そのディレクトリに`.git`というディレクトリが作成される．
これがGitリポジトリである．そして，実際に作業しているディレクトリを**ワークツリー**と呼ぶ．

例を挙げよう．いま，Gitの管理対象となっているディレクトリが以下のような構造であったとする．

```sh
.
├── .git
├── README.md
├── llmk.toml
└── test.tex

1 directory, 3 files
```

この`.git`ディレクトリが「Gitリポジトリ」と呼ばれるものであり，それを除いた残りの部分がワークツリーである．

#### ステージング・エリア

上記の状態でワークツリー内のファイルに変更が生じたとしても，それはすぐにはリポジトリには反映されない．
反映させるためには，**ステージング・エリア**（**インデックス**）と呼ばれる領域にその情報を登録する必要がある．
ステージング・エリアに情報を登録することを**ステージング**といい，
ステージング・エリアに登録された情報をリポジトリに反映させる操作を**コミット**と呼ぶ．
このような二段階の工程を踏むことにより，いくつかの変更をまとめてコミットしたり，特定のファイルのみをコミットしたりできる．

また，ある特定のファイルはGitに管理させたくない，という場合，そのファイルの名前を`.gitignore`というファイルに記述しておくと，
Gitはそれを無視してくれる．`.gitignore`に記述するファイル名には「`*.log`」のような書式も有効で，この場合「`.log`で終わるファイルすべて」という意味になる．auxファイルやlogファイルは管理させても仕方ないので，`.gitignore`に記述しておくべきである．

## GitHub

作成したローカルリポジトリをインターネット上のリモートリポジトリに反映させるためには，
そのためのプラットフォームが存在していると都合がよい．
そのようなプラットフォームはいくつか存在している[^3]が，GitHubというプラットフォームが定番である．

数あるプラットフォームの中からGitHubを選択する理由としては，定評があるというのはもちろんであるが，
もっと重要な理由として，ライセンスと`.gitignore`を自動生成してくれるという点が挙げられる．

[^3]: 各プラットフォームにはそれぞれ特色がある．本記事では紹介しないが，目的によっては違うプラットフォームを利用するのが適切である場合もある．

プラットフォーム上で作成したリモートリポジトリは，公開されているものは自由にローカルマシン上に複製できる．
その行為を**クローン**と呼ぶ．クローンによって作成されたローカルリポジトリは
取得元のリモートリポジトリと紐づいており，リモートリポジトリに変更があった場合，
新しくクローンし直すことなく更新を反映させることができる．この更新の反映は**プル**という．

自身が所有するリモートリポジトリの場合，
ローカルマシン上のローカルリポジトリの内容をそのリモートリポジトリ上に反映させることができる．
その行為を**プッシュ**と呼ぶ．この場合，当然ローカルリポジトリとリモートリポジトリは紐づいていなければならない．
ローカルリポジトリとリモートリポジトリを独立に作成した場合，その紐づけ作業をしなければならないが，
リモートリポジトリをクローンして作成されたリモートリポジトリの場合はその作業は不要である．
従って，特に理由がなければ，先にリモートリポジトリを作成した上でそれをクローンすることが推奨される．


#### 最低限のワークフロー

以上のことを踏まえれば，Gitでファイルを管理してそれをGitHub上のリモートリポジトリと連携させたい場合，
最低限のワークフローは以下のようになる．

1. GitHub上でリモートリポジトリを作成する．
1. リモートリポジトリをクローンし，ローカルマシン上にそのリモートリポジトリと紐づいたローカルリポジトリを作成する．
1. ワークツリー上で作業する．
1. 作業したファイルをステージング・エリアに登録する．
1. ステージング・エリアの情報をもとにローカルリポジトリにコミットする．
1. ローカルリポジトリの内容をリモートリポジトリにプッシュする．




# 環境構築

:::note warn
ここでは，WSLで導入するディストリビューションはUbuntuであることを想定している．
それ以外のディストリビューションを導入したい場合は，
導入後に実行するコマンドをそのディストリビューションに応じたものに置き換えよ．
:::

## WSL

詳細な方法は調べればいくらでも出てくるので省略．例えば以下．

https://qiita.com/whim0321/items/ed76b490daaec152dc69

なお，これ以降の操作はすべて導入したLinuxディストリビューション上での操作である．
「ターミナル上」は導入したLinuxディストリビューションを起動すると表示されるコンソール上のことであると読み替えてよい．

## Git

### インストール

ターミナル上で以下のコマンドを実行する[^4]：

```sh
$ sudo apt install git
```

実行した場合にはパスワードが要求されるが，そのパスワードはLinuxディストリビューションを導入したときに設定したものを入力する．

[^4]: なお，ここの「`$`」はコンソール上の入力を表す記号であり，実際に入力するわけではない．


### 初期設定

リモートリポジトリをcloneするだけなら不要であるが，
コミットすることも考えるとユーザー名とメールアドレスをここで設定しておくべきである．
コミットにはこの設定が必須だからである．
設定には`~/.gitconfig`ファイルを編集してもよいが，ターミナル上からも行える．次のコマンドを実行すればよい（名前とメールアドレスの部分は各自置き換え）：

```sh
$ git config --global user.name "Your Name"
$ git config --global user.email "YourEmail@gmail.com"
```

## GitHub

### アカウントの作成

[GitHub](https://github.com)にアクセスし，「Sign Up」からアカウントを作成する．
ここで設定するユーザー名やメールアドレスは，Gitで設定したものと異なっていてもよい（両者はまったく独立である）．

### パーソナルアクセストークンの作成

プライベートリポジトリをクローンしたり，リモートリポジトリにプッシュしたりする場面において，認証が求められる場合が多々ある．
認証にはユーザー名とパスワードの入力が求められるので，アカウント作成時のユーザー名とパスワードを入力すればよいものと考えて入力すると，認証に失敗してしまう．実はパスワードによる認証は2021/08/13に終了しており，失敗するのはそれが原因である．

https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/

ここでは，パスワードではなくパーソナルアクセストークンによる認証方法を紹介する．
SSHキーによる認証方法は，例えば

https://qiita.com/shizuma/items/2b2f873a0034839e47ce

を参照せよ．手順は以下のようになる：

1. GitHubの右上に表示されているユーザーのアイコンをクリックする．
1. 表示されているメニューの中から「Settings」をクリックする．
1. ページ左のメニューから「Developer settings」をクリックする．
1. ページ左のメニューから「Personal access tokens」をクリックする．
1. 「Generate new token」ボタンをクリックする．
1. 「Note」欄に何かしらの説明を書く（省略不可）．
1. 「Expiration」のところでトークンの有効期限を設定する．
1. 「Select scopes」以下の欄にこのトークンを使った場合に許可したい操作にチェックを入れる．一番上の「repo」にチェックを入れておけばたいていは事足りると思われる[^5]．
1. 一番下にある緑色の「Generate token」をクリックする．
1. 画面上に作成されたトークンが表示されるので，記録する．

[^5]: 基本的に，与える権限は必要最小限にしておくべきである．「とりあえずこの辺りをまとめて許可しておけばいいか」という運用は実は望ましくない．

Gitが関係するコマンドで入力が要求される「パスワード」には，GitHubアカウントを作成した際のパスワードではなくここで作成したパーソナルアクセストークンを入力することになる．


# 運用

いよいよ具体的な運用法を述べる．

## リモートリポジトリの作成

1. GitHub上で緑色の「New」ボタンをクリックし，新しいリモートリポジトリを作成する．この「New」ボタンはトップ画面やリポジトリ一覧画面等にある．
1. リポジトリ名を記入する．リポジトリ名には日本語は使用不可である（ハイフンに置換されてしまう）．
1. リポジトリをパブリック・プライベートのどちらにするかを決める（無論途中で変更できるので，とりあえずで決めて構わない）．
1. リポジトリ作成時にREADMEを追加する場合，「Add README file」にチェックを入れる（後でローカルリポジトリ上で作成してプッシュしてもよい）．
1. 「Add .gitignore」にチェックを入れる．
1. 「.gitignore template: None ▼」というボタンが表示されるので，それをクリックして「TeX」を選択する．
1. 「Choose a license」にチェックを入れる．
1. 「License: None ▼」というボタンが表示されるので，それをクリックして適切なライセンスを選択する．筆者個人としてはMITがオススメである．
1. 緑色の「Create repository」ボタンをクリックする．これでリモートリポジトリが作成される．

なお，ここでプライベートリポジトリを作成した場合，クローンやプッシュには認証が要求される場合がある．
詳しくは[パーソナルアクセストークンの作成](#パーソナルアクセストークンの作成)の項を参照せよ．

## リモートリポジトリのクローン

まずはターミナル上でリモートリポジトリをクローンしたい場所に移動する．ここでは，「`git`」というディレクトリを新しく作成し，そこにクローンすることとする．

まず，以下のコマンドを実行し，ディレクトリ「`git`」を作成する：

```sh
$ mkdir git
```

次に，以下のコマンドを実行し，作成したディレクトリ「`git`」に移動する：

```sh
$ cd git
```

この状態で，以下のコマンドを実行する：

```sh
$ git clone https://github.com/<UserName>/<RepositoryName>
```

後半のURLは作成したリポジトリのURLを入力する．

## LaTeX文書の作成

ワークツリー上で思うがままに執筆する．なお，WindowsのエクスプローラーからLinux側のファイルにアクセスするためには，
エクスプローラー上で「`\\wsl$`」を開けばよい（開いているファイルが表示されている部分のアイコンをクリックして入力）．
この作業は頻繁に行うので，そもそもLinux上で執筆できるようになっていることが望ましい．
使い慣れたエディタを使えばよいが，これといったものがないならVSCodeがオススメである．
環境構築は

https://qiita.com/_masa_u/items/d3c1fa7898b0783bc3ed

などを参照せよ．この場合，TeX環境もWSL側に用意されているべきである．インストール方法はLinuxにインストールする方法とまったく同じである．

## ステージングとコミット

適当な切れ目でローカルリポジトリにファイルの変更をコミットしておこう．
まず，以下のコマンドを実行してステージングを行う：

```sh
$ git add .
```

後ろにくっついているドットはタイポではない．このドットは「カレントディレクトリのファイルすべて」という意味である．
ファイル名を明示的に指定することでそのファイルのみをステージングすることもできるが，そのような状況はあまり多くはないであろう．
なお，ドットを記述しても`.gitignore`に記述されたファイルは無視される．
PDFファイルを無視させたくない場合，`.gitignore`を開いて「`*.pdf`」をコメントアウトするか削除すればよい．
文書が完成し，公開に移る段階で行うことが多いだろう．

次に，以下のコマンドを実行してステージング・エリアの情報をローカルリポジトリに反映させる（「some comment」の部分は各自書き換え）：

```sh
$ git commit -m "some comment"
```

`-m`以降はコミットに付随するコメントを表す．コミットにはコメントが必須であり，`-m`以降を省略して
`git commit`とした場合はコメントを入力する画面が立ち上がり，入力が求められる．

コメントの内容は，「誤植の修正」とか「証明の追加」等コミットの内容を一言で言い表したものが望ましい．
真面目に開発を行う場合はコミットの粒度やコメントの内容はよく検討すべきであるが，
本記事で想定しているような物置としての運用であれば雑でもよいだろう．

## リモートリポジトリへのプッシュ

ここまで上に述べた手順通りに進めた場合，ローカルリポジトリとリモートリポジトリの紐づけはすでに完了している．
従って，プッシュには以下のコマンドを実行するだけでよい：

```sh
$ git push
```

コマンドを実行すると，SSHキーで認証していない場合には
認証のためにGitHubのユーザー名とパスワードの入力が求められる．
ここで入力するパスワードは，作成したパーソナルアクセストークンである（[パーソナルアクセストークンを作成](#パーソナルアクセストークンを作成)を参照せよ）．

プッシュが成功すると，GitHub上のリポジトリの情報も更新されているはずである．

## パブリック・プライベートの切り替え

「文書作成途中はプライベートで，完成した段階でパブリックに」という運用をすることも考えられる．
あるいは，「文書に重大な間違いが見つかったので，修正するまで一時的に非公開としておく」といったこともあるだろう．
その場合，次のようにして切り替える：

1. GItHub上でそのリポジトリを開く．
1. ページ上部のメニューから歯車アイコンとともにある「Settings」を選択する．
1. 「Options」メニュー下部にある「Change visiblity」ボタンをクリックする．
1. 「Make public」か「Make private」のうち適切な方を選択する．
1. 確認のため，「ユーザー名/リポジトリ名」を入力する．
1. 「I understand, change repository visiblity」ボタンをクリックする．


# ローカルリポジトリを独立して作成する場合の運用

ここでは，リモートリポジトリをクローンせず，ローカルリポジトリを独立して作成する場合の運用を述べる．

## ローカルリポジトリの作成

まず，Gitに管理させたいディレクトリに移動する．そして，そのディレクトリ上で以下のコマンドを実行する：

```sh
$ git init
```

`git init`コマンドはリポジトリの新規作成を行うコマンドであり，これによってステージング・エリアやローカルリポジトリが作成される．
リモートリポジトリと関係ない`git add`や`git commit`はこの時点でも上で述べたものと同様にできる．

## リモートリポジトリの作成

これは上と同様である．ただし，`.gitignore`とライセンスは作成しない．ファイルが1つも存在しない空のリポジトリを作成する．

## リポジトリの紐づけ

作成したローカルリポジトリとリモートリポジトリを紐づけする．
紐づけしたいローカルリポジトリがあるディレクトリに移動し以下のコマンドを実行する（URLは紐づけしたいリモートリポジトリのものを入力）：

```sh
$ git remote add origin https://github.com/<UserName>/<RepositoryName>
```

ここに書かれている「origin」は，リモートリポジトリに対してGitがデフォルトでつけている名前を表す．
つまり，このコマンドはローカルリポジトリが想定するリモートリポジトリに作成したリモートリポジトリを
加える操作を表すことになる．

## mainブランチの作成

次にmainブランチというブランチを作成する[^6]．

```sh
$ git branch -M main
```

[^6]: ブランチについては本記事では省略する．ここではおまじないと思ってよい．

## GitHub上でのファイルの追加

このやり方では`.gitignore`やライセンスは自動生成できないのではないか，などと心配する必要はない．
次の手順で途中からでも自動生成できる：

1. GitHub上でそのリモートリポジトリを開く．
1. 「Add file」ボタンをクリックし，「Create new file」を選択する．
1. 作成するファイル名に「.gitignore」もしくは「LICENSE」を入力する．
1. 右側の「Cancel changes」ボタンの隣に「Choose .gitignore ▼」もしくは「Choose a license template」ボタンが現れるのでそれをクリックする．
1. 適切なものを選ぶ．
1. 下部の「Commit directly to the `main` branch.」にチェックが入っていることを確認（入っていなければチェックを入れる）し，緑色の「Commit new file」をクリックする．

## リモートリポジトリ更新の反映 

上記手順で行われたリモートリポジトリの変更は，ローカルリポジトリには反映されていない．以下のコマンドを実行することで反映させることができる：

```sh
git pull
```

## プッシュ

以下のコマンドを実行する：

```sh
$ git push -u origin main
```

`-u origin main`なるものがくっついているが，これはoriginという名前がついたリモートリポジトリのmainブランチにpushするという意味で，`-u`オプションはこれを（上流ブランチとして）設定するという意味である．
細かい意味はともかく，このオプションにより次回以降のプッシュではこの部分は省略して`git push`のみでプッシュできるようになる．