| @技術/プログラミング

なんか作業してて変更発生して一旦 git commit したとします。例えば行末の空白(trailing white space)刈りをしていたとしましょう。一通り刈り終わって git commit して別のファイル開いたらまた trailing white space があったとします。さっき "remove trailing white space" とコミットログを残したのにまた同じの書くのは意味ないし同じようなことやってるコミットを二つに分ける意味はない。なので git commit --amend すると思うんですけど(じゃんじゃんコミットして後で git rebase -i するやり方もあるけど remote に push 後だったら force push しないといけなくてだるい)、単なる git commit --amend だとエディターが立ち上がってコミットログを確認して保存して終了しないといけない。非常にだるい。 git commit --amend のエディター立ち上がらないオプションとかないのかと調べていたら --no-edit というオプションがあることを知った。エディター立ち上がらずに --amend できて非常に便利。これまで「現在の作業内容をどこまで終わらせてからコミットするか」を考えるのが結構苦痛だったんだけど、 git commit --amend --no-edit のおかげでリストカット感覚でコミットしていけそう。

| @技術/プログラミング

会社で使ってる GitHub のプライベートリポジトリで master ブランチに対して出てる Pull Request を Merge したらコードが消えるという珍事があった。ファイルを削除する commit とかないにもかかわらず、全消しされてしまった。ちなみに同じ Merge を手もとでやるとコードが消えたりはせずちゃんと Merge された。極めて謎な現象だった。

master ブランチが空になるとデプロイができなくなって不都合があるので( Webistrano 上でデプロイするとき master ブランチからしかデプロイできないようなレシピになってる)、コードが消滅したブランチを bukkowaremaster にリネームして手もとで Merge したブランチを force push してしのいだ。

GitHub に問い合わせてみたところ、ぬるい感じの一次返信が来たので原因教えて欲しいと送った。すると今度は別の人( Jeff King という人物)から返事が来た。名前でググったら git のコミッターだった。どうやら大事みたいだ。

We are still tracking down the exact cause of the problem you experienced, but we believe it is related to an unchecked error condition in git that triggers only occasionally (it does not reproduce reliably on your repository, and over all of our repositories over the past few years, yours is only the second instance we have seen).

In the meantime, we've put additional checks into the merge process to sanity-check the result. This should help us narrow down the root cause, but more importantly, it will prevent such a bogus merge from being presented to the user (we will catch the error and retry it).

I hope that addresses your concern.


(以下拙訳)

引き続き問題の原因を調査してるけど、これは git の unchecked error condition に起因する問題だと思っています。(再びあなたのリポジトリで同じ問題が起こることはないはずです。ここ数年間でこの問題に遭遇したのは GitHub の全リポジトリでもあなたのケースが 2 例目です)

一方で、 Merge のプロセスにはもっと厳密なチェックを追加するようにしました。このことで問題の原因を絞り込むことができますし、さらに大事なことに、今回のような空の Merge をユーザーの目にさらすことがなくなります(問題があれば我々が事前に察知し、 Merge を再実行します)

この対応であなたの懸念を解消できるのではないかと思います。

unchecked error condition ってのが何なのかがよく分からなくて、軽くググってみたら例外キャッチできなくて死ぬ現象で、セキュリティ上の懸念事項っぽい( CWE - CWE-391: Unchecked Error Condition (2.5))。

「 Pull Request を Merge したらコードが消えました」と聞かされたときは、冗談か何かかなと思ったけど、見てみたら本当に消えててびっくりした( git なので手もとにも同じコードあるからそんなに不安な感じはしなかった)。

GitHub 、問い合わせたらちゃんとまともな感じの返信が返ってくるのでその点は評価できる。今回も git の中の人みたいな感じの人から返信来たし、すでに追加的なチェック処理を行うようにしたと書いてあって対応速かった。 GitHub が git の問題直せる人を雇ってるというの、いいと思う。 OSS を使ってる会社が OSS の問題を直せる人を雇ってると強いなぁと感じた。

GitHub には今年の春の時点で 600 万リポジトリくらいあるらしいから( Five years )、 600 万リポジトリの中で行われた Pull Request のすべての Merge の中で 2 例目のレアな経験をしたということになる。なのでこれ読んでる人が同じ現象に遭遇することはまずないと思うけど、こういうことがありましたよというお話でした。

| @技術/プログラミング

他の人は Vagrantfile をプロジェクトルートの上に置いてるけど自分はプロジェクトルートに置きたくて、Vagrantfile を ignore したいと思った。しかしそれは自分の都合なので PROJECT_ROOT/.gitignore には追加したくない。そんなことはありませんか。

シェルの設定ファイルでやるみたいに、 .gitignore.local みたいなファイルを作って読み込ませたり出来ないのかなと思ったけど、出来ないみたいだった。

ところで git はホームディレクトリにある .gitconfig に git config --global したときの設定情報を保存する。自分は ~/.gitconfig に以下のように書いてる。

[core]
  excludesfile = /Users/morygonzalez/.gitignore

自分のホームディレクトリにも .gitignore ファイルを作っていて、こちらをプロジェクト横断的に読み込ませている。従ってこちらに Vagrantfile を追加しても良かった。

しかしそうするとプロジェクト横断的に Vagrantfile が無視されてしまい、Vagrantfile をバージョンコントロールしているプロジェクトで困ってしまう。

調べてみたところ、リモートブランチには反映させたくないけど自分の手元だけで特定のファイルを無視したいときには以下のようにすると良さそうだった。

  1. PROJECT_ROOT/.git/info/exclude に無視したいファイル名を記載する
  2. PROJECT_ROOT/.git/config で以下のように記載する
[core]
  excludesfile = /path/to/ignore-definition

自分は新しく ignore-list 用のファイルを作るのが面倒くさかったので .git/info/exclude に無視したいファイルリストを書いた。

| @技術/プログラミング

Git flow を導入して仕事してる。master ブランチと develop ブランチをベースに、 feature ブランチ、hotfix ブランチ、release ブランチをつくって色々やるあれ。確かに便利何だけどだるいところもある。

hotfix ブランチのバージョン番号

たとえば誰か(A さんとしよう)がバグを見つけて hotfix を start したとする。hotfix 用のタグを 1.0.1 としよう。

$ git flow hotfix start 1.0.1

ここで別の誰か(B さんとしよう)が他のバグを見つけたとする。このとき B さんは A さんがローカル環境で 1.0.1 のタグを既に使っていることを知らない。ので当然 $ git flow hotfix start 1.0.1 してしまう。そんで B さんが

| @技術/プログラミング

やってみた。以下を参考にした。

これもうむかし.macとかについてたiBlogとかわらんわ。GUIのクライアントはないけど、VimとかCodaとか好きなエディタ(TextMateで日本語がネイティブに扱えたらなー)で記事書いて、gitで git push するだけ。

で、やり方なんですけどちょっとgitに慣れてない人には複雑かもしれない。三つgitのリポジトリを用意する必要がある。

まず記事を作成するパソコンでgitとjekyllのセットアップをしたあと、リポジトリを作る(リポジトリ1)。その後Dreamhostの公開ディレクトリでないところに空のリポジトリを作る( git --bare init )。ここでは blog.git という名前にしましょう(リポジトリ2)。そんでそこにリポジトリ1をpushする。その後リポジトリ2の /blog.git/hooks/post-update というファイルを作り、以下のように書く。ファイルに実行可能なアクセス権を与えることを忘れずに。

#! /bin/sh
unset GIT_DIR && cd $HOME/tech.portalshit.net/ && git pull

そんでもって git clone blog.git <公開用のディレクトリ名> する(リポジトリ3)。リポジトリ1から公開用ディレクトリにリポジトリがコピーされるので、この中に含まれる _site というディレクトリを panel.dreamhost.com で公開ディレクトリとして設定すると、git push する度にhookが発動されて、めでたく記事が公開されるという次第です。

まとめ

まとめると、

  1. 記事を作成するローカルリポジトリ
  2. ローカルリポジトリをpushするリモートリポジトリ
  3. リモートリポジトリをcloneする公開用リポジトリ

の三つが必要なことを忘れないようにしてくだしあ。

これであなたもハイド博士だ!

| @技術/プログラミング

Gitでbranchの効率的な使い方みたいのがよくわからない。

  • 実験的な機能をつけたい

  • ブランチを分ける(例えば開発用に alternate というブランチを作る)

  • 開発する

  • 開発完了後、 master にマージ

みたいな感じかなと思ってた。

しかし実際に運用してみると、実験的な機能の実装の他に、日常的にmasterでコードの改良みたいな作業があり、alternateで開発が完了した後にmasterにマージしたら多分コンフリクト起こりまくりになるような気がしてきた。

それで日常メンテみたいな作業はmasterブランチで行い、それをalternateにマージするという手順をとってる。正しい開発方法かどうかはわからないけど、一応alternateブランチもmasterの最新の変更を追跡できる。んでalternateではしこしこ開発を続けて、開発完了時にmasterにマージしても多分派手なコンフリクトは起こらないんじゃないかと思ってますがどうなんでしょう。