( ꒪⌓꒪) ゆるよろ日記

( ゚∀゚)o彡°オパーイ!オパーイ! ( ;゚皿゚)ノシΣ フィンギィィーーッ!!!

.gitconfigでFizzBuzz

.gitconfigのtipsを公開するのが流行ってるみたいなので。

git config alias.fizzbuzz "!f() { seq "$@" | awk '$0=NR%15?NR%5?NR%3?$0:\"Fizz\":\"Buzz\":\"FizzBuzz\"' ;}; f"

( ꒪⌓꒪) git fizzbuzz <num> · 7a4ddcd · yuroyoro/dotfiles · GitHub


git fizzbuzz で実行

ozaki@mbp-4 $ git fizzbuzz 30 
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz


Fizzbuzzも書けないプログラマは(炎上ワードにつき削除)

実体はawkです。
AWK Users JP :: awk で FizzBuzz

指定したコミットで修正されたファイルをvimで開く

.gitconfigにこういうalias書いた。'git modified HEAD~'で一つ前のコミットで修正されたファイルをvimで開く

[alias]
  # 指定したコミットで変更されたファイルを編集する
  modified = "!f() { git diff $1..$1\\^ --name-only | xargs sh -c 'vim "$@" < /dev/tty' - ;}; f"

dotfiles/.gitconfig at master · yuroyoro/dotfiles · GitHub


もっとうまい方法ないんか?あ

git cherryでブランチ間のコミットのdiffを。色もつけて

git cherryで、ブランチ・ツリー間のコミットのdiffを見ることができる。

git cherry [-v] [<upstream> [<head> [<limit>]]]


デフォルトでは、upsteamに無いコミットは"+"で、逆にheadになくてupstreamにあるコミットは"-"で表示される。それとsha1のみ。味もそっけもない。

f:id:yuroyoro:20121022153203p:plain


"git cherry -v"で、コミットログもでる。

f:id:yuroyoro:20121022153223p:image:w640


これでも充分だけど、もっとdiffっぽく色付けたり、Autherや日付表示したりしたい。のでこんなalias書いた

  # colorized cheery -v
  cch= "!f() { git cherry -v "$@" | awk '{ if($1 == \"+\"){ color = \"green\" } if($1 == \"-\"){ color = \"red\" } cmd = \"git show --date=short --no-notes --pretty=format:\\047%C\" color $1 \" %h %Cgreen%cd %Cblue%cn%x09%Creset%s\\047 --summary \" $2; cmd | getline t; close(cmd); print t }' ;}; f"

( ꒪⌓꒪) Add git cch as colorized git cherry · 859732d · yuroyoro/dotfiles · GitHub


こんな表示になる。

f:id:yuroyoro:20121022153303p:image:w640


awkコワイ。

git-issue : CLIでRedmine/Github-issuesのticketをbrows/editできるgitサブコマンド

というのを作ったました。ちょこちょこ機能改善してます。


yuroyoro/git-issue · GitHub
git-issue | RubyGems.org | your community gem host


仕事では、異臭管理システムはRedmineを使っていて、作業はsshでサーバに入ってコード書いてるわけです。


で、次どのチケットやろうか、とか今やってるチケットの細かい仕様どうだっけ?みたいなときに、
いちいちブラウザに切り替えて目的のチケットを検索するのタルすぎて死ねる。


もうターミナルから離れたくないんだ俺は。


そこで、'git issue 1000'ってやると1000番のチケットを見ることができるようにした。

$ git issue 15

[open] #15 Issueをadd/updateするときに引数で全部渡すのタルい
--------------------------------------------------------------------------------
yuroyoro opened this issue Tue Feb 28 03:38:17 UTC 2012

comments           : 0                        votes              :
position           :
labels             : 
html_url           : https://github.com/yuroyoro/git-issue/issues/15
updated_at         : Tue Feb 28 03:38:17 UTC 2012
-----------------------------


'git issue list'ってやると一覧な。

$ git issue list

#4     open  tracとか                                           yuroyoro   c:0 v:0 p:0 2012/02/17 2012/02/17
#12    open  proxy環境下での利用についてもそっと何とか汁        yuroyoro   c:0 v:0 p:0 2012/02/24 2012/02/24
#15    open  Issueをadd/updateするときに引数で全部渡すのタルい  yuroyoro   c:0 v:0 p:0 2012/02/28 2012/02/28


pull requestを送ってくれた皆さんありがとう!

screenshots

f:id:yuroyoro:20120301143816p:image:w640
f:id:yuroyoro:20120301143815p:image:w640

setup

'gem install git-issue'で入る。あとは、 README読んでくれ。

usage

git issue helpでコマンドとオプションの一覧が出てくる。RedmineとGithubで微妙にコマンドやオプションが違うので注意。以下は、Githubの場合

git issue <command> [ticket_id] [<args>]
  Commnads:
show     s show given issue summary. if given no id,  geuss id from current branch name.
list     l listing issues.
mine     m display issues that assigned to you.
commit   c commit with filling issue subject to messsage.if given no id, geuss id from current branch name.
add      a create issue.
update   u update issue properties. if given no id, geuss id from current branch name.
branch   b checout to branch using specified issue id. if branch dose'nt exisits, create it. (ex ticket/id/<issue_id>)
publish  pub push branch to remote repository and set upstream 
rebase   rb rebase branch onto specific newbase
help     h show usage.
mention  men create a comment to given issue

  Options:
    -a, --all                        update all paths in the index file 
    -f, --force                      force create branch
    -v, --verbose                    show issue details
    -n, --max-count=VALUE            maximum number of issues 
        --oneline                    display short info
        --raw-id                     output ticket number only
        --remote=VALUE               on publish, remote repository to push branch 
        --onto=VALUE                 on rebase, start new branch with HEAD equal to "newbase" 
        --debug                      debug print
    -s, --supperss_commentsc         show issue journals
        --title=VALUE                Title of issue.Use the given value to create/update issue.
        --body=VALUE                 Body content of issue.Use the given value to create/update issue.
        --state=VALUE                Use the given value to create/update issue. or query of listing issues.Where 'state' is either 'open' or 'closed'
        --milestone=VALUE            Use the given value to create/update issue. or query of listing issues, (Integer Milestone number)
        --assignee=VALUE             Use the given value to create/update issue. or query of listing issues, (String User login)
        --mentioned=VALUE            Query of listing issues, (String User login)
        --labels=VALUE               Use the given value to create/update issue. or query of listing issues, (String list of comma separated Label names)
        --sort=VALUE                 Query of listing issues, (created,  updated,  comments,  default: created)
        --direction=VALUE            Query of listing issues, (asc or desc,  default: desc.)
        --since=VALUE                Query of listing issue, (Optional string of a timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ)
        --password=VALUE             For Authorizaion of create/update issue.  Github API v3 does'nt supports API token base authorization for now. then, use Basic Authorizaion instead token.
        --sslnoverify                don't verify SSL

基本的な使い方は以下の通り。

  • 'git issue 'でチケットの詳細が表示される。
  • 'git issue list'で一覧表示。
  • 'git issue add'でチケット登録。内容は、コマンドライン引数でオプションで渡すなどしてくれ。
  • 'git issue update 'で更新する。

ぼくのかんがえたさいきょうのGit Repository Browser

こんなヤツ

デモサイトはこちら http://gitterb.yuroyoro.net/


f:id:yuroyoro:20110707204302p:image:w360

Gitである程度運用してると、ブランチがいっぱいになっていつどこから生えたのかわからなくなったり、どのブランチがマージされてるか把握できなかったりとかがあると思う。
たとえばgit log --graph とかgit merge-baseとかコマンドで頑張ればいいんだけど、俺はあまり頭良くないし記憶力もないので、コミットのつながりをグラフィカルに表示してほしいと常々思っていたわけ。

たとえばGitXとかgitkとかGit Towerとかのツリー表示って、こんな感じじゃないですか。

f:id:yuroyoro:20110707204305p:image:w360

これはこれでまぁいいんだけど、この程度ならlog --graphやtigを使えばいいのでわざわざGUI起動するまでもないし、そもそもあんまりグラフィカルじゃない。見たいのは、Pro Gitとかにあるようなコミットを○と矢印でつないだ有向グラフな図なんだよ。


で、あんまりにもないので作った。

yuroyoro/gitterb · GitHub


Ruby1.9.2とRails3.0.9で動作確認してる。多分Ruby1.8.7/Rails2.3でも動くと思うけど確認してない。

LGPLなライセンスで。テストは、書いてない。pull request歓迎します。

セットアップ

pygementが必要なのでeasy_installでいれろ

 sudo easy_install pygments

Bundler使って依存Gem入れろ

    gem install bundler # if you haven't
    bundle install ./vendor/bundle

config/database.ymlに表示するgitリポジトリを絶対パスで指定しる

    development:
      repository: '/home/your_name/your_repository'

サーバ起動して、'http://localhsost:3000'で表示させり

    script/rails server

使い方的なアレ

とりあえず最初はmasterからさかのぼって100件分のコミットを出す。一緒に、表示されているコミットに到達可能なブランチとそのコミットもだす。これは'all'チェックボックスをoffると消える。
赤い時の四角がブランチで、青いのがtagな。
git log --graph --all的なイメージで表示してると思え。思え。

f:id:yuroyoro:20110707204303p:image


フォーカスするブランチを切り替えたいならプルダウンから選べばいいんじゃない?好きにすれば?


○で表示してるのがコミットオブジェクトな。マウス乗せるとコミットログをポップアップさせる。させる。

f:id:yuroyoro:20110707204304p:image

クリックすると、そのコミットの詳細が出る。ダブルクリックすると消える。以上。

できないこと

  • 複数のリポジトリを切り替えたり
  • リモートのブランチを出したり(fetchしろ)
  • comitしたりpullしたりrebaseしたりpushしたり(そういうのはもっと高機能なGUIツールでやるのがいいとおもいます)

.gitconfigに設定してるaliasなどのまとめ

22:56 @thinca さんからの指摘を追記



「そんな.gitconfigで大丈夫か?」
f:id:yuroyoro:20101006140122p:image


そんなわけで、仕事でもモリンモリンにgitしてるわけですが、わからないことがある度についったーにポストしてみなさまの好意とネットの集合知に助けられているゆろよろですこんにちウォー。


で、この前「gitの便利な設定知りたいから.gitconfig晒してください。」とお願いしたらいろいろな人から情報を頂いたのでまとめます。@kenchan さん、@mincemaker さん、@kiy0taka さんありがとウォー。

[user]
  name = ozaki
  email = ozaki@yuroyoro.com
[color]
  # colorの設定(以下のコマンドは自動で色つける)
  status = auto
  diff = auto
  branch = auto
  interactive = auto
  grep = auto
[push]
  default = tracking       # defaultのpush先はtrackingしているリポジトリ
[core]
  excludesfile = ~/.gitignore  # globalな.gitignoreの指定
  autocrlf = input                 # CRLFを自動変換
[alias]
  st = status
  sh = show
  so = remote show origin
  ft = fetch
  up = pull --rebase       # pull rebase
  rbm = rebase master      # masterへのrebaseはよく使うのでalias
  ad = add
  ci = commit -a           # modifiedなファイルを全てstageへ
  cam = commit -a --amend  # 直前のcommitを修正
  co = checkout
  # branch関連
  br = branch
  ba = branch -a           # originも含めた全てのbranchを表示
  bm = branch --merged     # merge済みのbranchを表示
  bn = branch --no-merged  # mergeしてないbranchを表示
  # log関連
  wc = whatchanged         # logに変更されたファイルも一緒に出す
  ls = log --stat          # logに変更されたファイルも一緒に出す
  lp = log -p              # diffも一緒に出す
  la = log --pretty=\"format:%ad %h (%an): %s\" --date=short  # ざっくりログ出す
  lr = log origin          # originのlog
  oneline = log --pretty=oneline
  ranking = shortlog -s -n --no-merges
  # logをtree表示
  log-graph = log --graph --date=short --pretty=format:'%Cgreen%h %cd %Cblue%cn %Creset%s'
  log-all = log --graph --all --color --pretty='%x09%h %cn%x09%s %Cred%d%Creset'
  # diff関連
  dm = diff master           # masterとのdiff
  dw = diff --color-words    # 単語単位でいろつけてdiff
  dc = diff --cached         # addされているものとのdiff
  ds = diff --staged         # 同上(1.6.1移行)
  d1 = diff HEAD~            # HEADから1つ前とdiff
  d2 = diff HEAD~~           # HEADから2つ前とdiff
  d3 = diff HEAD~~~          # HEADから3つ前とdiff
  d4 = diff HEAD~~~~         # HEADから4つ前とdiff
  d5 = diff HEAD~~~~~        # HEADから5つ前とdiff
  d10 = diff HEAD~~~~~~~~~~  # HEADから10前とdiff
  # mergeの際にconflictが起きたファイルを編集
  edit-unmerged = "!f() { git ls-files --unmerged | cut -f2 | sort -u ; }; vim `f`"
  # mergeの際にconflictが起きたファイルをadd
  add-unmerged = "!f() { git ls-files --unmerged | cut -f2 | sort -u ; }; git add `f`"
  # grep関連
  gr = grep
  gn = grep -n

dotfile関連は.gitconfigも含めてGitHubに置いてありますんで。
http://github.com/yuroyoro/dotfiles/blob/master/.gitconfig

他にも「こんなのが便利!」というのがあったらコメントもらえるとありがたいです。


「大丈夫だ。問題ない。」
f:id:yuroyoro:20101006140123p:image


以下、特に便利!とかおもろい!とかおもったものを紹介します。

CUIでもLogをtree表示

# logをtree表示
  log-graph = log --graph --date=short --pretty=format:'%Cgreen%h %cd %Cblue%cn %Creset%s'
  log-all = log --graph --all --color --pretty='%x09%h %cn%x09%s %Cred%d%Creset'

branchがいっぱいあったりしてツリーがどうなってんの?ってときにグラフィカルに見れたら便利ですよね。gitkとかGitXでも見ることができますが、サーバー上で作業してたりしてXとかウゼェってときに、こんな風に見ることが出来て重宝します。
f:id:yuroyoro:20101008185108p:image

サンプルとしてtwitter4jを使わせてもらいました。GitXで見るとこんな感じです。ほぼいっしょですね。
f:id:yuroyoro:20101008185216p:image

1つ前や2つ前のcommitとのdiff

@mincemaker さんからパクらせてもらいました。^^^とか入力めんどいのでなるほどと思いました。

  d1 = diff HEAD~            # HEADから1つ前とdiff
  d2 = diff HEAD~~           # HEADから2つ前とdiff
  d3 = diff HEAD~~~          # HEADから3つ前とdiff
  d4 = diff HEAD~~~~         # HEADから4つ前とdiff
  d5 = diff HEAD~~~~~        # HEADから5つ前とdiff
  d10 = diff HEAD~~~~~~~~~~  # HEADから10前とdiff


あと、HEAD^とHEAD~は微妙に動作が異なることを@thinca さんから指摘してもらいました。
このあたりはGit と GitHub を体験しながら身につける勉強会行ってきた - 予定は未定Blog版に非常にわかりやすく解説してあります。この記事はgit使うなら必読です。

conflictが起きたときのファイルを編集/addする

conflictが起きてmergeが必要になったときに、対象のファイルを一括して編集したりaddしたりします。

  # mergeの際にconflictが起きたファイルを編集
  edit-unmerged = "!f() { git ls-files --unmerged | cut -f2 | sort -u ; }; vim `f`"
  # mergeの際にconflictが起きたファイルをadd
  add-unmerged = "!f() { git ls-files --unmerged | cut -f2 | sort -u ; }; git add `f`"

logにそのコミットで変更されたファイルも一緒にだす

git whatchangedで、こんな感じでlogに変更されたファイルも一緒に出すことができます。地味に便利。

commit e903c577fb3401b4c66037dfc477e73e6851e8e1
Author: Yusuke Yamamoto <yusuke@mac.com>
Date:   Wed Apr 21 20:23:16 2010 +0900

    added some logging message

:100644 100644 bfe6eb9... 33b8ce3... M  twitter4j-core/src/main/java/twitter4j/internal/http/HttpClientFactory.java

commit 925ada673cd56f9d49f1451c7ca192f039d897de
Author: Yusuke Yamamoto <yusuke@mac.com>
Date:   Wed Apr 21 01:41:16 2010 +0900

    TFJ-342 Streaming API: wait time for TCP level error is always initialized to 250ms

:100644 100644 d3694e1... 6e6a7bd... M  twitter4j-core/src/main/java/twitter4j/TwitterStream.java

commit 5169a3363b4808f3b0ee498534511530e3b9318b
Author: Yusuke Yamamoto <yusuke@mac.com>
Date:   Tue Apr 20 23:17:41 2010 +0900

    TFJ-341 StackOverFlowError at RequestToken.hashCode() - fixed infinite loop in hashCode()

:100644 100644 955250a... 5766efb... M  twitter4j-core/src/main/java/twitter4j/http/RequestToken.java
:100644 100644 7239976... ac6f381... M  twitter4j-core/src/test/java/twitter4j/http/OAuthTest.java

@thinca さんにlog --statというものがあると教えてもらいました。確かにこちらの出力のほうが見やすいですね。

ozaki@yuroyoro-MacBook $ git log --stat                                                                        (git)-[master][~/sandbox/java/twitter4j] 
commit e903c577fb3401b4c66037dfc477e73e6851e8e1
Author: Yusuke Yamamoto <yusuke@mac.com>
Date:   Wed Apr 21 20:23:16 2010 +0900

    added some logging message

 .../twitter4j/internal/http/HttpClientFactory.java |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

commit 925ada673cd56f9d49f1451c7ca192f039d897de
Author: Yusuke Yamamoto <yusuke@mac.com>
Date:   Wed Apr 21 01:41:16 2010 +0900

    TFJ-342 Streaming API: wait time for TCP level error is always initialized to 250ms

 .../src/main/java/twitter4j/TwitterStream.java     |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

commit 5169a3363b4808f3b0ee498534511530e3b9318b
Author: Yusuke Yamamoto <yusuke@mac.com>
Date:   Tue Apr 20 23:17:41 2010 +0900

    TFJ-341 StackOverFlowError at RequestToken.hashCode() - fixed infinite loop in hashCode()

 .../src/main/java/twitter4j/http/RequestToken.java |   20 --------------------
 .../src/test/java/twitter4j/http/OAuthTest.java    |    1 +
 2 files changed, 1 insertions(+), 20 deletions(-)

Globalな.gitignoreと、プロジェクト固有で自分だけ無視したいファイルの設定

core.excludesfileに.gitignoreを指定することで、全てのプロジェクトで無視したいファイルを設定できます。


で、$HOME/.gitignoreには書きたくなくて、プロジェクトのリポジトリにはプロジェクト固有の.gitignoreが登録されていて、自分だけそのプロジェクトで無視したいファイルを指定したいしたいときには、プロジェクト内の".git/info/exclude"に指定すればよいそうです。(@kenchan さんありがとウォー)

/vendor/plugins/b/ 
*.bak

このように".git/info/exclude"に書いておくと、プロジェクト固有の.gitignoreを汚染することなく自分だけ無視したいファイルを設定できます。