BFGを使用するにあたって色々調べてみた
BFGとは
git-filter-branch
の代わりに使うことができる(事もある)
概要
git-filter-branchと比較して
- 10 - 720倍高速に動作する
- よりシンプル
- コードが公開されているのでカスタマイズして使用できる
使い所
- git-filter-branchのオプションが結構複雑なのでシンプルに実行したいとき
- git-filter-branchでは時間がかかりすぎて終りが見えないとき
といった感じ。
各オプションの詳細はこちら
使用してみる
BFGの実行ファイルダウンロード
# Homebrewでも入れられるらしい $ wget http://repo1.maven.org/maven2/com/madgag/bfg/1.12.14/bfg-1.12.14.jar $ java -version java version "1.8.0_102" Java(TM) SE Runtime Environment (build 1.8.0_102-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)
まずは検証用に適当なリポジトリを作成。
空のリポジトリを作成
# bareリポジトリ $ mkdir hoge_bare.git $ cd hoge_bare.git $ git init --bare Initialized empty Git repository in /Users/USER_NAME/Documents/bfg_test/hoge_bare.git/ # gitリポジトリ $ cd .. $ mkdir hoge $ cd hoge $ git init Initialized empty Git repository in /Users/USER_NAME/Documents/bfg_test/hoge/.git/ # bareをremoteとして登録 $ git remote add origin ../hoge_bare.git $ git remote -v origin ../hoge_bare.git (fetch) origin ../hoge_bare.git (push) # 適当な画像を置いてcommit push $ git add . $ git commit -m "initial commit" [master (root-commit) 14668fc] initial commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 1.png $ git push origin master (master) Counting objects: 3, done. Delta compression using up to 4 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 54.77 KiB | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To ../hoge_bare.git * [new branch] master -> master
適当にブランチを切ったりしてワークツリーを作成し、remoteにpushしておく
ここでは1コミットにpngファイルを1つコミットしている。
実際にやってみる
パターン①:特にオプションを付けない(png指定のみ)
# bareからmirrorでcloneする $ git clone --mirror hoge_bare.git hoge_test1.git $ java -jar bfg-1.12.14.jar --delete-files '*.png' hoge_test1.git $ cd hoge_test1.git $ git reflog expire --expire=now --all && git gc --prune=now --aggressive $ cd .. $ git clone hoge_test1.git hoge_result1
オプションなしの場合、HEADが指しているブランチのみプロテクトの対象となり、最新のコミットが保持される。
masterでは最初のコミットと、5番目のコミットで追加されたpngファイルが残っており、一番最初に追加した画像が5番目のコミットで追加したことになっている。
hogeブランチやfugaブランチは何も無かったことに。
masterの1番最初のコミットでの画像追加が無かったことに。
パターン②:--no-blob-protectionオプションを付けてみる
このオプションは対象ファイルを履歴上からも全て消し去る。
# bareからmirrorでcloneする $ git clone --mirror hoge_bare.git hoge_test2.git $ java -jar bfg-1.12.14.jar --no-blob-protection --delete-files '*.png' hoge_test2.git $ cd hoge_test2.git $ git reflog expire --expire=now --all && git gc --prune=now --aggressive $ cd .. $ git clone hoge_test2.git hoge_result2
消え去っている。
master以外のブランチからも削除されている。
完全に消し去りたい時はこれで良さそう。
パターン③:--protect-blobs-fromオプションを付けてみる
--protect-blobs-fromでは、プロテクトするブランチを指定できる。
master, hogeブランチをプロテクト対象にする。
# bareからmirrorでcloneする $ git clone --mirror hoge_bare.git hoge_test3.git $ java -jar bfg-1.12.14.jar --protect-blobs-from master,hoge --delete-files '*.png' hoge_test3.git $ cd hoge_test3.git $ git reflog expire --expire=now --all && git gc --prune=now --aggressive $ cd .. $ git clone hoge_test3.git hoge_result3
masterは、パターン①と同様で、masterブランチで追加したファイルが最新のコミットにまとめらている。
hogeブランチは、masterからの派生時に存在した1.png
とhogeブランチで追加した画像2つが最新のコミットでaddされたことになっている。
当然、2.png
を追加した時点のコミットは空コミットに。
fugaブランチはプロテクトの対象にしなかったので、画像は追加されない。
masterにhogeブランチとfugaブランチをそれぞれマージしてみる。
fugaブランチのコミット履歴上、何も追加していないことになっているので、fugaブランチのマージ履歴は空に。
hogeブランチのマージでは、2.png
, 4.png
が正しくマージされる。
1.png
もhogeの最新コミット履歴で追加したことになっていたけど、ここでコンフリクトなどは発生しない。
最終的なmasterブランチでは、fugaブランチで追加した画像ファイル以外の画像がちゃんと残っている。
その他注意点
- --delete-foldersはパスの区切り文字を使えず、フォルダ名のみで探して削除するので、同名のフォルダが違うパスで存在する場合、両方とも削除されてしまう。(未検証)
- 特定のフォルダ以下を対象にするといった事はできない。(未検証)
- bfg自体はかなり高速に動作するものの、その後の
git gc --prune=now --aggressive
はファイル数やサイズによっては結構時間がかかる。 - それでもgit-filter-branchより速い
- CPUコア数でかなり差が出るのでMac Book Pro 13inchとかだと結構辛い
雑感
ウィッチャー3を購入!
PS4版 ウィッチャー3(GAME OF THE YEAR EDITION)をAmazonで購入し、届きました。
まだプレイしていないけど、以下のようなゲームのようです。
オープンワールド
FF15で日本国内でも知名度が一気に上がった気がするけど、本格的なオープンワールドゲームらしい。
オープンワールド (Open World) とは、英語におけるコンピュータゲーム用語で、舞台となる広大な世界を自由に動き回って探索・攻略できるように設計されたレベルデザインを指す言葉である。
FF15はクリアするまではプレイしたのでなんとなく分かった気になっていたものの、ウィッチャー3をプレイした後にFF15をプレイした人はガッカリすることが多かったとか。
FF15でも自由に行動できる事が多かったけど、それ以上に広大な世界が広がっていそうなので楽しみ。
ファンタジーRPG
PVを見た感じだとダークファンタジーなRPGという感じ。
世界観や戦闘シーンがダークソウル3みたいな雰囲気。
ダークソウル3は死にまくったものの、難易度調整が絶妙で、途中で投げることなくクリアできた。
あそこまで難易度高くなくて良いけど、プレイスタイルも自由なのでこちらも楽しみ。
Skyrimと迷った
Skyrimと迷いました。
Skyrimの方がよく聞く気がするけど、好みが別れるっぽかったのでPVを見てウィッチャー3の雰囲気が自分に合ってそうだったので、今回はウィッチャー3にしました。
Skyrimは自由にキャラメイキングできるので、そのあたりも好みが分かれそう。
そもそも何で購入したのか
一番は英語の勉強のため。
iknowを利用してかれこれ半年以上、毎日30分〜1時間継続して英語学習ができている。
おかげで、ある程度ボキャブラリーが増えてきたので、少しずつ英語が読めるようになってきた。
次に何をしようかと考えていたときに、技術ドキュメントを読む事が多いのでリーディングを伸ばしたいと思い、いい題材を探していた。
ウィッチャー3は英語音声 + 英語字幕を表示できる上にクエストなどで文章もかなり多いらしく楽しみながら英語を大量にリーディングできるのではないかという甘い考え。
自分の今の語彙力で対応できるかわからないけど、まずはやってみようと思う。
まとめ
ゼロから作るDeep Learningの学習環境をDockerで作った
会社で「ゼロから作るDeep Learning」を使ってDeep Learningを学ぶ勉強会をしようということになったので、環境を作ってみた。
使用する書籍はこちら↓
なぜDockerなのか
- Pythonや各ライブラリのバージョン差異によるメンバー間の挙動の違いが発生しないようにしたい。
- そもそも環境の構築が面倒なのでサクッと作れるようにしたい。
といった感じ。
というわけで、Docker for Macを使って学習環境を作った。
環境・バージョンなど
Mac
Docker
- Python 3.5.2 :: Anaconda 4.2.0 (64-bit)
- Jupyter 4.2.0
Docker for Macのインストール
まだインストールしていなければこちらからDocker for Macをダウンロードしてインストールする。
詰まるところは無いと思うのでインストール方法は省略。
公式のGit HubをForkしてClone
こちらがオライリーが公式に公開している、「ゼロから作るDeep Learning」用のGitHubリポジトリ。
色々コードを触りたいので、自分のGitHubアカウントにForkして、Cloneする。
今回は/Users/{USER_NAME}/github/deep-learning-from-scratch
にcloneした。
$ cd ~ $ mkdir github $ cd github $ git clone https://github.com/{GITHUB_ACCOUNT}/deep-learning-from-scratch.git
Jupyter notebookを使うことになるので、.gitignoreに以下の行を追加しておくといい。
.ipynb_checkpoints/
Docker Imageの作成
※Docker for Macは起動させておく。
Docker Imageはこちらのannaconda用イメージを利用した。
docker-images/anaconda3 at master · ContinuumIO/docker-images · GitHub
# docker imageをpullする $ docker pull continuumio/anaconda3 # docker imageを作成(ざっくり以下の設定を行っている) # cloneしておいたGitHub用のリポジトリを、/opt/notebooks/deep-learning-from-scratchにマッピング # 8888番ポートをフォワード $ docker run -i -t -v /Users/{USER_NAME}/github/deep-learning-from-scratch:/opt/notebooks/deep-learning-from-scratch -p 8888:8888 continuumio/anaconda3 /bin/bash
docker runするとプロンプトがdocker内に移動するので、以下のコマンドでJupyter notebookをインストールする。
# /opt/notebooksをJupyterのルートディレクトリにし、8888番ポートを利用する $ /opt/conda/bin/conda install jupyter -y --quiet && /opt/conda/bin/jupyter notebook --notebook-dir=/opt/notebooks --ip='*' --port=8888 --no-browser
Jupyterが起動するので一度Ctrl + C
で終了し、exitで抜けておく。
以上でDockerの環境ができた。
Docker環境完成後
2回目以降は以下の手順でDocker Imageを立ち上げることができる。
# dockerのプロセスを探す $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a5f0b5dbc6db continuumio/anaconda3 "/usr/bin/tini -- /bi" 12 hours ago Exited (0) 10 hours ago serene_curran # ↑で探したコンテナID(今回の場合:a5f0b5dbc6db)を指定してdockerを起動する $ docker start -i a5f0b5dbc6db
dockerのプロンプトに移動するのでJupyterを起動する
$ /opt/conda/bin/jupyter notebook --notebook-dir=/opt/notebooks --ip='*' --port=8888 --no-browser
Jupyter起動中は、ブラウザでhttp://localhost:8888/
にアクセスすることでJupyterを使う事ができる。
また、Mac側の指定したディレクトリとシンクされているので、deep-learning-from-scratch
というディレクトリが既に存在する。
deep-learning-from-scratch
以下には各チャプターごとの参考コードが載っているし、notebookを作成し、notebookから該当のコードを呼び出すことができる。
呼び出し方は書籍内に出て来るのでそちらを参照。
Mac側とディレクトリを共有しているので、当然finderで中身を見ることもできるし、ブラウザ上のJupyter notebookで編集したnotebookを、自分のGitHubリポジトリにpushすることもできる。
これで色々捗りそうなので、Deep Learningについても学んでいきたい。
【iOS】Table Viewを使ってみる
前回の続き。
今回はTable Viewを表示する所をやってみる。
予め2ページ目の中央に配置していたLabelは削除しておく。
story boardでObject LibraryからTable View
を探してページに置く。
続けてTable View Cell
を探し、先程配置したTable View
の上に置く。
ここで2ページ目を表示するためのView Controllerを作成する。
プロジェクトツリーで右クリック -> New File..
を選択。
以下の画面でCocoa Touch Class
を選択する。
クラス名にSecondPageViewController
と入力し、
Subclass of にはUIViewController
を選択する。
※Table Viewだけのページであれば、UITableViewController
でも良さそう。
Storty Boardに戻り、2ページ目のView ControllerのAttribute Inspectorの設定で、classに先程作成したSecondPageViewController
を指定する。
Assistant Editor(∞みたいなアイコン)を開くと、左側にStory Board 右側にSecondPageViewControllerが表示される。
※表示されなければ表示されるように調整する。
この状態で、Table ViewからCtrl
キーを押しながらSecondPageViewControllerのクラス定義の直下にドラッグする。
↓画像のようなダイアログが出るので、tableView
という名前で設定する。
そうすると、@IBOutlet
でStory BoardのUITableViewとSecondPageViewController
のUITableViewがtableView
という変数名で接続され、以下のようにコードが挿入される。
その後、クラス定義部分にUITableViewDelegate
とUITableViewDataSource
を追加して以下のように書き換える。
class SecondPageViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
Story Boardに戻って、tableView
のConnection Inspector
を開く。
dataSource
とdelegate
からSecondPageViewController
に向かってドラッグする。
そうすると、dataSource
とdelegate
がSecondPageViewController
に接続される。
ここでdataSource
とdelegate
を実装していないのでコンパイルエラーが出るけど、先にCellの定義を追加する。
新たにCocoa Touch Class
作成画面を開く。
クラス名にSecondPageTableViewCell
を指定し、
Subclass of: にUITableViewCell
を指定する。
Story BoardでTableViewCellのIdentity Inspector
を開き、classにSecondPageTableViewCell
を指定する。
ついでにCellで画面表示したい項目をLabelで配置しておく。
画像の例だと、Labelでid
とname
を配置している。
同様にAttributes Inspector
を開き、IdentifierにSecondPageCell
を指定する。
※この項目は後ほどコード上でCellを取得するために使われる。
Assistant Editorで左にStory Board 右にSecondPageTableViewCell
を開いて、
Story BoardのCellからid
項目とname
項目をCtrl
キーを押しながらドラッグして、SecondPageTableViewCell
に接続する。
更に、データセット用のメソッドを定義する。
func setUserData(id: String!, name: String!) { self.id.text = id self.name.text = name }
最終的には以下のようなクラスになっている。
import UIKit class SecondPageTableViewCell: UITableViewCell { @IBOutlet weak var id: UILabel! @IBOutlet weak var name: UILabel! func setUserData(id: String!, name: String!) { self.id.text = id self.name.text = name } override func awakeFromNib() { super.awakeFromNib() // Initialization code } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } }
SecondPageViewController
に戻って、TableViewの実装を行う。
まずはtableViewが何行あるかを表示するための以下のメソッドを実装する。
今回は練習なので単純に5をreturnする。
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 5 }
さらに、対象行のCellを取得するためのメソッドを定義する。
withIdentifier
に設定する項目は、Attributes InspectorでIdentifierに設定した値に合わせる必要がある。
今回の場合は、SecondPageCell
になる。
また、型はSecondPageTableViewCell
を指定する。
最後にsetUserData
でCellにセットする項目を入れる。
※今回の場合、現在の行のindexというidと"hoge"という名前がセットされる。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SecondPageCell", for: indexPath) as! SecondPageTableViewCell cell.setUserData(id: String(indexPath.row), name: "hoge") return cell }
この状態でビルドして実行すると、以下の画面のようにTable Viewを表示することができた。
ここまで進めてきて徐々に難しくなってきた反面、楽しくなってきたので引き続きiOSアプリ開発方法を学んでいきたい。
Swiftのコード実装も増えてくるといい感じ。
【iOS】NavigationBarで前の画面に戻れるようにする
前回の続き。
今回は画面遷移した後、元のページに戻るという部分をやってみた。
今回もソースコードの変更はなし。
まずは右下のObject LibraryからNavigation Bar
を探して、遷移後の画面に配置する。
続いて同様にBar Button Item
を探して、先程追加したNavigation Bar
の左側に配置する。
↑で配置したTitle、Itemと表示されている部分をダブルクリックすると表示名を変更できるようになるので、適当な名前に変更しておく。
今回の場合だと、
- Title -> 2nd Page
- Item -> Back
にそれぞれ変更した。
続いてBar Button Item
を選択した状態で、Ctrl
キーを押しながら1画面目のView Controllerにドロップする。
Segueのアクションをどうするか聞かれるので、Show
を選択。
そうすると、↓図のように2ページ目から1ページ目へのSegueが表示されるようになる。
この状態でシミュレータを起動すると、
- 1ページ目の
Next
ボタン -> 2ページ目 - 2ページ目の
Back
ボタン -> 1ページ目
に遷移できるようになった。
今回もコードはいじっていないので次はコードを触っていきたい。
次のMacはディスク256GBにしよう
愛用しているMacBook Pro Early 2015のディスク容量が心許なくなってきた。
early 2015の中でも一番安いモデルなので、構成は↓こんな感じ。
ディスクは載ってないけど、128GBのモデル。
以前、以下で書いたように一度 TranscendのJetDriveを購入してSDカードとして増設している。
おかげで+64GBされているが本体側のディスク容量が既に半分以下になってしまった。
自分はあまり容量を使わないし、と油断していたらこんな結果になっていた。
容量が半分を切ると、精神衛生上あまり良くないなと感じるようになってきました。
JetDriveをもっと使えばいいと思うかもしれないけど、やっぱりいくつか不満もあって、最近では本体のSSDばかり使ってしまう。
気になっているのは以下の点。
- 本体のSDDの方が高速
- SDカードが刺さっているとスリープ状態でもバッテリーを消費してしまう
- Finder上で別のデバイスとして認識されるので、少しだけ面倒
最初は気にしないようにしていたものの、長く使っていくとやっぱり気になってくるもので、、
次は少しディスクに余裕を持たせようと思うようになった。
購入するのはもう少し先になりそうだけど、Appleの商品ページを見ていたら最新のラップトップでディスクが128GBってもうMacBook Airしかなかった。
次もきっとMacBook Proを買うと思うので杞憂に終わった。
Late2016は色んな意味で話題になっているし、USB-TypeC対応の周辺機器がまだまだ出揃っていないので、自分の買い時は 2017年か2018年モデルかなという感じ。
(それまでディスクが持てば・・)
とりあえずその時までにお金を貯めよう・・!
【iOS】単純な画面遷移をやってみる
練習用にプロジェクトは作ったので、まずは単純な画面遷移をしてみる。
今回はstoryboardで完結するのでコードの変更はなし
単純な画面遷移
まずはXcodeでMain.storyboard
ファイルを開く。
画面右下から遷移先用画面となるView Controllerを選択して、1画面目の右にドロップする。
画面が2枚に増えるので、画面右下の検索ウィンドウでbutton
と入力。
出てきたbutton
を、1画面目の真ん中あたりにドロップする。
ボタンの表示やサイズは適当に設定する。
ボタンを選択した状態で、ctrl
キーを押したまま、2画面目にドロップする。
Segueの接続先を選べるので、今回はShow
を選択する。
1画面目と2画面目を接続するラインができた。(これがsegue..?)
2画面目が分かるように、適当にlabel
を配置する。
この状態で保存して、実行してみる。
1画面目でNext
ボタンが表示され、ボタンを押すと
2画面目に遷移してmoved!
と表示された。
今回は単純な画面遷移しかしていないものの、1行もコードを書くことなく画面遷移ができたのはなかなか新鮮。
次はもう少し複雑な画面遷移をやってみる。