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
860
開発効率をあげるgitテクニック / Useful git
2018/08/27にペパボ社内で行われたシェル大活用講座の発表資料です
buty4649
August 27, 2018
Tweet
Share
More Decks by buty4649
See All by buty4649
mrubyで始める自作シェル / Handmade bash-like shell with mruby
buty4649
1
440
AWS DirectConnectを使ったハイブリットクラウドの構築と活用 / hybrid cloud with aws directconnect
buty4649
0
600
Mackerelとペパボとプラグインと / Mackerel & Pepabo & Plugins
buty4649
0
1.7k
プライベートクラウドではじめるDevOps / Private Cloud and DevOps
buty4649
1
3.3k
ラズパイで始める電子工作 / Raspberry PI de Asobu
buty4649
0
1.1k
5分でわかるOpenStack Octavia / OpenStack Octavia in 5min
buty4649
0
1.1k
Mackerel User Groupの説明 / about mackerel user group
buty4649
0
2.8k
100行あったmod_rewirteを ngx_mrubyで書き換えた話
buty4649
5
8.6k
Other Decks in Programming
See All in Programming
ビット演算の話 / Let's play with bit operations
kaityo256
PRO
4
170
"Swarming" をコンセプトに掲げるアジャイルチームのベストプラクティス
boykush
2
210
App Router 悲喜交々
quramy
7
370
Subclassing, Composition, Python, and You
hynek
3
110
MLOps in Mercari Group’s Trust and Safety ML Team
cjhj
1
110
Modern Functional Fluent CFML REST by Luis Majano
ortus24
0
130
RemixとCloudflare Stack におけるFile Upload
ossamoon
1
120
Unlocking Python's Core Magic
leew
0
120
Интеграционное тестирование: как приручить хаос
mariyasaygina
0
510
pytest プラグインを開発して DRY に自動テストを書こう
inuatsu
2
250
Progressive Web Apps for Rails developers
siaw23
2
530
"noncopyable types" の使いどころについて考えてみた
andpad
0
140
Featured
See All Featured
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
92
16k
GraphQLの誤解/rethinking-graphql
sonatard
65
9.9k
How GitHub (no longer) Works
holman
311
140k
A Modern Web Designer's Workflow
chriscoyier
692
190k
Embracing the Ebb and Flow
colly
83
4.4k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
158
15k
Practical Orchestrator
shlominoach
185
10k
VelocityConf: Rendering Performance Case Studies
addyosmani
324
23k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
364
22k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
7
560
XXLCSS - How to scale CSS and keep your sanity
sugarenia
246
1.3M
Fashionably flexible responsive web design (full day workshop)
malarkey
403
65k
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コマンドのタイプ数を減らすと効率があがる • シェルスクリプトを駆使してサブコマンドを作ると便利だし楽しい • 便利なツールを使うとより生産性があがる