はじめに
個人で細々と Visual Studio Code のExtensionを作って公開しています。
テストデータや画像ファイルなど master ブランチには含めたくないものをどうやって管理するか悩んでいました。
merge ドライバーを使って特定のファイルを除外する方法は、設定が悪いのかもしれませんが機能しませんでした。
(衝突が起きないために merge ドライバーが呼ばれないのだと思いますが)
そこでそれ以外の方法を模索してみました。
環境
Windows 10 Pro 64bit
git version 2.27.0.windows.1
要件
管理しなければいけないデータは、以下のようなものです。
- npm(Atom)で管理できるパッケージ
- メインコンテンツ
- 自作の共通ライブラリ
- 別のパッケージと共通で使う自作ライブラリ(npm モジュール)
- パッケージのためのバイナリデータ
- jpg などの画像データ
- テストのためのデータおよびテストコード
- テストフレームワークのコード
- テストデータ
- 開発中のアイデア等を書き込んでおくメモなど
このうち、テストのためのデータや画像データは、リポジトリで管理しますが公開するパッケージには含めないことにします。
バイナリデータは、常に最新の物のみ管理することにします。
履歴は要りません。
テストコードも履歴を管理します。
必要なファイルの概要は、以下のようになります。
/package
main.js
readme.md
...
/library
main.js
...
/image
image.jpg
...
/test
/testCode
main.test.js
...
/testData
test1.txt
test2.txt
...
todo.txt
リポジトリの構成
要件を満たすためのリポジトリ構成は、以下のようにしました。
なお、個人で開発していますので衝突が起こることは考えていません。
また、最悪リモートリポジトリを作り直すことも出来るものとしています。
- 公開用のリモートリポジトリ
- リリースのための master ブランチ
- 開発のための develop ブランチ
- バイナリデータのための binary(image)ブランチ
- テストのための test ブランチ
- 作業用のローカルリポジトリ
- master ブランチ
- 開発のための develop ブランチ
- バイナリデータのための binary(image)ブランチ
- テストのための test ブランチ
運用方針
- リモートリポジトリは、GitHub もしくは GitBucket を使う。
単純ですが、準備も必要なく無料で使えるからです。
- 複数のパッケージで使う自作ライブラリは、それ単体で npm パッケージとして公開する。
サブモジュールで実現しようとしましたが、Atom のパッケージマネージャがバージョンなどをうまく解決できない等の不都合がありました。
余計なことをしないで既存の便利な仕組みを使うことにします。
- バイナリデータは独立(orphan)ブランチで管理する。
リリースするデータに含めずに Git で管理するためです。
また、バックアップの意味でリモートリポジトリに上げておきます。
- README に必要な画像データに関して、GitHub の Issue を使ったテクニックは使わない。
GitHub がサポートしているか不透明だからです。
- 場合によっては、バイナリデータは GoogleDrive などのクラウドストレージを使う。
容量などの問題で必要に応じて選択します。
もっとも、ダウンロードの仕組みの煩雑化や、一元管理できなくなるなど避けたいところです。
- バイナリデータの管理に、Git LFS を使わない。
不特定多数の人にダウンロードされる都合上、ダウンロード制限がある GitHub では使えません。
また、容量制限に関してもバイナリファイルを更新するごとに容量を圧迫します。
いちいち容量を減らすためにリポジトリから古いデータを削除するぐらいならば、LFS を使わなくても運用で何とかなります。
もともと、バイナリデータは、最新のものしか管理するつもりがないので古いデータを削除してから新しいファイルをプッシュすることにします。
これは、面倒なので改善したい点です。
-
改行コードは全て
LF
にする
Windows で開発を行っていますがCRLF
によるメリットは何もないのでLF
に統一します。 -
コミットは機能単位で細かく分ける。もしくは、リリース毎に 1 つ程度にまとめてしまう。
-
merge ドライバーによる除外は、使用しない
./.git/config に以下のように追記し、
[merge "ours"]
driver = true
.gitattributes に
.gitignore merge=ours
とする方法は、残念ながらうまく行きせんでした。
衝突が起きた時は、うまく行ったりもするのですが、基本的に自分一人で作っているので衝突が起きずにうまく行かないことの方が多いです。
そのためこの方法は諦めました。
運用に即して使うコマンドあれこれ
リポジトリの作成
master と develop ブランチの.gitignore には以下を追加しておく。
.gitignore
todo.txt
test
image
image ブランチは orphan ブランチとして作成する。
git init
echo "main" > main.js
echo "readme" > readme.md
git add main.js
git add readme.md
echo "todo.txt" > .gitignore
echo "image" >> .gitignore
echo "test" >> .gitignore
git add main.js
git add readme.js
git add .gitignore
git commit -m "frist commit"
git remote add origin <URL>
git push -u origin master
git switch -c develop
echo "script" > script.js
git add script.js
git commit -m "first develop"
git push -u origin develop
git switch -c test
git rm .gitignore
echo "image" >> .gitignore
git add .gitignore
mkdir test
mkdir test/testCode
echo "main.test" > test/testCode/main.test.js
echo "script.test" > test/testCode/script.test.js
mkdir test/testData
echo "01" > test/testData/01.txt
echo "02" > test/testData/02.txt
git add test
echo "todo" > todo.txt
git add todo.txt
git commit -m "first on test"
git push -u origin test
git switch -orphan image
git rm -rf .
echo "todo.txt" > .gitignore
echo "test" >> .gitignore
git add .gitignore
mkdir image
echo "image" > image/image.jpg
git add image
git commit -m "first on image"
git push -u origin image
git switch master
powershell で実行すると改行コードが CRLF
になってしまいますが、実際には LF
でのみ作成します。
作業ブランチ
開発作業をする場合は、常にdevelopブランチで行う。
ある程度まとまったらテストデータを取って来るか、testブランチに切り替えてdevelopブランチをマージする
git switch develop
... //作業
git push
git switch test
git merge develop
... //テスト作業
git push
git switch master
git merge develop
... //リリース
git push
git switch develop
git rebase(merge) master
git push
画像データのリンクについて
README などから画像データにアクセルする場合のリンクの指定方法は以下のようになります。
- GitHub のリポジトリにあるファイルの場合、以下のようにすれば参照できる。
https://raw.githubusercontent.com/UserName/RepositoryName/BranchName/FileName
- GoogleDrive に保存した場合、以下のようにすれば参照できる。
- 共有リンクを取得する
https://drive.google.com/open?id=ID
- そして以下の形式に変更して記述する
http://drive.google.com/uc?export=view&id=ID
- 共有リンクを取得する
- DropBox に保存した場合、以下のようにすれば参照できる。
- 共有リンクを取得する
https://www.dropbox.com/s/FileName?dl=0
- そして以下の形式に変更して記述する
https://www.dropbox.com/s/FileName?raw=1
- 共有リンクを取得する
バイナリファイルを消すときに使うコマンド
履歴からPATH-TO-DATA
で示されるファイルを全て削除する。
全てのブランチから削除したいならば最後に--all
を付ける。
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch PATH-TO-DATA' --prune-empty --tag-name-filter cat
フォルダの場合は、以下になる。
git filter-branch --force --index-filter 'git rm -rf --cached --ignore-unmatch PATH-TO-DATA' --prune-empty --tag-name-filter cat
削除結果をリモートに反映させる。
こちらも全てのブランチから削除したならば最後に--all
を付ける。
git push origin --force
タグがある場合は、以下も行う。
git push origin --force --tags
refs/original フォルダに保存されているオブジェクトを削除する。
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
reflog を削除する。
git reflog expire --expire=now --all
ファイルを消した履歴とそれにアクセス出来そうな履歴だけを削除したいならば以下を使って個別に消す。
もっとも十分な知識がないと整合性が取れなくなる恐れがある。
git reflog delete refs
到達不能オブジェクトの削除と最適化
git gc --prune=now
もしくは、
git gc --prune=now --agressive
test コードへのアクセス
ファイルを取ってくる場合は、以下のように行う。
git restore --source=test test
(git restore --staged test)
テストを更新したい場合は、test ブランチへ切り替えてから行う。
最後に
まだまだ決して使いやすいものになっていません。
色々と改善していきたいものです。
そもそも、orphan ブランチを別リポジトリにしてしまうのも 1 つの方法のようですが。
Git が油汚れでギットギットになってからでは遅いんです。(`・ω・´)