Gitでなるべくストレージ容量を節約したい


# Gitでストレージをなるべく節約する。
## shallow cloneの場合
## git clone --depth 1
```sh
git clone --depth 1 <URL>
```
### 複数のブランチとタグ情報をclone[^3]
```sh
git clone --depth 1 --no-single-branch <URL>
```
[^3]: https://zenn.dev/tetsu_koba/articles/77347ef2c283ac
### 過去履歴がほしいとき。
```sh
git fetch --depth 100
```

### タグ情報が欲しい時
```sh
git fetch --tags
```

### メインブランチ以外にcheckoutしたい場合
SUB_BRANCHにチェックアウトする場合
```sh
git fetch origin SUB_BRANCH:SUB_BRANCH
git checkout SUB_BRANCH
git push -u origin SUB_BRANCH
```

### shallow clone解除（全履歴）
全履歴取得なので、時間もかかるし、ストレージの負担は大きい。
```sh
git fetch --unshallow
```

### shallow cloneを解除して、partial cloneのfilterを用いる場合
git describe --tagsでタグが見つからず、表示されない場合にも使える。
```sh
git fetch --filter=tree:0 --no-recurse-submodules --unshallow
```
or
```sh
git fetch --filter=blob:none --no-recurse-submodules --unshallow
```
```sh
git describe --tags
```

filterを指定しておくと、unshallowで、すべてを取得せず、最低限のみ取得してくれているっぽい。
パーシャルクローン(partial clone)というらしい。[^1][^2]
[^1]: https://qiita.com/irgaly/items/0aace5cbd44aa4220733
[^2]: https://github.blog/jp/2021-01-13-get-up-to-speed-with-partial-clone-and-shallow-clone/

`--filter=tree:0`
`--filter=blob:none`

mirrorレポジトリでsubmoduleを扱う場合には、partial cloneの利用は、ちょっと注意が必要みたい。

## partial cloneで最初からcloneする場合
clone時にfilterを指定し、partial cloneをする。
```sh
git clone --filter=blob:none <URL> <REPOSITORY>
```
or
```sh
git clone --filter=tree:0 <URL> <REPOSITORY>
```

ローカルでcloneできるかチェック。
```sh
git clone <REPOSITORY> <CLONE_TEST>
cd <CLONE_TEST>
git describe --tags
cd ..
rm -rf <CLONE_TEST>
```

### partial clone & mirror
clone後、git worktreeコマンドで、checkoutすることで、objectsデータをfetch(ダウンロード)しておく。その後、removeで作業ツリーを削除して、容量を節約する。
```sh
git clone --mirror --filter=tree:0 <URL> <REPOSITORY>
cd <REPOSITORY>
git worktree add tmp
git worktree remove tmp
git branch -d tmp
cd ..
```
ローカルでcloneできるかチェック。
```sh
git clone <REPOSITORY> <CLONE_TEST>
cd <CLONE_TEST>
git describe --tags
cd ..
rm -rf <CLONE_TEST>
```

## Arch、ManjaroでPKGBUILDのgitソースのストレージ節約
### shallow clone & partial clone
PKGBUILDにgit+httpsなどで、gitレポジトリがソースに指定されている場合、makepkgコマンドで作られるmirrorフォルダは下記gitコマンドと同じ形式で作成される模様。
```sh
git clone --mirror URL
```
容量を節約しつつ、makepkgの作業レポジトリ作成の時間も増やさない手順。
1. mirrorを--depth 1でcloneする。(shallow clone)
2. cloneしたフォルダに移り、`--filter=tree:0`と`--unshallow`を指定してfetchする。(shallow解除＆partial)
```sh
git clone --mirror --depth 1 <URL> <REPOSITORY>
cd <REPOSITORY>
git fetch --filter=tree:0 --no-recurse-submodules --unshallow
cd ..
```
1の手順のみだと、`--depth 1`を指定しないcloneと比べて、作業レポジトリのコピーに時間がかかる。  
2の手順を行うと、その時間が短縮される。  
またclone時にfilterを指定すると、makepkgコマンドで作業コピーが失敗する。必要なobjectsファイルがダウンロードされていないためで、worktreeコマンドなどを利用して、あらかじめfetchしておくことで対処できる。その方法は、次の項目を参照してください。

また以下のコマンドでcloneすると、tag情報の同期がされないので、別途オプション指定が必要そうです。
(tag情報などでpkgverが更新される場合もあるので、tag情報なども必要になってきます。)
```sh
git clone --bare --depth 1 <URL> <REPOSITORY>
```
```sh
git clone --bare --config remote.origin.mirror=true --depth 1 <URL> <REPOSITORY>
```

### partial clone
最初にcloneする時点で、filterを指定してpartial cloneを行う場合。  
clone後、git worktreeコマンドで、checkoutしておき、objectsデータを一通りfetch(ダウンロード)しておく。容量節約のために、その後、worktreeをremoveしておく。この手順を追加することで、makepkgコマンドで作業コピーが失敗するのを回避できる。mirrorレポジトリなので、checkoutコマンドなどは使えないが、worktreeコマンドなどは利用できる。
```sh
git clone --mirror --filter=tree:0 <URL> <REPOSITORY>
```
or
```sh
git clone --mirror --filter=blobe:none <URL> <REPOSITORY>
```
```sh
cd <REPOSITORY>
git worktree add tmp
git worktree remove tmp
git branch -d tmp
cd ..
```
ローカルでcloneできるか、tag情報が取得できているかなどをチェックする。
```sh
git clone <REPOSITORY> <CLONE_TEST>
cd <CLONE_TEST>
git describe --tags
cd ..
rm -rf <CLONE_TEST>
```

### scalarを用いる
`--full-clone`を指定しておくと、活用できそうです。
```sh
scalar clone -b <BRANCH> --no-src --full-clone <URL> <REPOSITORY_TMP>
cd <REPOSITORY_TMP>
git config --bool core.bare true
git config fetch.showForcedUpdates true
cd ..
mkdir <REPOSITORY>
mv <REPOSITORY_TMP>/.git/* <REPOSITORY>
scalar unregister <REPOSITORY_TMP>
rm -rf <REPOSITORY_TMP>
```

## github fork元のタグを取得
upstreamからタグ情報を取得する手順例
```sh
git remote add upstream <fork元のリポジトリ>
git fetch upstream --filter=tree:0 --no-recurse-submodules --unshallow
git describe --tags upstream/master
git describe --tags origin/master
git push origin --tags
```
[^4]: https://zenn.dev/tetsu_koba/articles/77347ef2c283ac
[^5]: https://qiita.com/jsasaki/items/f77c23f4fea3f7edb812

# 参考サイト
[Git の最新アップデートから考える開発手法の潮流](https://speakerdeck.com/yuukiyo/trends-in-development-methodology-from-the-latest-git-updates?slide=34)
[パーシャルクローンとシャロークローンを活用しよう](https://github.blog/jp/2021-01-13-get-up-to-speed-with-partial-clone-and-shallow-clone/)[^2]
[git リポジトリを clone 後に軽量化する (blobless化)](https://qiita.com/irgaly/items/0aace5cbd44aa4220733)[^1]
[以前forkしたgithubリポジトリを追従させる方法](https://zenn.dev/tetsu_koba/articles/77347ef2c283ac)[^4]
[Github で fork したリポジトリの簡便な同期と運用](https://qiita.com/jsasaki/items/f77c23f4fea3f7edb812)[^5]
[Git で shallow clone するときに全ブランチの最新履歴を取得する](https://zenn.dev/snowcait/articles/d44d6b2bed2e4b29ada4)[^3]