過去のUnityプロジェクトを整理したあと、GitHubのPrivateリポジトリへ保存する作業を進めた。
最初は、
GitHubへ上げる
=
git pushする
くらいの理解だった。
ただ、実際に作業してみると、
Git
GitHub
GitHub CLI
PowerShell
はそれぞれ役割が違っていた。
今回は、実際に使ったコマンドをもとに、
ローカルでGit管理する
↓
GitHubにリポジトリを作る
↓
GitHubへpushする
までの流れを整理する。
まずGitとGitHubは別
今回一番整理できたのがここだった。
Gitは、PC内でファイルの変更履歴を管理する仕組み。
一方GitHubは、そのGitリポジトリをネット上に保存・共有できるサービス。
つまり、
Git
→ ローカルPC上で履歴を管理する
GitHub
→ Gitリポジトリをネット上に保存する
という違いがある。
さらに今回使った gh は、GitHub CLIというツール。
GitHubのWeb画面で行う操作を、PowerShellなどのコマンドラインから実行できる。
PowerShellはこれらを実行する場所
たとえば、
PS C:\Users\User>
と表示されているPowerShell上で、
git init
や、
gh repo create...
を実行していた。
つまり、
PowerShell
↓
Gitのコマンドを実行する
PowerShell
↓
GitHub CLIのコマンドを実行する
という関係。
全部PowerShell上に表示されるので最初は同じものに見えたが、実際には別のプログラムを呼び出している。
git init でGit管理を始める
まず使ったのが、
git init
このコマンドは、
現在のフォルダを
Gitで管理するリポジトリにする
という意味。
実行すると、そのフォルダ内に、
.git
という隠しフォルダが作られる。
この .git の中に、Gitの履歴や設定などが保存される。
この時点ではまだGitHubには何も作られていない。
あくまで、
PCの中でGit管理を開始した
だけ。
git add. でコミット対象にする
次に、
git add.
を実行した。
これは、
現在のフォルダ以下にある変更を
次のコミット対象として登録する
という意味。
最後の、
.
は現在のフォルダを表している。
そのため、
git add.
は、
現在のフォルダ以下をまとめて対象にする
という指定になる。
.gitignore で不要なファイルを除外する
Unityプロジェクトの場合、すべてのファイルをGitHubへ保存する必要はない。
たとえば、
Library
Temp
Logs
obj
などはUnity側で再生成できる。
そのため .gitignore に、
[Ll]ibrary/
[Tt]emp/
[Oo]bj/
[Ll]ogs/
UserSettings/
MemoryCaptures/
[Bb]uild/
[Bb]uilds/
.vs/
.vscode/
.idea/
*.csproj
*.sln
などを書いた。
これによって git add. をしても、これらのファイルはGit管理対象から外れる。
今回GitHubへ保存したかった中心は、
Assets
Packages
ProjectSettings
だった。
git commit で履歴として保存する
次に、
git commit -m "Initial commit"
を実行した。
これは、
git addで選んだ変更を
Gitの履歴として保存する
という意味。
-m
はコミットメッセージを指定するオプション。
今回は最初の保存だったので、
Initial commit
とした。
ここまで、
git init
git add.
git commit -m "Initial commit"
を実行しても、まだGitHubには何も送られていない。
ここまでは全部ローカルPC上のGit操作。
git branch -M main でブランチ名をそろえる
次に、
git branch -M main
を使った。
これは現在のブランチ名を、
main
へ変更するコマンド。
環境によっては最初のブランチ名が master になることがある。
今回はGitHub側とそろえるために main にしていた。
GitHub側にリポジトリを作る
ここで初めてGitHub側の操作が出てくる。
使ったのがGitHub CLIの、
gh repo create <repo-name> --private
このコマンドは、
GitHub上に
新しいPrivateリポジトリを作る
という意味。
ブラウザで、
New repository
↓
名前を入力
↓
Privateを選択
↓
Create repository
としていた操作を、コマンドから実行している。
git remote add origin でGitHubとの接続先を登録する
GitHub側にリポジトリを作っただけでは、ローカルGitとはまだつながっていない。
そこで、
git remote add origin https://github.com/<owner>/<repo-name>.git
を使う。
これは、
このGitHubリポジトリを
ローカルGitの送信先として登録する
という意味。
ここでの、
origin
は、リモートリポジトリにつける名前。
一般的に最初のリモート先を origin と呼ぶことが多い。
すでに origin がある場合
過去のプロジェクトでは、すでに別のGitHubリポジトリが登録されていることもあった。
その場合、
git remote add origin...
ではなく、
git remote set-url origin https://github.com/<owner>/<repo-name>.git
を使った。
これは、
既存のoriginのURLを
新しいGitHubリポジトリへ変更する
という意味。
git push -u origin main でGitHubへ送る
最後に、
git push -u origin main
を実行した。
これは、
ローカルのmainブランチを
originとして登録したGitHubへ送る
という意味。
分けると、
git push
→ GitHubへ送る
origin
→ 送信先
main
→ 送るブランチ
になる。
さらに、
-u
を付けることで、
ローカルのmain
↓
origin/main
という対応関係も登録される。
そのため、次回以降は、
git push
だけでも送れるようになる。
全体の流れ
ここまでを並べると、
Unityプロジェクト
↓
git init
Git管理を開始
↓
git add.
コミット対象にする
↓
git commit
ローカルGitに履歴として保存
↓
gh repo create
GitHub側にPrivateリポジトリを作る
↓
git remote add origin
ローカルGitとGitHubを接続する
↓
git push
GitHubへ履歴を送る
という流れになる。
最初は全部まとめて、
GitHubにアップロードする処理
と考えていたが、実際にはそれぞれ別の役割を持っていた。
gh repo view でリポジトリが存在するか確認する
複数のプロジェクトを自動でアップロードしていると、
すでにGitHubにあるものは飛ばしたい
という必要が出てきた。
そこで、
gh repo view "<owner>/<repo-name>"
を使った。
これは指定したGitHubリポジトリの情報を表示するコマンド。
リポジトリが存在すれば成功する。
自動処理では、
gh repo view "<owner>/<repo-name>" *> $null
のようにした。
*> $null
は、
画面への出力を捨てる
という意味。
今回は中身を表示したいのではなく、
存在するかどうかだけ知りたい
ために使った。
$LASTEXITCODE で成功・失敗を確認する
git や gh はPowerShellの外部プログラム。
実行結果は、
$LASTEXITCODE
で確認できる。
一般的に、
0
→ 成功
0以外
→ 失敗
として扱える。
たとえば、
gh repo view "<owner>/<repo-name>" *> $null
if ($LASTEXITCODE -eq 0) {
Write-Host "すでに存在します"
}
なら、
GitHubリポジトリが存在したら
「すでに存在します」と表示する
という処理になる。
gh repo list でリポジトリ一覧を取得する
既存リポジトリをまとめて確認するために、
gh repo list <owner> --limit 500 --visibility private
も使った。
これは、
指定したアカウントの
Privateリポジトリを一覧取得する
という意味。
名前だけ欲しい場合は、
gh repo list <owner> `
--limit 500 `
--visibility private `
--json name `
--jq '.[].name'
とした。
これによって、
GitHubにすでにあるリポジトリ名
を取得して、PC側のUnityプロジェクトと比較できる。
大量作成するとGitHub側の制限に当たった
複数のUnityプロジェクトを順番にGitHubへ上げていると、
GraphQL:
You have created too many repositories, too quickly.
Please try again later.
というエラーが出た。
最初は、
git pushで失敗している?
と思った。
しかし実際に失敗していたのは、
gh repo create
の部分だった。
つまり、
git init
git add
git commit
など、ローカル側のGit処理は終わっている。
その後、
GitHubに新しいリポジトリを作る
ところで制限に当たっていた。
ここでも、
Git
↓
GitHub
を分けて考えることが役立った。
最初は10分待って再試行していた
最初のスクリプトでは、リポジトリ作成に失敗すると、
Start-Sleep -Seconds 600
としていた。
これは、
600秒
=
10分
待つ処理。
その後もう一度、
gh repo create
を実行していた。
しかし、10分待っても解除されないことがあり、3回試しても同じエラーになることがあった。
制限に当たったら停止する形へ変更した
最終的には、
GitHub作成制限に当たる
↓
その場で処理を終了
↓
作成途中のGitリポジトリは残す
↓
次回また実行して再開する
という方式に変えた。
無理に再試行し続けるより、
途中まで終わった作業を保存して
次回そこから再開する
形にした方が扱いやすかった。
一時Gitリポジトリを再利用した
GitHub側のリポジトリ作成に失敗しても、
Assets
Packages
ProjectSettings
.git
まで作成済みの場合がある。
その場合、
Test-Path (Join-Path $exportPath ".git")
で .git の存在を確認した。
.git があれば、
git init
git add
git commit
まで終わっていると判断し、その一時Gitリポジトリを次回再利用するようにした。
これでGitHub側の制限に当たっても、ローカル作業を最初からやり直す必要がなくなった。
今回整理できた役割
今回使ったものを整理すると、
PowerShell
→ 処理全体を組み立てる
Git
→ PC内で履歴を管理する
GitHub
→ Gitリポジトリをネット上に保存する
GitHub CLI
→ GitHubをコマンドから操作する
という役割だった。
特に、
git commit
と、
gh repo create
は全く別の処理。
git commit はPC内のGit履歴を作る。
gh repo create はGitHub上に保存先を作る。
そして、
git push
で両方をつなぐ。
まとめ
今回よく使ったGitのコマンドは、
git init
Git管理を始める
git add.
変更をコミット対象にする
git commit
ローカルの履歴として保存する
git branch -M main
ブランチ名をmainにする
git remote add origin
GitHubの接続先を登録する
git push
ローカルの履歴をGitHubへ送る
GitHub CLIでは、
gh repo create
GitHubリポジトリを作る
gh repo view
特定のリポジトリを確認する
gh repo list
リポジトリ一覧を取得する
を使った。
最初は、
GitHubへアップロードする
という1つの作業に見えていた。
実際には、
ローカルでGit管理する
↓
GitHub側に保存場所を作る
↓
接続先を設定する
↓
pushする
という複数の処理に分かれていた。