Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
開発効率をあげるgitテクニック / Useful git
Search
buty4649
August 27, 2018
Programming
1
950
開発効率をあげるgitテクニック / Useful git
2018/08/27にペパボ社内で行われたシェル大活用講座の発表資料です
buty4649
August 27, 2018
Tweet
Share
More Decks by buty4649
See All by buty4649
mrubyでワンバイナリーなテキストフィルタツールを作った / Building Text Filtering Tools with mruby #tokyorubykaigi
buty4649
0
110
mrubyで始める自作シェル / Handmade bash-like shell with mruby
buty4649
1
600
AWS DirectConnectを使ったハイブリットクラウドの構築と活用 / hybrid cloud with aws directconnect
buty4649
0
710
Mackerelとペパボとプラグインと / Mackerel & Pepabo & Plugins
buty4649
0
2k
プライベートクラウドではじめるDevOps / Private Cloud and DevOps
buty4649
1
3.5k
ラズパイで始める電子工作 / Raspberry PI de Asobu
buty4649
0
1.1k
5分でわかるOpenStack Octavia / OpenStack Octavia in 5min
buty4649
0
1.2k
Mackerel User Groupの説明 / about mackerel user group
buty4649
0
2.9k
100行あったmod_rewirteを ngx_mrubyで書き換えた話
buty4649
5
9k
Other Decks in Programming
See All in Programming
AIのメモリー
watany
11
1.1k
AI時代の『改訂新版 良いコード/悪いコードで学ぶ設計入門』 / ai-good-code-bad-code
minodriven
24
10k
Understanding Kotlin Multiplatform
l2hyunwoo
0
230
No Install CMS戦略 〜 5年先を見据えたフロントエンド開発を考える / no_install_cms
rdlabo
0
370
CDK引数設計道場100本ノック
badmintoncryer
2
590
脱Riverpod?fqueryで考える、TanStack Queryライクなアーキテクチャの可能性
ostk0069
0
570
Android 16KBページサイズ対応をはじめからていねいに
mine2424
0
740
Startups on Rails in Past, Present and Future–Irina Nazarova, RailsConf 2025
irinanazarova
0
310
AIに安心して任せるためにTypeScriptで一意な型を作ろう
arfes0e2b3c
0
270
MySQL9でベクトルカラム登場!PHP×AWSでのAI/類似検索はこう変わる
suguruooki
1
250
PHPUnitの限界をPlaywrightで補完するテストアプローチ
yuzneri
0
350
React は次の10年を生き残れるか:3つのトレンドから考える
oukayuka
40
15k
Featured
See All Featured
Side Projects
sachag
455
43k
A Tale of Four Properties
chriscoyier
160
23k
Thoughts on Productivity
jonyablonski
69
4.8k
Code Reviewing Like a Champion
maltzj
524
40k
BBQ
matthewcrist
89
9.8k
Intergalactic Javascript Robots from Outer Space
tanoku
271
27k
Reflections from 52 weeks, 52 projects
jeffersonlam
351
21k
Building Applications with DynamoDB
mza
95
6.5k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.5k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
60k
The Cult of Friendly URLs
andyhume
79
6.5k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Transcript
開発効率をあげるgitテクニック 〜シェル芸もあるよ〜
高谷雄貴 @buty4649 シニアエンジニア 技術部 プラットフォームグループ
git
• 普段からgitを使っている ◦ GitHub / GH:E ◦ GitHub Workflow •
gitコマンドを便利にして生産性↑↑ 今日のテーマ
• gitってなに???って話はしません ◦ ググるか誰かに聞いてください • bashを使うことを前提で書いている部分があります。 ◦ zsh/fish/bsh/ksh/csh/tcsh/ash/dash な人は適宜読み替えてください おことわり
目次 1. 減らす 2. 便利にする
PRを作る場合のオペレーション例 普段どんなオペレーションをしますか? $ git clone
[email protected]
/foo/bar $ cd bar $
git checkout -b new-branch <ファイルを変更する> $ git status $ git add foobar $ git commit $ git push origin new-branch <ブラウザを開いてPRを作る> 1.減らす
PRを作る場合のオペレーション例 普段どんなオペレーションをしますか? $ git clone
[email protected]
/foo/bar $ cd bar $
git checkout -b new-branch <ファイルを変更する> $ git status $ git add foobar $ git commit $ git push origin new-branch <ブラウザを開いてPRを作る> 打鍵数が多い! 84文字! (下線部のみ) 1.減らす
減らす
alias g=git
1.減らす • シェルのエイリアス機能 ◦ コマンドに別名を割り当てる • g で gitコマンドが実行される alias
g=git
1. 減らす • 引数はそのまま処理される ◦ g status は git status
として実行される • 引数付きのコマンドもエイリアスにできる ◦ alias gs=’git status’ とするとgsでgit statusが実行される • エイリアスを消したい場合は unalias コマンドを使う ◦ unalias g ◦ 一時的に無効にしたい場合はコマンド名の頭に \ をつける • エイリアスはカレントシェルのみに反映される ◦ 永続化したい場合は ~/.bash_profile へ エイリアス機能の補足
84文字 → 74文字!! エイリアスによって削減 $ g clone
[email protected]
/foo/bar $ cd
bar $ g checkout -b new-branch <ファイルを変更する> $ g status $ g add foobar $ g commit $ g push origin new-branch <ブラウザを開いてPRを作る> 1.減らす
まだ減らす
git config --global alias.st status
1.減らす • “git” のエイリアス機能 ◦ サブコマンドをにエイリアスをつけられる • よく使うサブコマンドを短い文字にエリアスする ◦ st
→ status, a → add など • 設定された内容は ~/.gitconfig に保存される ◦ ~ は $HOME と同じ意味 ◦ ファイルに設定を書いても良い(即時反映される) git config --global alias.st status $ cat ~/.gitconfig [alias] st = status
1.減らす gitサブコマンドのエイリアス例 $ cat ~/.gitconfig [alias] a = add cl
= clone cm = commit co = checkout cob = checkout -b p = push st = status
84文字 → 50文字!! エイリアスによって削減 $ g cl
[email protected]
/foo/bar $ cd
bar $ g cob new-branch <ファイルを変更する> $ g st $ g a foobar $ g cm $ g p origin new-branch <ブラウザを開いてPRを作る> 1.減らす
1.減らす • よく使うコマンドを短くすると効果的 • 引数を含めよく使うコマンドもエイリアスにする ◦ サブコマンド+オプションにするとよいと思う ◦ 例: git
checkout -b → git cob • シェルのエイリアスとの使い分け ◦ シェルのエイリアスにした方がサブコマンドのスペースが減らせる ◦ 例: alias gcob=’git checkout -b’ ◦ シェルの補完が効かないしコマンド名がかぶる可能性 ◦ 好みの問題かも エイリアス作成のコツ(私のやり方)
1. 減らす 私の設定例 [alias] br = branch cm = commit
-v cma = commit -v --amend cman = commit -v --amend --no-edit co = checkout cob = checkout -b d = diff dc = diff --cached g = grep 詳しくは https://github.com/buty4649/dotfiles/blob/master/cookbooks/configfiles/files/.gitconfig
もっと減らす
もっと減らす $ g cl
[email protected]
/foo/bar $ cd bar $ g
cob new-branch <ファイルを変更する> $ g st $ g a foobar $ g cm $ g p origin new-branch <ブラウザを開いてPRを作る> 1.減らす めんどくさい!
1.減らす • いちいちファイル名を書くのが手間 ◦ git add . でもいいけど、一部だけaddしたい場合不便 • 極力ファイル名を打ちたくない!
◦ 浅い階層ならいいが深い階層だとその分タイプ数が増える ファイル名を書くのがめんどくさい! どうしたらファイル名を打たずにgit addできるか?
1.減らす • git addのあとにaddしたいファイル名を羅列する ◦ git add <file1> <file2> …
• このコマンドを生成できればよい • 変更がかかったファイルはgit statusで取れる • つまり↑をいい感じにしてgit addするスクリプトを書けばよい! どうしたらファイル名を打たずにgit addできるか?
1.減らす • 生のgit statusの結果はパースしづらいのでオプションをつける スクリプトを作る $ git status --short MM
file1 ワークツリーの状態 インデックスの状態 M: 変更された A:追加された D:削除された U:更新されたがマージされていない(コンフリクトなど) ※ 詳しくはgit status --helpを参照
1.減らす • 出力結果をフィルタする必要がある ◦ Dなファイルをgit addに渡すとエラーになる ◦ addしたいファイルのみを選択したい ▪ コマンドラインセレクターを使うと便利!
▪ 例えば peco (詳しくはこのあとのudzuraさんの発表で) • スクリプトをどこに書くか? ◦ gitのエイリアスはスクリプトが書ける ◦ !を先頭に書くとスクリプトとして解釈される ◦ 例: v = !vim → git v でvimが起動する スクリプトを作る
1.減らす 完成したコマンド [alias] a = !"git status --short | awk
'!/^[ADRM] /' | peco | awk '{print $NF}' | xargs -r git add" git status --short | awk '!/^[ADRM] /' | peco | awk '{print $NF}' | xargs -r git add 先頭がADRMを除外 ファイルを選択 ファイル名のみ切り出し git addを組み立て
1.減らす 解説(awk) $ git status --short D file1 M file2
$ git status --short | awk ‘!/[ADRM] /’ M file2 $ git status --short | awk ‘!/[ADRM] /’ | > awk ‘{print $NF}’ file2
1.減らす 解説(xargs) • 標準入力をコマンドの引数に追加し実行する ◦ 例: echo b | xargs
echo a → echo a b が実行される • forやwhileでも同じことができる ◦ 例: date | xargs echo → date | while read LINE;do echo $LINE;done ◦ サブシェルを作らない分xargsのほうが早い • -r オプションをつけると入力が空の場合実行しない ◦ macOSのxargsにはないかも… • 通常は末尾に引数を追加するが-Iで任意の場所に追加できる ◦ -Iに続いて置換する文字列を書く ◦ 2文字以上でも使える ◦ 例: date | xargs -I{} echo {} hogehoge • これ以外にもすごく便利なのだけどそれを書くには十分な余白がry
1.減らす これでpushはgit gpushでいけるようになる git push origin new-branchも短くする [alias] gpush =
!"git rev-parse --abbrev-ref HEAD | xargs git push origin" $ git rev-parse --abbrev-ref HEAD new-branch
1.減らす これでpushはgit gpushでいけるようになる git push origin new-branchも短くする [alias] gpush =
!"git rev-parse --abbrev-ref HEAD | xargs git push origin" $ git rev-parse --abbrev-ref HEAD new-branch
1.減らす • git push origin HEAD でいける ◦ この資料を作っているときに知った。。 •
つまり、↑をエイリアスすればよい git push origin new-branchも短くする [alias] gpush = push orogin HEAD
1.減らす 私の設定例 # ブランチを選択してcheckout c = !"git branch | awk
'!/^\\*/' | peco | xargs -r git checkout" # リモートブランチを選択してcheckout cobr = !"git branch -r | grep -vE '/(HEAD|master$)' | sed -e 's,origin/,,g' | peco | xargs -r -I{} git checkout -b {} origin/{}" # 変更されたファイルを選択してcheckout cof = !"git status --short | peco | awk '{print $2}' | xargs -r git checkout --" ※ \ はエスケープする必要がある
84文字 → 29文字!! 65%効率アップ!!!! 最終結果 $ g cl
[email protected]
/foo/bar $
cd bar $ g cob new-branch <ファイルを変更する> $ g st $ g a $ g cm $ g gpush <ブラウザを開いてPRを作る> 1.減らす
目次 1. 減らす 2. 便利にする
• 減らすではタイプ数を減らすことに注力した • 次はタイプ数削減以外の方法で効率化する • 便利なツールや機能を使ってより作業効率をあげる 2.便利にする
2.便利にする git-completion.bash & git-prompt.sh • gitをインストールするとついてくる便利スクリプト • bashの補完機能を提供 ◦ (brew)
/usr/local/etc/bash_completion.d/git-completion.bash ◦ sourceで読み込む • プロンプトにカレントブランチを表示 ◦ (brew) /usr/local/etc/bash_completion.d/git-prompt.sh ◦ PS1環境変数に __git_ps1関数を追加する $ git branch 20180827-pepabo-college ~/path/to/hoge ( 20180827-pepabo-college ) $ echo $PS1 \w$(__git_ps1 " (\[\e[0;31m\]%s\[\e[00m\])")\n\$
2.便利にする ghq • ローカルリポジトリの管理ツール ◦ https://github.com/motemen/ghq • 指定のディレクトリ配下にgit cloneする ◦
デフォルトは ~/.ghq ◦ GOPATHと合わせておくと便利 ▪ git config --global ghq.root ~/src • 使い方 ◦ リモートリポジトリのクローン ▪ ghq get <リモートブランチのURL> ◦ ローカルリポジトリのフルパスを一覧で表示 ▪ ghq list -p
2.便利にする ghq • ghq list と pecoを組み合わせて移動できる ◦ cd $(ghq
list -p | peco) • これをコマンドにする ◦ 外部コマンドではcdできないので関数で定義する ◦ 例: gcd() { cd $(ghq list -p | peco); }
2.便利にする tig • TUIなgitクライアント ◦ https://github.com/jonas/tig • 詳しくはこのあとのjune29の発表で!!! • 私の使い方
◦ git ll にエイリアスしている ◦ fixup / squash できるようにしている $ cat ~/.gitconfig [tig "bind"] diff = F ?!git commit --fixup %(commit) diff = S ?!git commit --squash %(commit) main = F ?!git commit --fixup %(commit) main = S ?!git commit --squash %(commit)
2.便利にする hub • Github社が作ったgitコマンドラッパー ◦ https://github.com/github/hub • gitにエイリアスして使う ◦ eval
$(hub alias -s) • gitに機能を追加する ◦ issueやPRの作成ができる ◦ 詳しくは https://hub.github.com/hub.1.html • ローカルリポジトリでhub browseすると便利 ◦ GH:Eなリポジトリを見るときは設定が必要 ◦ git config --global hub.host <GHEのFQDN>
2.便利にする git hookを使う • 特定のアクションの実行前/後にスクリプトを実行する ◦ 詳しくは https://git-scm.com/docs/githooks • hookスクリプトは
.git/hooks 配下にある ◦ 例えばcommit前にhookするなら ▪ .git/hooks/pre-commit ▪ chmod +x するのを忘れない(重要)
2.便利にする hook利用例(1): プッシュ前にlintを行う • プッシュした後にCIのlintチェックで落ちると悲しい… • git pushする前にlintすれば回避できる! $ cat
.git/hooks/pre-push #!/bin/bash rake lint • しかし、プッシュに時間がかかるようになるというデメリット
2.便利にする hook利用例(2): master pushを防ぐ • master pushやりがち • Github側で設定変更するという手段もある ◦
すべてのリポジトリに設定するのは手間 • hookを使って防ぐ
2.便利にする hook利用例(2): master pushを防ぐ https://github.com/buty4649/dotfiles/blob/master/cookbooks/configfiles/files/.git_template/hooks/pre-push $ cat .git/hooks/pre-push #!/bin/bash CURRENT_BRANCH="$(git
rev-parse --abbrev-ref HEAD)" if [ "$CURRENT_BRANCH" = "master" ];then if [ -z "$ALLOW_GIT_MASTER_PUSH" -a \ -z "$(git config --get git.allow-master-push)" ];then echo "WARN: It's the master branch !!" echo 'If you want git push, please set either.' echo '* $ALLOW_GIT_MASTER_PUSH=1' echo '* git config --local git.allow-master-push 1' exit 1 fi fi
2.便利にする hook利用例(2): master pushを防ぐ $ git branch master $ git
push WARN: It's the master branch !! If you want git push, please set either. * $ALLOW_GIT_MASTER_PUSH=1 * git config --local git.allow-master-push 1 error: failed to push some refs to 'foobar'
2.便利にする hook利用例(2): master pushを防ぐ • master pushしなくなって悲しみが減った • ただ、master pushでもいいときに回避するのが手間
◦ プロンプトをだしてyを入力したらpushでもいいかも • hookにスクリプトを直接書くと変更するときに面倒 ◦ hookからはコマンドを呼び出すだけにしたほうが良いかも • git init / git cloneの度にhookを配置するのが手間 ◦ git-templateを使うと便利 ◦ https://git-template.readthedocs.io/en/latest/ • すでにあるリポジトリに設置したい ◦ ghq list -p | xargs -L1 -I{} cp -pv pre-push "{}/.git/hooks" ◦ (自信なし)
まとめ
まとめ • gitコマンドのタイプ数を減らすと効率があがる • シェルスクリプトを駆使してサブコマンドを作ると便利だし楽しい • 便利なツールを使うとより生産性があがる