BitBucket Serverでgit lfsを利用する


#1.Git LFSとは
Git LFSは、昨年10月[^1]にGitHubからGit LFSの正式版がリリースされた、gitの拡張機能です。
具体的な利用用途としては、大きなバイナリファイルのバージョン管理を想定した機能です。

gitでプロジェクトを運用する際、大きなバイナリファイルの管理は、
一番頭を悩ませる部分だっただけに、多くのgit管理者および利用者に嬉しい機能追加でした。
なお、現在では、SourceTreeといったgitのクライアントツールでもgit lfsが利用可能です。

【公式】
[Git LFS公式サイト](https://git-lfs.github.com/)

【参考】
[サイズの大きいバイナリファイルを扱うための Git LFS 導入](http://wp.graphact.com/2015/10/04/setup-git-lfs)
[“Git LFS”をサポート。UIデザインを一新した「SourceTree」v1.8が公開](http://www.forest.impress.co.jp/docs/news/20160223_744948.html)

#2.Bitbucket Serverでgit lfsを設定する
Bitbucket Serverは、バージョン4.3からgit lfsに対応しています。

[Bitbucket Server 4.3 release notes](https://confluence.atlassian.com/bitbucketserver/bitbucket-server-4-3-release-notes-794211212.html)

git lfsの有効化は、各リポジトリごとに設定が可能で、
下図のようにリポジトリの管理画面からgit lfs機能を有効化できます。
![gitlfs_enable.png](https://qiita-image-store.s3.amazonaws.com/0/14190/98f982a5-2e18-919c-73ee-bbf03a6f9f67.png "gitlfs_enable.png")


#3.クライアント側でgit lfsを設定する

##3-1.git lfsインストール
git lfsのインストールは、他サイトに記載されているように、
tar.gzファイルを解凍して、install.shを叩くのみです。

```
tar xfz git-lfs-darwin-amd64-1.2.0.tar.gz
cd git-lfs-1.2.0
sudo bash install.sh
```

##3-2.初期設定
`git lfs install`を実行すると、~/.gitconfigに、下記のエントリが追加されます。

```
[filter "lfs"]
	clean = git-lfs clean -- %f
	smudge = git-lfs smudge -- %f
	required = true
```

##3-3.track対象ファイルの設定
`git lfs track`を実行すると、現在のgit lfsのtrack対象ファイルを確認できます。

```
$ git lfs track
Listing tracked paths
```

このコマンド実行後、下記のように.git配下にlfsディレクトリが追加されます。

```
.git
├── HEAD
├── config
├── description
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── pre-push
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── prepare-commit-msg.sample
│   └── update.sample
├── info
│   └── exclude
├── lfs #この配下が追加される
│   ├── objects
│   │   └── logs
│   └── tmp
│       └── objects
├── objects
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags
```

今回は、*.jpgファイルをgit lfsの対象に入れました。

```
$ git lfs track "*.jpg"
Tracking *.jpg
$ git lfs track
Listing tracked paths
    *.jpg (.gitattributes)
```

#4.実行結果
##4-1.初回push
git lfsの準備ができたら、実際に1.8M程度のjpgファイルをpushしてみます。

```
$ git add dinner.jpg
$ git commit -m '夕食の画像'
[master (root-commit) 0427398] 夕食の画像
 1 file changed, 3 insertions(+)
 create mode 100644 dinner.jpg
$ git push
Git LFS: (1 of 1 files) 1.85 MB / 1.85 MB
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 340 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://git@****/****/gitlfs-sample.git
 * [new branch]      master -> master
```

pushし終わったら、別のディレクトリでcloneしてみます。

```
$ git clone ssh://git@****/****/gitlfs-sample.git
$ du -sh ./gitlfs-sample
104K	./gitlfs-sample
$ cat gitlfs-sample/dinner.jpg
version https://git-lfs.github.com/spec/v1
oid sha256:7621a0126e06e74c5876d4b32ed83068bcad9c918952439dd14969dd0e71f15d
size 1938859
```

.jpgがポインタになっているだけなので、テキストファイルとしてcloneされています。
この後、[^2]のように、`git lfs pull`を実行してあげれば、最新のバイナリファイルがpullされてきます。

##4-2.バイナリファイルを更新する
pushした写真を更新します。

```
$ git commit dinner.jpg -m '夕食の写真を間違えた'
[master fceea3b] 夕食の写真を間違えた
 1 file changed, 2 insertions(+), 2 deletions(-)
$ git push
Git LFS: (1 of 1 files) 1.31 MB / 1.31 MB
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 396 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://git@****/****/gitlfs-sample.git
   0427398..fceea3b  master -> master
```

こちらも別のディレクトリからpullして、ファイルの更新を確認します。

```
$ cat dinner.jpg
version https://git-lfs.github.com/spec/v1
oid sha256:1a02144f8c960f0aa6a6cb24fc9e5709584fe0eb212d9bf79578693af31bfdae
size 1371436
```

ハッシュキーが変更されてますね。
当然ですが、これも`git lfs pull`でpullして実ファイルを落とすことが可能です。

ちなみに、Bitbucket Serverでの画像比較は、以下のような感じになります。

![hikaku1.png](https://qiita-image-store.s3.amazonaws.com/0/14190/e6525a92-bc42-75df-622e-8627b1ec41c5.png "hikaku1.png")
![hikaku_2.png](https://qiita-image-store.s3.amazonaws.com/0/14190/45df1d35-13d9-c863-bb01-e17fa31c1643.png "hikaku_2.png")
![hikaku_3.png](https://qiita-image-store.s3.amazonaws.com/0/14190/e99ed423-23b7-b983-cacc-cb3ed35ef603.png "hikaku_3.png")
![hikaku_4.png](https://qiita-image-store.s3.amazonaws.com/0/14190/0d06e0a5-8f15-6f05-2697-e67d0c7dc3c8.png "hikaku_4.png")



#5.git lfs関連の実行メモ
## 5-1.サーバ側のアクセスログ

```
*.*.*.* - - [17/Apr/2016:22:17:14 +0900] "POST /scm/****/****.git/info/lfs/objects/batch HTTP/1.1" 200 771 "-" "git-lfs/1.1.2 (GitHub; darwin amd64; go 1.6; git bf6a6c9)" "-" 0.078
*.*.*.* - - [17/Apr/2016:22:17:15 +0900] "PUT /rest/git-lfs/storage/****/****/7621a0126e06e74c5876d4b32ed83068bcad9c918952439dd14969dd0e71f15d HTTP/1.1" 200 5 "-" "git-lfs/1.1.2 (GitHub; darwin amd64; go 1.6; git bf6a6c9)" "-" 0.905
```

`git push`した際、このようにPOSTのアクセスログが記録されます。
また、`git lfs pull`したときは、以下のログが出力されます。

```
*.*.*.* - - [24/Apr/2016:23:54:32 +0900] "POST /scm/****/****.git/info/lfs/objects/batch HTTP/1.1" 200 782 "-" "git-lfs/1.2.0 (GitHub; darwin amd64; go 1.6.1; git 9bd3b8e)" "-" 0.076
*.*.*.* - - [24/Apr/2016:23:54:36 +0900] "GET /rest/git-lfs/storage/****/****/f7f3a2d4b9d38cbf0466ad555e049b5603ce21896dc2f5f6db5b794680756054 HTTP/1.1" 200 1190697 "-" "git-lfs/1.2.0 (GitHub; darwin amd64; go 1.6.1; git 9bd3b8e)" "-" 4.198
```

両ログとも、UserAgentにgit lfsのバージョンが記録されているのもわかるかなと。

## 5-2.クライアントのgitエラー

```
Git LFS: (2 of 1 files) 266.44 KB / 1.85 MB
Client error: https://****/rest/git-lfs/storage/****/****/7621a0126e06e74c5876d4b32ed83068bcad9c918952439dd14969dd0e71f15d from HTTP 413
```
Bitbucket Serverの前段にnginxなどのwebサーバを配置していると、
このようにHTTPステータスコードが413で返ってくるときがあります。
そのときは、POSTサイズの容量制限に引っかかっているため、
nginxの`client_max_body_size`を変更するなどして、POSTのサイズ制限を緩和してあげる必要があります。

```
client_max_body_size 1024M; #利用ファイルのサイズに応じて変更
```


#6.TL;DR
まとめとしては、以下の通り

- Bitbuclet Serverがバージョン4.3からgit lfsに対応し、追加費用なしで利用可能
- nginxなどでリバースプロキシを行っている場合は、POSTサイズ制限に注意が必要
- SourceTreeなどのクライアントツールでも、git lfsが使える
- `git lfs pull`で、必要なときに実体ファイルを落としてくることが可能

何かのご参考になれば。

[^1]: [GitHub、Gitで画像や動画など大容量ファイルを扱える「Git LFS」（Git Large File Storage）正式リリース](http://www.publickey1.jp/blog/15/git_lfs.html)
[^2]: [Git LFSが1.0になってGitHubで使えるようになったので試してみた](http://qiita.com/kiida/items/0d51c43ac73f14f09f5a)