ぼくの技術日誌

日誌って銘打っていますが、更新頻度が…

Gitのブランチを上書きする方法

Gitを開発に利用する途中、git pushするとあるブランチ(uartブランチ)が

 ! [rejected]        uart -> uart (non-fast-forward)

といわれるようになりました。
調べてみると、リモートから取得した内容に変更を加えてpushしようとしたが、他からの変更が先にpushされたことが原因とのことです。
要は競合したということでしょうか。

他のブランチで作業を進めるようになり、放置していたのですが、上書きして再利用することを思いつきました。
ブランチの上書きは現在のブランチでgit branchに-fを付けて上書き対象のブランチを指定することでできるようです。
実際にやってみました。

yosuke@yosuke-vb:~/bitbucket/stellaris$ git branch -a
  master
* sandbox
  uart
  remotes/origin/master
  remotes/origin/sandbox
  remotes/origin/uart
yosuke@yosuke-vb:~/bitbucket/stellaris$ branch -f uart
yosuke@yosuke-vb:~/bitbucket/stellaris$ git checkout sandbox
yosuke@yosuke-vb:~/bitbucket/stellaris$ git push origin uart
Password for 'https://yosuke_kirihata@bitbucket.org': 
remote: bb/acl: yosuke_kirihata is allowed. accepted payload.
To https://yosuke_kirihata@bitbucket.org/yosuke_kirihata/stellaris.git
   9bbc3dc..cd46432  uart -> uart

sandboxブランチの中身をuartブランチに上書きをしたいので、sandbox上でgit branch -fを実行します。
checkoutでブランチを移動し、(中身が上書きされたことを確認して)pushでリモートへ結果を反映します。
以上で終了です。


http://linux.keicode.com/prog/git-resolve-non-fast-forward-push-problem.php

http://transitive.info/article/git/command/branch/

Gitのリモートリポジトリへ誤ってgit pushした場合の取り消す方法

本日、Gitでmasterブランチを作業ブランチに切り替えることを忘れてそのままcommit、pushをしてしまいました…
急ぎ修正の方法を調べて治したのですが、今後もやってしまいそうなので作業内容をメモしておこうと思います。


先ず、git log で戻したいcommitのハッシュ値を調べます。

yosuke@ubuntu:~/bitbucket/stellaris$ git log
commit 666ce6c28a3e87ec8d4cc9f075436b9d876dcb30
Author: yosuke kirihata <yosuke@ubuntu.(none)>
Date:   Mon Mar 18 18:56:45 2013 +0900

    Mod start.S and vector.c.

commit 664ab6180dc7c37c2b073119556f590e68fbb58b
Author: Yosuke Kirihata <yosuke@ubuntu.(none)>
Date:   Thu Mar 14 21:06:15 2013 +0900

    First commit.

今回はcommit 664ab6180dc7c37c2b073119556f590e68fbb58bに戻したいと思います。
git branch でブランチの一覧を確認します(-aでリモートとローカル両方のブランチを表示)。

yosuke@ubuntu:~/bitbucket/stellaris$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/sandbox

git reset [hash]でブランチを戻します。

yosuke@ubuntu:~/bitbucket/stellaris$ git reset 664ab6180dc7c37c2b073119556f590e68fbb58b
Unstaged changes after reset:
M	startup.S
M	vector.c
yosuke@ubuntu:~/bitbucket/stellaris$ git log
commit 664ab6180dc7c37c2b073119556f590e68fbb58b
Author: Yosuke Kirihata <yosuke@ubuntu.(none)>
Date:   Thu Mar 14 21:06:15 2013 +0900

    First commit.

checkoutでファイルも前の状態に巻き戻します。

yosuke@ubuntu:~/bitbucket/stellaris$ git checkout -f
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.

リポジトリの状態を見てみます。

yosuke@ubuntu:~/bitbucket/stellaris$ git status
# On branch master
# Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
#
nothing to commit (working directory clean)

最後に巻き戻した内容でリモートリポジトリへpushします。

yosuke@ubuntu:~/bitbucket/stellaris$ git push origin master
To git@bitbucket.org:yosuke_kirihata/stellaris.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'git@bitbucket.org:yosuke_kirihata/stellaris.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するだけでは失敗してしまいます。
リモートブランチを削除したうえで改めてpushする必要があるとのことです。

yosuke@ubuntu:~/bitbucket/stellaris$ git push origin:master
ssh: Could not resolve hostname origin: Name or service not known
fatal: The remote end hung up unexpectedly

これで戻るはずが、なぜかsshで名前を解決できないようで失敗してしまいます…


正しいコマンドは

$ git push origin :master

だったらしいです。originの後にスペーズがありませんでした…


エラーメッセージやssh関係で検索してみましたが通らないので、別のWebページに載っていたgit push origin +masterを実行してみました。

yosuke@ubuntu:~/bitbucket/stellaris$ git push origin +master
Total 0 (delta 0), reused 0 (delta 0)
remote: bb/acl: yosuke_kirihata is allowed. accepted payload.
To git@bitbucket.org:yosuke_kirihata/stellaris.git
 + 666ce6c...664ab61 master -> master (forced update)

これで無事巻き戻すことができました!
(終わり良ければすべて良しということで)めでたしめだたし。

今回の方法は目についた記事に習って作業をしただけなので、もっと違う方法や良い方法があれば知りたいところです。
でもそのためにはGitを深く理解する必要がありそうです。


参考リンク

http://hylom.net/2011/03/01/how-to-reset-remote-git-branch/

http://blog.toshimaru.net/git-pushgithub



mrubyをビルドしてみる

昨晩は京都でGithub創業者の方の講演会に行ってきました。
講演内容についてまとめたいのですが、うまくまとまらないので気が向いたら書こうと思います。
ただ、今日の講演会はかなり刺激を受けました!
先月はrubyビジネスセミナーやFirefoxOSおさわり会にも参加したのですがネタはあるのですが…
苦にならないようにして続けてゆきたいと思うので、今回は勉強会レポートと違う内容について書きます。


前置きが長くなりましたが、記事タイトルの通りmrubyのビルドをしてみました。
なお、ビルドはUbuntu 12.04 LTS 64bit版で行いました。

mrubyはGithubで開発されていますので、そちらのリポジトリからソースコードを取得してmakeします。
gitが入っていない場合はgitの導入から行う必要があります。

$ sudo aptitude install git-core
$ git clone https://github.com/mruby/mruby.git
$ cd mruby
$ make
ruby ./minirake
make: ruby: コマンドが見つかりませんでした
make: *** [all] エラー 127

おっと、rubyが入っていないようです(調べてみると最近のビルドからrakeを使うようになったので必要らしい)。
rubyも最新版を使うためにビルドしてみようかと思いましたが、今回は省略してaptでrubyを導入することにしました。

$ sudo aptitude install ruby1.9.3
$ ruby -v
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-linux]

表示された日付からも古いバージョンであることがわかります。
後々rubyも自力ビルドをしたいと思います。

rubyを入れて再びmakeを実行。

$ make
ruby ./minirake
(in /home/yosuke/mruby)
CC    tools/mruby/mruby.c -> build/host/tools/mruby/mruby.o
CC    src/init.c -> build/host/src/init.o
CC    src/crc.c -> build/host/src/crc.o
CC    src/math.c -> build/host/src/math.o
CC    src/object.c -> build/host/src/object.o
CC    src/compar.c -> build/host/src/compar.o
CC    src/array.c -> build/host/src/array.o
CC    src/numeric.c -> build/host/src/numeric.o
CC    src/dump.c -> build/host/src/dump.o
CC    src/regerror.c -> build/host/src/regerror.o
CC    src/gc.c -> build/host/src/gc.o
CC    src/st.c -> build/host/src/st.o
CC    src/error.c -> build/host/src/error.o
CC    src/regparse.c -> build/host/src/regparse.o
CC    src/regexec.c -> build/host/src/regexec.o
CC    src/proc.c -> build/host/src/proc.o
CC    src/string.c -> build/host/src/string.o
CC    src/re.c -> build/host/src/re.o
CC    src/state.c -> build/host/src/state.o
CC    src/hash.c -> build/host/src/hash.o
CC    src/print.c -> build/host/src/print.o
CC    src/regcomp.c -> build/host/src/regcomp.o
CC    src/vm.c -> build/host/src/vm.o
CC    src/kernel.c -> build/host/src/kernel.o
CC    src/sprintf.c -> build/host/src/sprintf.o
CC    src/class.c -> build/host/src/class.o
CC    src/time.c -> build/host/src/time.o
CC    src/pool.c -> build/host/src/pool.o
CC    src/etc.c -> build/host/src/etc.o
CC    src/range.c -> build/host/src/range.o
CC    src/codegen.c -> build/host/src/codegen.o
CC    src/regenc.c -> build/host/src/regenc.o
CC    src/variable.c -> build/host/src/variable.o
CC    src/symbol.c -> build/host/src/symbol.o
CC    src/load.c -> build/host/src/load.o
CC    src/enum.c -> build/host/src/enum.o
CC    src/struct.c -> build/host/src/struct.o
YACC  src/parse.y -> build/host/src/y.tab.c
sh: 1: bison: not found
rake aborted!
Command Failed: ["bison" -o "build/host/src/y.tab.c" "src/parse.y"]

make: *** [all] エラー 1

今度はbisonが無いと怒られてしまいました。
これも追加します。

$ sudo aptitude install bison
$ ruby ./minirake
(in /home/yosuke/mruby)
CC    tools/mruby/mruby.c -> build/host/tools/mruby/mruby.o
CC    src/dump.c -> build/host/src/dump.o
CC    src/class.c -> build/host/src/class.o
CC    src/etc.c -> build/host/src/etc.o
CC    src/regparse.c -> build/host/src/regparse.o
CC    src/regenc.c -> build/host/src/regenc.o
CC    src/gc.c -> build/host/src/gc.o
CC    src/crc.c -> build/host/src/crc.o
CC    src/init.c -> build/host/src/init.o
CC    src/string.c -> build/host/src/string.o
CC    src/proc.c -> build/host/src/proc.o
CC    src/math.c -> build/host/src/math.o
CC    src/range.c -> build/host/src/range.o
CC    src/load.c -> build/host/src/load.o
CC    src/vm.c -> build/host/src/vm.o
CC    src/variable.c -> build/host/src/variable.o
CC    src/struct.c -> build/host/src/struct.o
CC    src/symbol.c -> build/host/src/symbol.o
CC    src/compar.c -> build/host/src/compar.o
CC    src/re.c -> build/host/src/re.o
CC    src/regcomp.c -> build/host/src/regcomp.o
CC    src/codegen.c -> build/host/src/codegen.o
CC    src/state.c -> build/host/src/state.o
CC    src/array.c -> build/host/src/array.o
CC    src/object.c -> build/host/src/object.o
CC    src/enum.c -> build/host/src/enum.o
CC    src/error.c -> build/host/src/error.o
CC    src/regexec.c -> build/host/src/regexec.o
CC    src/kernel.c -> build/host/src/kernel.o
CC    src/pool.c -> build/host/src/pool.o
CC    src/print.c -> build/host/src/print.o
CC    src/regerror.c -> build/host/src/regerror.o
CC    src/sprintf.c -> build/host/src/sprintf.o
CC    src/hash.c -> build/host/src/hash.o
CC    src/numeric.c -> build/host/src/numeric.o
CC    src/time.c -> build/host/src/time.o
CC    src/st.c -> build/host/src/st.o
YACC  src/parse.y -> build/host/src/y.tab.c
CC    build/host/src/y.tab.c -> build/host/src/y.tab.o
CC    tools/mrbc/mrbc.c -> build/host/tools/mrbc/mrbc.o
AR    build/host/lib/libmruby_core.a 
ar: creating build/host/lib/libmruby_core.a
LD    build/host/bin/mrbc 
GEN   *.rb -> build/host/mrblib/mrblib.c
      MRBC mrblib/print.rb 
      MRBC mrblib/hash.rb 
      MRBC mrblib/range.rb 
      MRBC mrblib/string.rb 
      MRBC mrblib/array.rb 
      MRBC mrblib/struct.rb 
      MRBC mrblib/enum.rb 
      MRBC mrblib/compar.rb 
      MRBC mrblib/kernel.rb 
      MRBC mrblib/class.rb 
      MRBC mrblib/numeric.rb 
      MRBC mrblib/error.rb 
CC    build/host/mrblib/mrblib.c -> build/host/mrblib/mrblib.o
AR    build/host/lib/libmruby.a 
ar: creating build/host/lib/libmruby.a
LD    build/host/bin/mruby 
CC    tools/mirb/mirb.c -> build/host/tools/mirb/mirb.o
LD    build/host/bin/mirb 

Build summary:

================================================
      Config Name: host
 Output Directory: build/host
         Binaries: mruby, mrbc, mirb
================================================

Build summaryによると出力先がbuild/hostらしいので中を見てみます。

$ ls build/host
bin  lib  mrblib  src  tools
$ ls -l build/host/bin/
合計 5524
-rwxrwxr-x 1 yosuke yosuke 1888644  2月  1 22:50 mirb
-rwxrwxr-x 1 yosuke yosuke 1871826  2月  1 22:50 mrbc
-rwxrwxr-x 1 yosuke yosuke 1891408  2月  1 22:50 mruby

mirbは対話型環境、mrbcはコンパイラ、mrubyはVMらしいです。
これでビルドは終了です。


ビルドができたので、プログラムの実行も試してみました。
GithubのmrubyページにHello Warldと実行方法が書いてあるので、こちらのページの通りに進めました。
https://github.com/mruby/mruby/wiki/Hello-World

下記のコードはGithubからの転載です。
・hello.c

#include <stdlib.h>
#include <stdio.h>

/* Include the mruby header */
#include <mruby.h>
#include <mruby/compile.h>

int main(void)
{
  mrb_state *mrb = mrb_open();
  char code[] = "p 'hello world!'";
  printf("Executing Ruby code from C!\n");

  mrb_load_string(mrb, code);
  return 0;
}

コードの意味も、gccのオプションも何も考えずにコンパイルしてみます(おいおい調べます…)。

$ gcc -Iinclude hello.c lib/libmruby.a -lm -o hello.out
gcc: エラー: mruby/lib/libmruby.a: そのようなファイルやディレクトリはありません

早速、ライブラリlibmruby.aが無いといわれてしまいました!
findコマンドで調べても見つからないので、うーんと唸ってTwitterにつぶやくとすぐに助け船がやってきました。
@masuidriveさん、ありがとうございます!


$ ls -l build/host/lib/
合計 7480
-rw-rw-r-- 1 yosuke yosuke 3840040  2月  1 22:50 libmruby.a
-rw-rw-r-- 1 yosuke yosuke     192  2月  1 22:50 libmruby.flags.mak
-rw-rw-r-- 1 yosuke yosuke 3809320  2月  1 22:50 libmruby_core.a

libmruby.aがbuild/host/libの中にありました。
(findがちゃんと使えてなかったのか… 見返すとビルドメッセージにも出力されています。)

パスを変更して再度コンパイルします。

$ gcc -Imruby/include -Imruby/include/mruby hello.c mruby/build/host/lib/libmruby.a -lm -ohello.o
$ ls hello.o
hello.o

エラーも無く、oファイルが生成されました!
生成されたhello.oを実行してみます。

$ ./hello.o
Executing Ruby code from C!
"hello world!"

正しく実行されたので、これでmrubyを開発する環境ができました!


因みに、ビルドしたmrubyディレクトリの直下にlib/libmruby.aが存在しない件についても以下のコメントをいただきました。


確かに、binディレクトリと階層構造を揃えておくとわかりやすいと思いますので、libディレクトリを新たに作ってその中にlibmruby.aを置くことにします。

$ mkdir lib
$ cp build/host/lib/* lib/
$ ls lib
libmruby.a  libmruby.flags.mak  libmruby_core.a


スクリプト言語をひとつくらい扱えるようになりたいと思っていたところ、組み込みに利用できるmrubyを知ってrubyに興味が湧きました。
今後はruby、mrubyの勉強してみようと思っています!
(良いrubyの参考書があれば教えてください。)