Gitでブランチを間違えて作業した上にpushまでしちゃった場合の対処方法
時間ができたのでHandBrake 0.9.5の日本語化に着手しているのだが、うっかり0.9.4のブランチで作業してしまったあげく、SourceForge.JP上のリポジトリにpushしてしまい途方に暮れる。
まあこういうミスをやる人は少ないだろうが、何かのヒントになるかもしれないので対処法をメモしておく。まず、「git log」コマンドで巻き戻したいcommitのハッシュを調べる。
$ git log : : commit 1485a5a2bbbb43eedbe131c919b7d604bcbd506d Author: unknownDate: Tue Jan 5 19:19:44 2010 +0900 update Installer, changelog, readme
今回は、この「1485a5a2bbbb43eedbe131c919b7d604bcbd506d」というcommitまで巻き戻すことにする。作業中のブランチが操作したいものであることを確認したうえで、「git reset <対象のハッシュ>」を実行する。
$ git branch -a jp-0.9.3 * jp-0.9.4 master original remotes/origin/HEAD -> origin/master remotes/origin/jp-0.9.3 remotes/origin/jp-0.9.4 remotes/origin/master remotes/origin/original $ git reset 1485a5 Unstaged changes after reset: M Jamrules M Makefile M win/C#/Installer/Installer.nsi M win/C#/InstallerJp/doc/AUTHORS M win/C#/InstallerJp/doc/CREDITS M win/C#/InstallerJp/doc/NEWS M win/C#/Properties/AssemblyInfo.cs M win/C#/frmAbout.Designer.cs
「git log」で巻戻ったことを確認する。
$ git log commit 1485a5a2bbbb43eedbe131c919b7d604bcbd506d Author: unknownDate: Tue Jan 5 19:19:44 2010 +0900 update Installer, changelog, readme
バージョン管理されているファイル自体は巻き戻されていないので、「-f」オプション付きでチェックアウトしてファイルも巻き戻す。
$ git checkout -f
ここまでの作業でローカルブランチの巻き戻しは完了。続いてリモートブランチの巻き戻しを行う。ただし、当然ながらそのままpushすることはできない。
$ git push Enter passphrase for key '/d/Users/hirom/.ssh/id_dsa': To hylom@git.sourceforge.jp:/gitroot/handbrake-jp/handbrake-jp.git ! [rejected] jp-0.9.4 -> jp-0.9.4 (non-fast-forward) error: failed to push some refs to 'hylom@git.sourceforge.jp:/gitroot/handbrake- jp/handbrake-jp.git' To prevent you from losing history, non-fast-forward updates were rejected Merge the remote changes (e.g. 'git pull') before pushing again. See the 'Note about fast-forwards' section of 'git push --help' for details.
そこで、いったんリモートブランチを削除した上で再度pushする。まずは削除。リモートブランチの削除は、「git push <リモートリポジトリ> :<対象リモートブランチ>」で行える。
$ git push origin :jp-0.9.4 Enter passphrase for key '/d/Users/hirom/.ssh/id_dsa': To hylom@git.sourceforge.jp:/gitroot/handbrake-jp/handbrake-jp.git - [deleted] jp-0.9.4
あとは再度ローカルリポジトリをpushするだけ。
$ git push origin jp-0.9.4:jp-0.9.4 Enter passphrase for key '/d/Users/hirom/.ssh/id_dsa': Counting objects: 233, done. Delta compression using up to 2 threads. Compressing objects: 100% (146/146), done. Writing objects: 100% (165/165), 30.48 KiB, done. Total 165 (delta 119), reused 0 (delta 0) To hylom@git.sourceforge.jp:/gitroot/handbrake-jp/handbrake-jp.git * [new branch] jp-0.9.4 -> jp-0.9.4
お粗末様でした。
Pythonコード中のSQL文インデントを考える
Pythonコード内にSQL文を書くときどうすれば良いのか、いまいち答えが探せなかったのでググって見た話。
ちなみに、今までは下記のような感じのコードを書いていた訳だが、これ見るからに分かりにくい。
# コード例その1
cur.execute("""
create table count (
sid text,
count int);""")
# コード例その2
try:
cur.execute("""insert into count ( sid, count )
values ( :sid, :count );""", d)
except sqlite3.IntegrityError:
cur.execute("""update count set sid = :sid, count = : count
where sid = :sid;""", d)
# コード例その3
cmd = """select sid, title, date from stories where date >= ? and date < ? and sid in (
select sid from topics where topic == ? and sid in (
select sid from topics where topic == ? )) order by date
"""
cur.execute(cmd, (begin_t, end_t, t1, t2))
「SQL インデント」でググると、そういう話のネタが一杯出てくるでてくる。その中から拾ってみたのが下記。
- SQLプログラミング作法
- SQL のコーディングスタイル(インデント) - 集中力なら売り切れたよ
- SQL文をきれいにフォーマットしてくれる『SQL in Form』 - POP*POP ~ 世界のニュースをクオリティ重視で
- VB.NETで作る! | SQL文の字下げ目安
- SQLの整形ツール~整形結果の例 - プログラマー'sペイジ
異端だけど、俺的コーディングルール SQL編 – suVeneのアレというのも参考になった。
で、この辺をまとめたところ、だいたい以下のようなルールに落ち着いた。
- SQLキーワードは大文字で
- 括弧挟まれた部分はインデントレベルを+1する
- カンマ、ANDの直後で改行
- カンマやANDでつなげられている部分はなるべくキーワード部分でそろえる
このルールで書いたコードは下記のような感じ。
# コード例その1
cur.execute("""
CREATE TABLE count (
sid text,
count int
);
""")
# コード例その2
try:
cur.execute("""
INSERT INTO count (
sid,
count
)
VALUES (
:sid,
:count
)
""", d)
except sqlite3.IntegrityError:
cur.execute("""
UPDATE count
SET sid = :sid,
count = : count
WHERE sid = :sid
""", d)
# コード例その3
cmd = """
SELECT sid,
title,
date
FROM stories
WHERE date >= ? AND
date < ? AND
sid IN (
SELECT sid
FROM topics
WHERE topic == ? AND
sid IN (
SELECT sid
FROM topics
WHERE topic == ?
)
)
ORDER BY DATE
"""
cur.execute(cmd, (begin_t, end_t, t1, t2))
本当にこれで良いのかはまだ自信がないが、おおむね間違ってはいないと思う。ていうかコード内にSQL文を直書きせずO/Rマッパー使え、という話もあるが……。
要ログインのサイトにPythonのurllib2でアクセスする
ログインが必要なWebサイトに対してスクリプトでページを取得/送信したい場合、まずログイン用のURLに対しログイン情報をPOSTしてCookieを取得する、という作業を行うのが一般的だ。しかし、Pythonのurllib2を利用すると簡単にPOSTは行えるのだが、なぜかCookieを取得できない、という問題が発生することがある。
これはurllib2のurlopen()でURLを開き、帰ってきたオブジェクトのinfo()メソッド経由でSet-Cookieヘッダを取得しようとする場合に発生する。たとえばCMSを使用しているWebサイトで、管理用ページ以外に(正当な)Cookieを持たずにアクセスするとCookieなしでアクセスできるトップページ等にリダイレクトされる、というケース。多くのCMSではログインに成功すると管理ページトップにリダイレクトされるのだが、urllib2のデフォルト設定ではCookie処理を行ってくれない&リダイレクトを自動的に処理してくれるため、「ログイン成功→(Cookieを返すがurllib2はCookieを保存せず)→管理ページトップにリダイレクト→Cookieがないので公開ページのトップにリダイレクト→Cookieは受け取れず」という事態になってしまうことがある。
この場合、urllib2.HTTPCookieProcessorを使ってCookie処理を行えばよいのだが、なぜかurllib2のドキュメントにはこのクラスの解説が無い。例にも上がっていない。ということで途方にくれるわけだが、実はCookieを扱うcookielibのほうに使い方の例が載っていたりする。
import cookielib # : # (このへんでurlやencoded_data、headersを準備) # : req = urllib2.Request(url, encoded_data, headers) cj = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) resp = opener.open(req)
取得したCookieはCookieJarオブジェクトに保存されるので、必要に応じて適宜取り出せばOK。かわりにFileCookieJarオブジェクトを使えばファイルへのsave/loadも可能。
gitメモ:ブランチを切ってないのにやばいコードを書いちゃった場合
gitを使ってコードの管理をしている場合において、実験的なコードを書く場合はソースコードを編集する前にブランチを作成しておくのが基本だ。しかし、ついブランチを作成し忘れたままでコードを変更してしまった、というパターンがある。
この場合、下記のようにgit stashでいったん変更点を保存した上で直前のcommitに戻し、新たなブランチを作成してそこでgit stash applyを行えばよい。
$ git stash $ git checkout hogehoge -b $ git stash apply $ git add hogehoge foobar $ git commit
git stash、便利だ。
Small Basic 0.9リリース
Microsoftがプログラミング学習用としてリリースしているBASICプログラミング環境「Small Basic」の0.9が6月11日にリリースされた。
Small Basicブログによると、Small Basicコンパイラのパフォーマンス強化や新規ライブラリの追加などが行われているとのこと。ループが多いプログラムで、4倍ものパフォーマンス向上を達成できた例もあるそうだ。
追加されたライブラリでは、MML的記法で音楽を再生できる「PlayMusic」機能が面白そうだ。教育用とはいえ、Flickr連携や作成したプログラムをSilverlightを用いてWebブラウザ上で実行する機能などもあり、ちょっとしたユーティリティなどを作成するのにも便利かもしれない。