個人開発者のためのコマンドラインGit使いこなし術

個人開発者のためのコマンドラインGit使いこなし術

個人開発者のためのコマンドラインGit使いこなし術

英語で先に書いてから翻訳しています

どうも個人アプリ作家のTAKUYAと申します。

Gitはコードベースや変更履歴の管理に必要不可欠なツールです。たとえ個人でアプリを開発していたとしても。 僕はデスクトップとモバイルの両方で動作する、InkdropというMarkdownのノートアプリを独りで開発しています。 当アプリはデスクトップ版はElectron、モバイル版はReact Nativeで作られています。 僕は開発作業は基本的にtmuxとvimでターミナル上で行っています。vimによるJavaScriptコーディングのためのセットアップについては前回シェアしたとおりです

本稿では、僕のGitのワークフローについてご紹介したいと思います。 内容はすでにGitの基本をご存知の方向けとなります。

Gitの操作も基本的にはターミナル上で行っています。 色んなGUIベースのGitクライアントアプリを試したのですが、結局慣れませんでした。というのも、Gitコマンド自体にこれと言って大きな不満がなかったからです。 だからといって皆さんもターミナルでGitを使うべきだ!なんて言うつもりは全くありません。 すでにお気に入りのクライアントアプリをお持ちであれば、引き続きそちらを使ってください。

動画での解説はこちら

My Git setup

基本構成は以下のとおりです:

  • コマンドエイリアス: より素早いコマンドの入力
  • Commitizen: ヒューマン及びマシンフレンドリーなコミットメッセージの入力
  • tig: GitのTUI
  • fugitive: GitのVimインテグレーション

僕のGitの設定ファイルはGitHub上に公開しています:

以下より詳しく説明していきます。

お題: ホームページをリニューアルする

さて、Gitのワークフローをご紹介するにあたって、ちょうどよいサイドプロジェクトを見つけました。 現在のホームページは、作ってからかれこれ3〜4年経過しています。 なのでそろそろ作り直したいなと思っているところで、新しいデザインを考えていました。

ところで、MagicaVoxelはご存知でしょうか? これはボクセルアートと呼ばれるローポリでMinecraftみたいな、ボックスを組み合わせたモデルが簡単に作れるアプリです。それで以前イヌさんを作りました:

“Dev as Life”というロゴもYouTubeチャンネルで使えるようなかわいい感じで作りました。 今回のリニューアルでは、新しいホームページにこのボクセルアートを載せたいと思っています。 でも単純に画像にしたやつを載せるだけでは面白くありません。 WebGLを使って動的にモデルを描画して、ぐりぐり動かせるようにしたいと思います。 それをちょうど作業していたところで、今回の題材として最適です。

VoxelDog用のGitリポジトリを作成して登録する

現時点で、MagicaVoxelからモデルをエクスポートしてブラウザ上でレンダリングするところまで出来ました。 ここで一旦区切りをつけて、Gitリポジトリを作ってコードを入れたいと思います。

こちらがVoxel Dogのプロジェクトです。 今どんな感じかお見せします。

かわいいでしょ :) イヌさんが机に向かってパソコンを打っています。 まだまだ改善の余地があります — 色合いとか影の感じとか。 でもご覧の通りとりあえず動いたし、カメラも回せました。 これをGitリポジトリに入れたいと思います。 まずはリポジトリをGitHub上に用意しました:

Gitエイリアスを設定して素早くコマンドを入力する

gitを実行する時、普通は 'git' って打つと思います。 でも毎回 'git' って打つのは面倒すぎるので、 'g' と一文字にエイリアスを張っています。 以下の要領で設定できます:

  • fishシェルだと: alias g git
  • zshまたはbashだと: alias g='git'

ではローカルにGitリポジトリを初期化しましょう。

いい感じ。 次に、GitHubリポジトリをremoteoriginとして登録します。

g remote add origin git@github.com:craftzdog/voxel-dog.git

オーケー、登録されました。

Gitコマンドは毎日何回も打つコマンドです。 1日に10回打つとしたら、月に300回、年に3000回以上も打つことになります。 そしたら ‘git’ なんて毎回打ってられません。 ‘g’ 一文字にエイリアスを貼るとこの負担が軽減されます。

次に、statusコマンドは ‘st’ にエイリアスを設定して ‘g status’ と打つ手間を軽減しています。 この設定は .gitconfig というファイルの alias セクションに書かれています:

このように、 ‘st’ に status を割り当てています。 他にも沢山エイリアス設定があります。diff, checkout, commit, push, pull, branch などなど。 エイリアスは入力負担を軽減するため、2文字から4文字で設定しています。 他のエイリアスについては後ほど説明します。

今なにもステージにファイルが入っていないので、追加しましょう:

g add .

これでファイル群がステージされました。

commitizenを使っていい感じのコミットメッセージを入力する

次にそれらをコミットします。通常は g commit と打ちますよね。 するとエディタが立ち上がり、コミットメッセージの入力を行います。でもそれも何度もやるのは面倒です。 なので、僕はcommitizenというヘルパーツールを使用しています。

‘g cz’ とタイプすると、このように、コミットの種類をリストから選ぶよう促されます:

今回は初めてのコミットなので、とりあえず ‘feat’ を選択します。 次に、変更のスコープを聞かれます:

今回は最初なので * とします。変更範囲がすべてだからです。 次に短い説明文を入力せよと言われます。 ここでは 'Initial commit' とします。 そして次に長い説明文を入力せよと言われますが、別に詳しく説明することも無いのでスキップします。オプショナルです。 ブレーキングチェンジはありますか?いいえ。 OpenのIssueに関係しますか?いいえ。 と入力していきます。

すると変更のコミットが作成されました。 コミットメッセージは結果的にこのようになりました:

feat(*): initial commit

便利ですね。いちいちコミットメッセージのフォーマットに気を取られる必要がありません。 このように、適当になりがちなコミットメッセージを、苦労せずに美しいフォーマットで入力出来るツールです。 あなたがすべきことは事前に定義されたコミットタイプを選択することです。 深く考えなくてもいい感じのコミットメッセージにしてくれます。 チームだけでなく個人開発でも役に立つでしょう。 例えば僕の場合、アプリのリリースノートを書く時にコミットヒストリをよく参照します。 こちらがデスクトップ版のコミットヒストリです:

ご覧のように、素早く各コミットを把握できます。 僕は頻繁に「何やったっけ?」と忘れてしまいます。 3、4週間も前の作業となると全く覚えていません。 でもこのようにコミットメッセージが明快に記述されていれば、どんな変更で、どんな範囲で、そして具体的に何の変更か把握できます。 超便利。

コミットログを素早く参照する方法

ではVoxel Dogプロジェクトに戻ります。 コミットログを参照する際に打ったgit histもエイリアスです。

[alias]  hist = log --pretty=format:\"%Cgreen%h %Creset%cd %Cblue[%cn] %Creset%s%C(yellow)%d%C(reset)\" --graph --date=relative --decorate --all

上記エイリアスはいろいろオプションを付けてフォーマットを指定しています。 他にも llog というエイリアスも設定しています:

[alias]  llog = log --graph --name-status --pretty=format:\"%C(red)%h %C(reset)(%cd) %C(green)%an %Creset%s %C(yellow)%d%Creset\" --date=relative

これはコミットログだけでなく変更されたファイル名の一覧も表示する設定です。 Inkdropプロジェクトでは、このようにどのファイルが変更されたのか素早く知ることが出来ます:

log コマンドはこのようにとても柔軟に出力形式を指定できます。 ぜひいろいろいじって遊んでお好みのフォーマット設定を見つけてください。

df エイリアスというのもあります。実行するとコミットヒストリを表示します:

ここでサイドバーの変更について詳しく知りたいとします。該当するコミットを選ぶと、そのdiffを表示します:

エイリアスはこのようになっています:

[alias]  df = "!git hist | peco | awk '{print $2}' | xargs -I {} git diff {}^ {}"

実際には前に説明した git hist を実行して、その結果を peco というstdinから任意の行を選択できるコマンドラインツールに渡して、awk で選択行からコミットハッシュを取り出して、 git diff に渡す、という事をしています。意味不明ですね。 要するに、任意のコミットを選んでdiffを参照するワンライナーです。 これで素早くコミットの詳細を参照できる訳です。

tig — TUI for git

tigコマンドもよく利用します。 名前の通り、Gitを逆さまにしたものです。 このコマンドは、コミットをインタラクティブに選択できます。 vimライクなキーバインドに対応してるのでvimmerに優しい設計です。 例えばあるコミットを選択してエンターキーを押すと、画面が分割されてdiffが表示されます。

tig はリリースノートを書く時に最近の変更ログを調べるのによく使っています。 なぜならコミットログを参照する度にgitコマンドを打つ必要がないからです。 これでワークフローがより効率化します。

リモートリポジトリにpushする

では、このコミットをリモートリポジトリにpushしましょう。 今1つのコミットがローカルリポジトリに入っています。 それをリモートにpushします:

g ps

出来ました。 このpsもエイリアスです:

[alias]  ps = "!git push origin $(git rev-parse --abbrev-ref HEAD)"

git push origin masterなんて毎度打ってられません。長すぎですよね。 なので ps と簡略化しています。 このエイリアスはブランチの指定も支援してくれます。 現在選択されているローカルのブランチと同名のリモートブランチにpushしてくれます。 'master'で作業しているとしたら、リモートの'master'ブランチにpushしてくれます。

pullするには、plを使います:

[alias]  pl = "!git pull origin $(git rev-parse --abbrev-ref HEAD)"

同様に、現在のブランチと同名のリモートブランチからpullします。 こうすることで、master以外のブランチで作業していた時もブランチ名の指定を省けます。 これで更にワークフローが改善します。

他にも brbranch に割り当てて短くしています:

[alias]  br = branch

つまり、とにかくエイリアスを活用せよという話です。

ターミナルからGitHubのプロジェクトページを素早く開く方法

GitHub上にリポジトリを作りましたが、ブラウザのタブでずっと開いている訳ではありません。 もしGitHub上でissueを参照したいとか詳しく調べたいといった時、g open と入力します。

するとGitHub上のリポジトリのページが素早くブラウザで開かれます。 g openエイリアスは以下のように定義されています:

[alias]  open = "!hub browse"

これは hub browse コマンドを実際には実行しています。 つまり hub browse を直接実行するのと等価です。 hubは、GitHub公式のコマンドラインツールで、GitHub特化のコマンドをgitに追加するものです。 例えば、GitHub上のリポジトリをcloneする時、フルのURLを指定しなくても出来ます:

g clone craftzdog/dotfiles-public

このように、GitHub特化のタスクの実行を支援してくれます。 これを使うことで、remoteとして登録されたGitHubプロジェクトページをターミナルからすぐにgit open コマンドで開くことが出来ます。

vim-fugitiveでVimからGitを使う

僕は普段Vimでコーディングしているので、やはりVimから直接Gitを使いたい時があります。 そうするには、例えばこちらがVoxelDogのソースコードで、three.jsを使ってイヌさんをレンダリングしています。 今、カメラがぐるぐる回っていますが、イヌさん自身も回してみましょう。

オーケー、回り始めました。

グレート。

ではコミットしましょう。 ステータスを確認します。 そしてg dを実行します。これはdiffのエイリアスです。

オーケー、このようにイヌを回転させる行が追加されました。 このように、常にコミットする前はdiffをチェックするようにしています。 そして良さそうなら g cz でcommitizenを実行します。 この時、 -a オプションを指定することで、まだステージされていないファイルも一緒にコミット出来ます。

これでもう1つのコミットが追加されました。 では g ps でpushします。 いい感じ。

ここから3ヶ月が経過したとしましょう。僕はもはやこの変更の事を覚えていません — なぜ追加したのか、いつ追加したのか、誰が担当したのかさえ。全く分かりません。 それを確認するためには、:Gblameを以下のようにvimで実行します:

すると、コミットヒストリが左側に表示され、対応する行が右側に表示されます。 スクロールすると双方が同期します。 これで、コミットを参照しながらコードを眺められます。 もしここでエンターを押すと、diffを見ることが出来ます。

これで、このコミットは11:53 November 5thにイヌさんを回転させるために追加されたという事が分かりました。

僕は数ヶ月前に自分のやったことを頻繁に忘れます。 でもこうすることで、いちいちgit blame コマンドを打ったりGitHub上で確認しなくても、vim上で直接過去の変更を素早く覗けます。

そして、もしそれでも分からん、もっと詳しく教えてくれとなった場合は、 :gopen コマンドを実行します。 するとGitHub上で該当するファイルをすぐさま開けます。 対応するコミットを参照してくれるので、他のコミットと差分を比較するのにも便利です。 このように、ターミナルとブラウザを行ったり来たりしています。

これをどのように実現しているかというと、vim-fugitiveというvimプラグインを使っています。 これはvimのgitラッパーです。 様々なGit関連のコマンドに対応しているので、いろいろ遊んでみてください。 gopengBrowseのエイリアスです。これは僕の好みです。

以上です!

Read more

なぜ体を壊してまで個人開発を頑張るのか?自尊心の欠如や過集中癖と向き合う

なぜ体を壊してまで個人開発を頑張るのか?自尊心の欠如や過集中癖と向き合う

どうもTAKUYAです。最近、個人開発を頑張りすぎて体調を崩してしまいました。アトピーが猛烈に悪化して、QoLが著しく下がってしまいました。まだ療養中ですが、毎日1万歩以上歩いて、徐々に回復しつつあります。 この過ちを繰り返さないためにも、自分は一体何が原因で頑張りすぎてしまうのか?という事について深堀りして考えてみたいと思います。また、個人開発におけるメンタルヘルスはあまり語られていないトピックだと思います。本記事が、同じように仕事を頑張りすぎてしまう人の助けになれば幸いです。 TL;DR * なんとなく続けていたソフト開発が自分を救った * 原体験が歪んだモチベーションを生んでしまった * 親が引くほどの過集中癖がある * 生得的な直せないバグと考えることにする * アプリの成功に関係なく、自分をあるがままに受け入れる * 挫折しないのは、なんだかんだで前向きだから * ユーザさんから「休め!」と叱咤された * 人生は長い。個人開発なんかで死ぬな 自己の原体験について振り返ってみる 個人開発だけで生活するようになって、かれこれ8年ぐらいが経ちます。こう

By Takuya Matsuyama
ユーザサポートの問い合わせを装った攻撃が怖すぎた

ユーザサポートの問い合わせを装った攻撃が怖すぎた

どうもTAKUYAです。個人開発をしていてアプリの知名度が上がってくると、作者個人(あるいはサイト管理人)を狙った攻撃というのをたまに受けます。つい先日も、怖すぎるメールを受け取ったのでシェアします。 件名: Cookie consent prevents platform access Hello, I cannot access use the store. The cookie consent notice keeps appearing and nothing happens once I approve or try to close it, so I’m unable to interact with the website. Please provide guidance on

By Takuya Matsuyama
万年ペーパーの自分が車の運転を楽しめるようになった理由

万年ペーパーの自分が車の運転を楽しめるようになった理由

どうもTAKUYAです。大学の入学前に免許を取って以来ずっとペーパードライバーで、都市生活では出来る限り運転は避ける生活を送っていた。事故を起こせば人を◯してしまう可能性もある代物を日常的に運転するなんて考えられなかった。 そんな自分に転機が訪れたのは、結婚して大阪に戻った事と、子供ができた事、そしてアウトドアに興味を持った事だ。大阪近辺だと箕面とか野勢、神戸、丹波篠山などが日帰りでドライブしやすい距離だ。それで、恐る恐るタイムズのカーシェアで時々ではあるが運転するようになった。 他の車も生きた人間が運転しているという驚き まず運転していて気づいたのは、他の車にも生きた人間が運転していると言う点だ。そんなのは当たり前だろと思うかもしれないが、結構新鮮な発見だった。Grand Theft Autoなどの現代をモチーフにしたゲームをプレイすれば分かるが、NPCの車の動きは鈍臭いのでガンガンぶつかる。プレイヤーの進行を予測した動きなどしないからだ。 しかし現実では相手も事故りたくないので、お互いに動きを読み合い、譲り合って運転する。ルードな運転手もたまにいるものの、どちらかがよっぽ

By Takuya Matsuyama
禅的思考: なぜInkdropはMarkdown独自拡張をしないのか

禅的思考: なぜInkdropはMarkdown独自拡張をしないのか

InkdropはMarkdownのノートアプリですが、Markdownの独自拡張は「絶対にやらない」と決めていて、それがアプリの哲学になっています。 Markdown(厳密にはGitHub-flavored Markdown)の強みは、ソフトウェア業界標準で広く使われてい緩い文書フォーマットという所です。 アプリの独自記法を加えてしまったら、あなたの書いたノートはたちまちそれらと互換性がなくなります。 「独自記法を加えた方が便利な機能が付けられるだろう」と思うかもしれません。もちろん実際Markdownは完璧な書式ではないため、必要な場面はいくつかあります。例えば画像のサイズ指定方法が定まっていない、など。それでも自分は、ノートの可搬性を第一にしてきました。その裏には禅にまつわる哲学があります。 日本の文化は周りの環境と対立するのではなく、溶け込もう、馴染ませよう、共生しようとする傾向があります。窓の借景、枯山水、建築の非対称性、茶室のシンプルさ、侘び寂びなどあらゆるところで見られます。 絵画における「減筆」の手法を例にとって説明します。 これは、描線を最小限に抑えながら絹や紙の

By Takuya Matsuyama