SlideShare ist ein Scribd-Unternehmen logo
1 von 91
Downloaden Sie, um offline zu lesen
Gitの便利ワザ
K.Tateishi
@ktateish
TechLunch #23
2015/07/24
オーバービュー
Git生活を少し便利にする小技や運用のコツを紹
介します。
● ファーストペアレントを辿ろう
● 使い捨て統合ブランチを使おう
ファーストペアレントを辿ろう
モチベーション
こういう人向けのはなし:
「他のリポジトリの履歴を見たら,マージでコミット
が入り乱れててログがよくわからない。」
ファーストペアレントを辿れば解決
そもそもファーストペアレントって何?
→ Gitのコミットに一番最初に記録される親のこと。
???
おさらい: Gitにおけるコミット
Gitのコミットには以下のものが記録される
● ツリーオブジェクトの名前
● 親コミットの名前
● オーサ―,コミッター,それぞれの時刻
● コミットメッセージ
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
% git rev-parse HEAD^
6f73c5b7753ffca739ae24f489617c7652e2728e
% git cat-file -p 6f73c5b7753ffca739ae24f489617c7652e2728e
tree 48df9351f27ba6927521a99575d85cf9805360c3
parent 9db8e21517181dae8cc9dda22f63db818d13edde
author Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
committer Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
Add a beautiful feature: JswFAA
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
% git rev-parse HEAD^
6f73c5b7753ffca739ae24f489617c7652e2728e
% git cat-file -p 6f73c5b7753ffca739ae24f489617c7652e2728e
tree 48df9351f27ba6927521a99575d85cf9805360c3
parent 9db8e21517181dae8cc9dda22f63db818d13edde
author Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
committer Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
Add a beautiful feature: JswFAA
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
% git rev-parse HEAD^
6f73c5b7753ffca739ae24f489617c7652e2728e
% git cat-file -p 6f73c5b7753ffca739ae24f489617c7652e2728e
tree 48df9351f27ba6927521a99575d85cf9805360c3
parent 9db8e21517181dae8cc9dda22f63db818d13edde
author Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
committer Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
Add a beautiful feature: JswFAA
コミット
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
% git rev-parse HEAD^
6f73c5b7753ffca739ae24f489617c7652e2728e
% git cat-file -p 6f73c5b7753ffca739ae24f489617c7652e2728e
tree 48df9351f27ba6927521a99575d85cf9805360c3
parent 9db8e21517181dae8cc9dda22f63db818d13edde
author Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
committer Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
Add a beautiful feature: JswFAA
名前は 6f73c5b...
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
% git rev-parse HEAD^
6f73c5b7753ffca739ae24f489617c7652e2728e
% git cat-file -p 6f73c5b7753ffca739ae24f489617c7652e2728e
tree 48df9351f27ba6927521a99575d85cf9805360c3
parent 9db8e21517181dae8cc9dda22f63db818d13edde
author Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
committer Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
Add a beautiful feature: JswFAA
親コミットは
9db8e2...
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
% git rev-parse HEAD^
6f73c5b7753ffca739ae24f489617c7652e2728e
% git cat-file -p 6f73c5b7753ffca739ae24f489617c7652e2728e
tree 48df9351f27ba6927521a99575d85cf9805360c3
parent 9db8e21517181dae8cc9dda22f63db818d13edde
author Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
committer Katsuyuki TATEISHI <kt@wheel.jp> 1437109176 +0900
Add a beautiful feature: JswFAA
親コミット。
名前は 9db8e2...
親コミットは
9db8e2...
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
%
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
%
コミットはいくらでも
子供を持てる
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
%
と,言うよりひとつの
親コミットを何個の子
コミットから指しても
いい
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
% 子コミットからも複数
の親を指せる
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
%
マージコミット
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
マージコミットの中身
は・・・
←
% git rev-parse HEAD
bfd06b18bde5540ebc760a269c2cea1a30d65f76
% git cat-file -p bfd06b18bde5540ebc760a269c2cea1a30d65f76
tree 1a5518ceeb8d8b804dd692d8082cd92655f3ab41
parent 6f73c5b7753ffca739ae24f489617c7652e2728e
parent c5ab51f0d2c899150d937e0bf8c9e1febf4210bf
author Katsuyuki TATEISHI <kt@wheel.jp> 1437109187 +0900
committer Katsuyuki TATEISHI <kt@wheel.jp> 1437109187 +0900
Merge branch 'feature1'
* feature1:
Add a prominent feature: h4ACFD
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
マージコミットの親
% git rev-parse HEAD
bfd06b18bde5540ebc760a269c2cea1a30d65f76
% git cat-file -p bfd06b18bde5540ebc760a269c2cea1a30d65f76
tree 1a5518ceeb8d8b804dd692d8082cd92655f3ab41
parent 6f73c5b7753ffca739ae24f489617c7652e2728e
parent c5ab51f0d2c899150d937e0bf8c9e1febf4210bf
author Katsuyuki TATEISHI <kt@wheel.jp> 1437109187 +0900
committer Katsuyuki TATEISHI <kt@wheel.jp> 1437109187 +0900
Merge branch 'feature1'
* feature1:
Add a prominent feature: h4ACFD
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
親がふたつ
% git rev-parse HEAD
bfd06b18bde5540ebc760a269c2cea1a30d65f76
% git cat-file -p bfd06b18bde5540ebc760a269c2cea1a30d65f76
tree 1a5518ceeb8d8b804dd692d8082cd92655f3ab41
parent 6f73c5b7753ffca739ae24f489617c7652e2728e
parent c5ab51f0d2c899150d937e0bf8c9e1febf4210bf
author Katsuyuki TATEISHI <kt@wheel.jp> 1437109187 +0900
committer Katsuyuki TATEISHI <kt@wheel.jp> 1437109187 +0900
Merge branch 'feature1'
* feature1:
Add a prominent feature: h4ACFD
1→
2→
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
ひとつめの親
% git rev-parse HEAD
bfd06b18bde5540ebc760a269c2cea1a30d65f76
% git cat-file -p bfd06b18bde5540ebc760a269c2cea1a30d65f76
tree 1a5518ceeb8d8b804dd692d8082cd92655f3ab41
parent 6f73c5b7753ffca739ae24f489617c7652e2728e
parent c5ab51f0d2c899150d937e0bf8c9e1febf4210bf
author Katsuyuki TATEISHI <kt@wheel.jp> 1437109187 +0900
committer Katsuyuki TATEISHI <kt@wheel.jp> 1437109187 +0900
Merge branch 'feature1'
* feature1:
Add a prominent feature: h4ACFD
1→
2→
merge実行時にチェックアウトしてあったブランチヘッドがファーストペアレントになる。
Gitにおけるコミットの具体例
cat-file でGitオブジェクトの中身を表示
ファースト
ペアレント
% git rev-parse HEAD
bfd06b18bde5540ebc760a269c2cea1a30d65f76
% git cat-file -p bfd06b18bde5540ebc760a269c2cea1a30d65f76
tree 1a5518ceeb8d8b804dd692d8082cd92655f3ab41
parent 6f73c5b7753ffca739ae24f489617c7652e2728e
parent c5ab51f0d2c899150d937e0bf8c9e1febf4210bf
author Katsuyuki TATEISHI <kt@wheel.jp> 1437109187 +0900
committer Katsuyuki TATEISHI <kt@wheel.jp> 1437109187 +0900
Merge branch 'feature1'
* feature1:
Add a prominent feature: h4ACFD
1→
2→
merge実行時にチェックアウトしてあったブランチヘッドがファーストペアレントになる。
ふーん,で?
ファーストペアレントが何かはわかったけど,それ
の何が嬉しいの?
→ git log --first-parent とやると,
ファーストペアレントだけ辿る
ようになる。右図だとイマイチ
嬉しさがないけど・・・
ファーストペアレントが何かはわかったけど,それ
の何が嬉しいの?
こんな感じに入り乱れてると,
git log を読み解くのは,
人類には不可能
ふーん,で?
ファーストペアレントが何かはわかったけど,それ
の何が嬉しいの?
git log --first-parent なら
ファーストペアレント
だけを辿れる
(gitkとかも同様)
ふーん,で?
例えばLinuxの v4.0 から v4.1 までに何が起こっ
たのか調べたい → git log しても・・・
実例
(...略...)
fd25cdd ARM: shmobile: lager: Add DU HDMI output support
3f47da0 rcu_tree: Avoid touching rnp->completed when a new GP is started
ee376db rcu: Consolidate rcu_synchronize and wakeme_after_rcu()
5d8a421 power_supply core: support use of devres to register/unregister a power supply.
329414c Merge tag 'topic/drm-misc-2015-02-25' of git://anongit.freedesktop.org/drm-intel into d
1d4a9c1 PM / sleep: add configurable delay for pm_test
0787824 drm/i915: Ensure crtc_state backpointer is always initialized
83d6573 drm/i915: Use enabled value from crtc_state rather than crtc (v2)
009f33e Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-nex
d79d210 net: dsa: Introduce dsa_is_port_initialized
bb66be1 Merge branch 'sf2_hwbridge'
12f460f net: dsa: bcm_sf2: add HW bridging support
(...略...)
コミットが前後無関係に入り乱れて何がどうなって
るのかわからない
実例
(...略...)
fd25cdd ARM: shmobile: lager: Add DU HDMI output support
3f47da0 rcu_tree: Avoid touching rnp->completed when a new GP is started
ee376db rcu: Consolidate rcu_synchronize and wakeme_after_rcu()
5d8a421 power_supply core: support use of devres to register/unregister a power supply.
329414c Merge tag 'topic/drm-misc-2015-02-25' of git://anongit.freedesktop.org/drm-intel into d
1d4a9c1 PM / sleep: add configurable delay for pm_test
0787824 drm/i915: Ensure crtc_state backpointer is always initialized
83d6573 drm/i915: Use enabled value from crtc_state rather than crtc (v2)
009f33e Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-nex
d79d210 net: dsa: Introduce dsa_is_port_initialized
bb66be1 Merge branch 'sf2_hwbridge'
12f460f net: dsa: bcm_sf2: add HW bridging support
(...略...)
たとえばこのコミット , v4.1-rc1の50代
前の親でマージされたブランチの 38
代前の親にマージされたブランチの 8
代前のコミットです。
% git describe --contains fd25cdd
v4.1-rc1~50^2~38^2~8
コミットが前後無関係に入り乱れて何がどうなって
るのかわからない
実例
(...略...)
fd25cdd ARM: shmobile: lager: Add DU HDMI output support
3f47da0 rcu_tree: Avoid touching rnp->completed when a new GP is started
ee376db rcu: Consolidate rcu_synchronize and wakeme_after_rcu()
5d8a421 power_supply core: support use of devres to register/unregister a power supply.
329414c Merge tag 'topic/drm-misc-2015-02-25' of git://anongit.freedesktop.org/drm-intel into d
1d4a9c1 PM / sleep: add configurable delay for pm_test
0787824 drm/i915: Ensure crtc_state backpointer is always initialized
83d6573 drm/i915: Use enabled value from crtc_state rather than crtc (v2)
009f33e Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-nex
d79d210 net: dsa: Introduce dsa_is_port_initialized
bb66be1 Merge branch 'sf2_hwbridge'
12f460f net: dsa: bcm_sf2: add HW bridging support
(...略...)
次に表示されてるコミットは , v4.1-rc1
の145代前の親でマージされたブラ
ンチの2代前の親にマージされたブラ
ンチにオクトパスマージされたブラン
チのうち,2番目のブランチ(3rdペア
レント)の10代前のコミットです(;´Д`)
% git describe --contains 3f47da0
v4.1-rc1~145^2~2^2^3~10
v4.0 から v4.1 までのコミット数は12,965コミット
・・・
これを一つ一つ見るのは無理ゲー
実例
% git log --oneline v4.0..v4.1 | wc -l
12965
%
ここでファーストペアレントだけ辿ると・・・
12,965→399 個(約30分の1)に減少
400個くらいなら読める・・・かもしれない
実例
% git log --oneline --first-parent v4.0..v4.1 | wc -l
399
%
ログはmasterへのマージコミットと小さいFixやリ
リース関係だけにサマライズされる
実例
% git log --oneline --first-parent --decorate v4.0..v4.1
b953c0d (tag: v4.1) Linux 4.1
d2228e4 Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
8f4ce07 Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
bb16140 Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/li
9a10758 Merge tag 'sound-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
e640a28 Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/lin
5ca62d6 revert "cpumask: don't perform while loop in cpumask_next_and()"
17fda38 Merge tag 'trace-fix-filter-4.1-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/r
32e0e38 Merge git://git.kernel.org/pub/scm/virt/kvm/kvm
6cea28d Kconfig: disable Media Controller for DVB
49fe9bc Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
66fc130 mm: shmem_zero_setup skip security check and lockdep conflict with XFS
0f57d86 (tag: v4.1-rc8) Linux 4.1-rc8
気になるマージがあったら・・・
実例
% git log --oneline --first-parent --decorate v4.0..v4.1
b953c0d (tag: v4.1) Linux 4.1
d2228e4 Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
8f4ce07 Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
bb16140 Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/li
9a10758 Merge tag 'sound-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
e640a28 Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/lin
5ca62d6 revert "cpumask: don't perform while loop in cpumask_next_and()"
17fda38 Merge tag 'trace-fix-filter-4.1-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/r
32e0e38 Merge git://git.kernel.org/pub/scm/virt/kvm/kvm
6cea28d Kconfig: disable Media Controller for DVB
49fe9bc Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
66fc130 mm: shmem_zero_setup skip security check and lockdep conflict with XFS
0f57d86 (tag: v4.1-rc8) Linux 4.1-rc8
マージコミットをたとえば M とすると,
M^..M のlogを見ればOK
実例
...
9a10758 Merge tag 'sound-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
...
% git log --oneline --decorate 9a10758^..9a10758
145c0e9 ALSA: hda - Fix unused label skip_i915
82d6d8a ALSA: hda - Fix noisy outputs on Dell XPS13 (2015 model)
0f252a3 ALSA: mips: let SND_SGI_O2 select SND_PCM
8b99aba ALSA: hda - Fix audio crackles on Dell Latitude E7x40
6ab42ff ALSA: hda - adding a DAC/pin preference map for a HP Envy TS machine
%
あるいは M^2 のlogでも可。こっちは M^ 側に既に
マージ済みのコミットも出力。
実例
...
9a10758 Merge tag 'sound-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
...
% git log --oneline --decorate 9a10758^2
145c0e9 ALSA: hda - Fix unused label skip_i915
82d6d8a ALSA: hda - Fix noisy outputs on Dell XPS13 (2015 model)
0f252a3 ALSA: mips: let SND_SGI_O2 select SND_PCM
8b99aba ALSA: hda - Fix audio crackles on Dell Latitude E7x40
6ab42ff ALSA: hda - adding a DAC/pin preference map for a HP Envy TS machine
535115b ALSA: hda - Abort the probe without i915 binding for HSW/BDW
a686ec4 ALSA: hda - Re-add the lost fake mute support
bf06848 ALSA: hda - Continue probing even if i915 binding fails
98a226e ALSA: hda - Don't actually write registers for caps overwrites
...
M^ にマージ済み
の分も出力
M^..M と M^2 の違いを図にするとこんな感じ
MとM^, M^2は右図のとおり
実例
...
9a10758 Merge tag 'sound-4.1' of git://git.kernel.org/pub/sc
...
% git log --oneline --decorate ...
9a10758
9a10758^
9a10758^2
M^..M と M^2 の違いを図にするとこんな感じ
M^..M とはこうで・・・
実例
...
9a10758 Merge tag 'sound-4.1' of git://git.kernel.org/pub/sc
...
% git log --oneline --decorate 9a10758^..9a10758
145c0e9 ALSA: hda - Fix unused label skip_i915
82d6d8a ALSA: hda - Fix noisy outputs on Dell XPS13 (2015 mo
0f252a3 ALSA: mips: let SND_SGI_O2 select SND_PCM
8b99aba ALSA: hda - Fix audio crackles on Dell Latitude E7x4
6ab42ff ALSA: hda - adding a DAC/pin preference map for a HP
%
9a10758
9a10758^
9a10758^2
9a10758^..9a10758
M^..M と M^2 の違いを図にするとこんな感じ
M^2 はこう。
実例
...
9a10758 Merge tag 'sound-4.1' of git://git.kernel.org/pub/sc
...
% git log --oneline --decorate 9a10758^2
145c0e9 ALSA: hda - Fix unused label skip_i915
82d6d8a ALSA: hda - Fix noisy outputs on Dell XPS13 (2015 mo
0f252a3 ALSA: mips: let SND_SGI_O2 select SND_PCM
8b99aba ALSA: hda - Fix audio crackles on Dell Latitude E7x4
6ab42ff ALSA: hda - adding a DAC/pin preference map for a HP
535115b ALSA: hda - Abort the probe without i915 binding for
a686ec4 ALSA: hda - Re-add the lost fake mute support
bf06848 ALSA: hda - Continue probing even if i915 binding fa
98a226e ALSA: hda - Don't actually write registers for caps
...
9a10758
9a10758^
9a10758^2
9a10758^..9a10758
9a10758^2
M^ にマー
ジ済み
マージコミット Mに対して M^2 が2ndペアレントを
指す一方, M^ は1stペアレントを指す。
補足:リビジョン範囲表記
9a10758
9a10758^
9a10758^2
つまり,任意のコミット C に対して
C^ は常に1stペアレントであり,
C^^, C^^^ のように指定すること
で1stペアレントを辿った相対指定
も可能。
9a10758^^
9a10758^^^
...
9a10758^2^
9a10758^2^^
9a10758^2^^^
9a10758^2^^^^
...
ただ,C^^^^^^^^^^ (^が10個)とかは誰も書きたく
ないので, C~10 という簡易表記が用意されてい
る。( C~n 表記の n ≧ 0)
補足:リビジョン範囲表記
9a10758~0
9a10758~1
9a10758^2
9a10758~2
9a10758~3
...
9a10758^2~1
9a10758^2~2
9a10758^2~3
9a10758^2~4
9a10758^2~5
9a10758^2~6
...
1stペアレントを意識することに慣れると,
こういう閲覧方法もササッと書けるようになる
応用
% i=@; while :
do
git log --color=always --oneline --decorate --stat ${i}^..${i} || break
echo
i=$(git rev-parse ${i}^)
done |less
意味は「1stペアレント毎にマージしたブランチの
stat(変更file,行数)一覧を出力しろ」
echo で空行の区切りを
入れてあるので /^$ で
(lessの)サーチをすれば
1stペアレント毎の移動
はn, pで可能。細かい
移動はj, kで。
もちろんもっと良い方法
があるかも。
例えば log --topo-order --show-linear-break とか
応用
% i=@; while :; do git log ... ; done | less
b953c0d (HEAD, tag: v4.1) Linux 4.1
Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
d2228e4 Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
524630d iser-target: Fix possible use-after-free
drivers/infiniband/ulp/isert/ib_isert.c | 1 +
1 file changed, 1 insertion(+)
2f1b6b7 iser-target: release stale iser connections
drivers/infiniband/ulp/isert/ib_isert.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
9253e66 iser-target: Fix variable-length response error completion
drivers/infiniband/ulp/isert/ib_isert.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
8f4ce07 Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
fcee3c7 Merge tag 'drm-intel-fixes-2015-06-18' of git://anongit.freedesktop.org/drm-intel into drm-fixes
031fea4 Merge branch 'drm-fixes-4.1' of git://people.freedesktop.org/~deathsimple/linux into drm-fixes
7f017e5 drm/radeon: don't probe MST on hw we don't support it on
drivers/gpu/drm/radeon/radeon_dp_mst.c | 5 +++++
1 file changed, 5 insertions(+)
3bc980b drm/radeon: Add RADEON_INFO_VA_UNMAP_WORKING query
drivers/gpu/drm/radeon/radeon_kms.c | 3 +++
...
016a65a drm/i915: Always reset vma->ggtt_view.pages cache on unbinding
drivers/gpu/drm/i915/i915_gem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
bb16140 Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
909aa10 Merge branch 'ccf/atmel-fixes-for-4.1' of https://github.com/bbrezillon/linux-at91 into clk-fixes
28df9c2 clk: at91: fix h32mx prototype inclusion in pmc header
drivers/clk/at91/pmc.h | 2 +-
...
Gitあるある: 「blame (or bisect or …) で原因ぽい
コミット a35f960 は見つけたけど,これはどういう
経緯で作られたんだっけ?」
応用その2
% git describe --contains --all a35f960
master~3^2~3
% git log --oneline --decoratemaster~3^..master~3
bb21a16 Merge branch 'feature2'
c505c6a Add a dependable feature: apAVpr
84d4d21 Add a fabulous feature: tmv1gt
e78b30b Add a fabulous feature: VoWbeM
a35f960 Add a dependable feature: XTf4SR
067def6 Add a effective feature: STBJ3I
%
describeが複雑な形
になることもあるけ
ど,再帰的に把握して
いけばOK
「ファーストペアレントを辿ろう」
おわり
使い捨て統合ブランチを使おう
モチベーション
こういう人向けのはなし:
「やっべ,今masterにpushしたコミットに恥ずかし
いtypoがあったわー・・・
まだ誰もfetchしてないだろうし,push -fしてやれ」
masterへのpush -fはダメ・・・でも
たしかに master を push -f したくなることはある。
それはなぜ?
→ 視点や環境が変わると間違いに気づきやす
い。ローカルブランチからpushすると,やはり間違
いに気づくことがある。
心当たりはないですか?
● masterへのpush -fをたまにしてしまう
● masterへのマージが怖い
○ 個別のトピック作業時,まだマージもしてないのにマージ
後に正しく動くかが心配で,チェックに過剰に時間をかけ
てしまう
○ ローカルのmasterにマージしたあと、pushする前の
チェックに過剰に時間をかけてしまう
● masterが単純ミスのfixでいっぱい
仮想的にmasterをpush -f可能にする
将来のmasterとまったく同じ内容の統合ブランチ
を,別の名前でpushし,masterはそれを追いかけ
るようにすれば良い。
そもそもmasterにpushする内容を別名でpushして
はいけない,なんてルールはないので。
使い捨て統合ブランチを使おう
統合ブランチとは,トピックのマージ先になるブラン
チのこと。使い捨て統合ブランチは使い捨て前提
の統合ブランチ
● master は捨てられないので,使い捨て統合ブ
ランチには別の名前を用いる。ex:
○ pu (proposed-updates), next
○ devel, staging
● それ専用リポジトリを用意するのもあり
使い捨てる,とは?
使い捨て = 間違っていたら修正版を push -f し
て,それまでの内容を捨てる。
具体例
使い捨て統合ブランチ名は next とする。
ローカル origin
master
master
具体例
next を作成。
ローカル origin
master
master
% git branch next master
next
具体例
完成したトピックはこれまで master にマージして
きたけど,今後はまず next にマージする
ローカル origin
master
master
% git checkout next
% git merge nice-feature
% git merge another-feature
next
nice-feature
another-feature
具体例
next をpushして,適宜テストなどを実施。
ローカル origin
master
master
% git push origin next
next next
push
具体例
しばらく(一日とか)経過してnextの内容が良さそう
だとわかったら,master をそこに進める
ローカル origin
master
master
% git checkout master
% git merge --ff-only next # または git reset --hard next
next next
具体例
つづいて,新しいトピックが完成していれば,next
にマージする。
ローカル origin
master
master
% git checkout next
% git merge new-feature
% git merge another-new-feature
next
next
具体例
nextとmasterをpushする。
ローカル origin
master
% git push origin master next
next
master
next
push
具体例
以降,nextとmasterはある程度の距離を保ちつ
つ,進める。
ローカル origin
master
next
master
next
具体例
nextにマージ,pushした内容がダメだったとわかっ
た時はどうするのか?
具体例
例としてnextをpushした直後,その先端でマージし
たブランチに間違いを見つけたとする。
この場合・・・
ローカル origin
master
master
next next
具体例
まず間違いのあるブランチを修正し,fixupなどして
整形した正しいブランチを用意する。
ローカル origin
master
master
next next
具体例
次にnextを問題ない場所までresetする。ここでは
next^がそう。もちろんmasterが限界点。
ローカル origin
master
master
next
next
% git checkout next
% git reset --hard HEAD^
具体例
これにより間違いはローカルでは見えなくなる。
ローカル origin
master
master
next
next
% git checkout next
% git reset --hard HEAD^
具体例
nextに修正したブランチをマージする。
ローカル origin
master
master
next next
% git merge another-feature-v2
具体例
他に完成したトピックや、resetによって外れた問題
ないトピックがあればマージしてOK。
ローカル origin
master
master
next
next
% git merge new-feature
% git merge another-new-feature
具体例
masterを進められる分があれば進めてもOK
ローカル origin
master master
next
next
% git checkout master
% git merge --ff-only next~3
具体例
最後にpushして完了。このとき next は + 付きで
指定することで, forced push になる。
ローカル origin
master
next
% git push origin master +next
master
next
push
なにが嬉しいの?
● 開発者みんなに将来のmasterを見せられる
● 間違いがあってもmasterを汚さず直せる
● masterへのpushを自信を持ってできる
● 各種ワークフローに対して直交的
使い捨て統合ブランチ運用上の注意
使い捨て統合ブランチを運用するにあたって,注
意しなければならない点はたったひとつ
「使い捨て統合ブランチをトピックの分岐元にして
はならない」
さっきのnextのように push -f される前提なので,
そこから分岐してしまうとpush -fの影響を受ける
どうしても分岐元にしたい場合
例えばnextに入ってる新機能が必要,といった場
合。その原因となるトピック(新機能をnextに持ち
込んだトピック)を自分のトピックにマージする。あ
るいはその新規のトピックの上に自分のトピックを
作る。
この場合も依存先トピックがrebaseされたらちゃん
と追従する必要はある。
場合によって注意が必要なケース
「masterへのマージするときは先端へrebaseして
FFマージ必須」みたいな運用だと適用が難しいか
も。
間違いがあったとき,問題ないはずの他のトピック
に与える影響が大きいので。(過剰に手間がかか
る)
その他のコツなど
関連した運用のコツをいくつか紹介
(便宜上使い捨て統合ブランチ=nextとする)
● トピックを個別にマージする
● nextに置く期間は具体的に決める
● ライトウェイトタグの活用
● rerereの有効化
● GitHubでの運用
その他のコツなど
関連した運用のコツをいくつか紹介
(便宜上使い捨て統合ブランチ=nextとする)
● トピックを個別にマージする
● nextに置く期間は具体的に決める
● ライトウェイトタグの活用
● rerereの有効化
● GitHubでの運用
トピックを個別にマージ
さきほどの例では master から next 側をFFマージ
することで追いかけていたけど,「next にマージし
たトピックを個別に master にマージしていく」とい
う運用もアリ。
こうする利点は next に留めておく時間をトピックご
とに変えられること。
トピックを個別にマージ
例えば「こっちはもう少しレビューが必要だから,
あっちを先にmasterにマージしよう」といった運用
が可能になる。
nextにおく時間は無限でもよくて,「nextはステージ
ング環境専用の変更を加えたトピックをずっと保持
しておく」なんてこともできる。
トピックを個別にマージ
この場合,masterのマージコミットはnextには存在
しないので乖離がどんどん大きくなる(logなどで差
分表示が煩わしくなる)。
そのときはmasterをnextにマージすれば良い。実
際の変更としては master ∈ next なので,この
マージでコンフリクトは起こらない。あるいは,next
を一旦masterにresetして作り直しても良い。
その他のコツなど
関連した運用のコツをいくつか紹介
(便宜上使い捨て統合ブランチ=nextとする)
● トピックを個別にマージする
● nextに置く期間は具体的に決める
● ライトウェイトタグの活用
● rerereの有効化
● GitHubでの運用
nextに置く期間は具体的に決める
「安定するまで」のような抽象的な基準だとグダグ
ダになりやすい。
「24時間」とか「1週間」とか「2人からreviewでOKも
らうまで」といった,はっきりした基準のほうが良
い。
その他のコツなど
関連した運用のコツをいくつか紹介
(便宜上使い捨て統合ブランチ=nextとする)
● トピックを個別にマージする
● nextに置く期間は具体的に決める
● ライトウェイトタグの活用
● rerereの有効化
● GitHubでの運用
ライトウェイトタグの活用
使い捨て統合ブランチを導入すると,resetや
rebaseなど,歴史改変操作を(比較的)多用するこ
とになる。不安があったら git tagで(-aオプションの
ない)ライトウェイトタグを使おう。
何かあったらいつでもそのタグにreset --hard すれ
ばいいという安心感が生まれるし,実際戻るときも
reflogとにらめっこするより,はるかに効率が良い。
その他のコツなど
関連した運用のコツをいくつか紹介
(便宜上使い捨て統合ブランチ=nextとする)
● トピックを個別にマージする
● nextに置く期間は具体的に決める
● ライトウェイトタグの活用
● rerereの有効化
● GitHubでの運用
rerereの有効化
rebaseの機会が増えて多用したり,next, master
に同じブランチを複数回マージする機会が増える
と,同じコンフリクトを解消することが多くなる。
この場合, rerere (Reuse Recorded Resolution)
機能を有効化しておくのがオススメ。詳細は git-
rerere(1)参照。
その他のコツなど
関連した運用のコツをいくつか紹介
(便宜上使い捨て統合ブランチ=nextとする)
● トピックを個別にマージする
● nextに置く期間は具体的に決める
● ライトウェイトタグの活用
● rerereの有効化
● GitHubでの運用
GitHubでの運用
これといって気にすることはない。
GitHubプルリクエスト(PR)をnextにマージした時
点ではPRに何も影響を与えない(マージコミットに
PR番号を書いてあげるとPRからnextへのマージ
が見えるのでGood)。
その後masterを,そのマージまで進めた時点で当
該PRは自動的にクローズされる。
GitHubでの運用
もちろん,WebUIで完結させたければnextと
master両方にPRを出して,それぞれマージする,
という手段も取れるが,煩雑になる割にメリットが
あまりない。
PR先はmasterへのみとし,nextへのマージはPR
内のコメントで知らせる,くらいの軽い運用がよさ
げ。
GitHubでの運用
トピックに間違いがあって修正する場合は,色々試
した結果,新しいPRを出し直すのが良さそう。修正
版を別名(-v2とか)でpushし,新しいPRを出すとき
のコメントで
Supercede: #123
のように番号に言及しておけば,元PRから自動的
に新PRへ辿れる様になる(番号だけでOK)
使い捨て統合ブランチの実例
● Git本家: pu(ほぼ毎日reset), next(機能リリー
ス直後のみresetする)という2種類の使い捨て
統合ブランチを使用している
● Linux: linux-next という使い捨て専用リポジトリ
を使用している
「使い捨て統合ブランチを使おう」
おわり
まとめ
● ファーストペアレントを辿ろう
○ log --first-parent
○ ログをサマライズできる
○ トピック毎のログは M^..M または M^2 で見る
● 使い捨て統合ブランチを使おう
○ master が最初にpushする場所である必要はない
○ nextとか作ろう。こっちは間違えたらpush -f可能
○ FFマージで追いかけるか,トピック毎にマージ
○ nextに置く期間は具体的に決めよう。
Thank you
参考文献
● Git Documentation: https://github.com/gitster/git-htmldocs
● Git: https://github.com/git/git/
● Linux: https://github.com/torvalds/linux

Weitere ähnliche Inhalte

Was ist angesagt?

はじめてのGit forデザイナー&コーダー
はじめてのGit forデザイナー&コーダーはじめてのGit forデザイナー&コーダー
はじめてのGit forデザイナー&コーダーSaeko Yamamoto
 
BuildKitの概要と最近の機能
BuildKitの概要と最近の機能BuildKitの概要と最近の機能
BuildKitの概要と最近の機能Kohei Tokunaga
 
Gitのよく使うコマンド
Gitのよく使うコマンドGitのよく使うコマンド
Gitのよく使うコマンドYUKI Kaoru
 
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話Daichi Koike
 
図解gitworkflows(7)
図解gitworkflows(7)図解gitworkflows(7)
図解gitworkflows(7)ktateish
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪Takuto Wada
 
ノンプログラマでも今日から使える「Git」でバージョン管理
ノンプログラマでも今日から使える「Git」でバージョン管理ノンプログラマでも今日から使える「Git」でバージョン管理
ノンプログラマでも今日から使える「Git」でバージョン管理H2O Space. Co., Ltd.
 
コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」Masahito Zembutsu
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Akihiro Suda
 
やりなおせる Git 入門
やりなおせる Git 入門やりなおせる Git 入門
やりなおせる Git 入門Tomohiko Himura
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなKentaro Matsui
 
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来についてshinjiigarashi
 
Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編Masahito Zembutsu
 
乗っ取れコンテナ!!開発者から見たコンテナセキュリティの考え方(CloudNative Days Tokyo 2021 発表資料)
乗っ取れコンテナ!!開発者から見たコンテナセキュリティの考え方(CloudNative Days Tokyo 2021 発表資料)乗っ取れコンテナ!!開発者から見たコンテナセキュリティの考え方(CloudNative Days Tokyo 2021 発表資料)
乗っ取れコンテナ!!開発者から見たコンテナセキュリティの考え方(CloudNative Days Tokyo 2021 発表資料)NTT DATA Technology & Innovation
 
Kubernetes環境に対する性能試験(Kubernetes Novice Tokyo #2 発表資料)
Kubernetes環境に対する性能試験(Kubernetes Novice Tokyo #2 発表資料)Kubernetes環境に対する性能試験(Kubernetes Novice Tokyo #2 発表資料)
Kubernetes環境に対する性能試験(Kubernetes Novice Tokyo #2 発表資料)NTT DATA Technology & Innovation
 
Python 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそうPython 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそうRyuji Tsutsui
 
WebAssemblyのWeb以外のことぜんぶ話す
WebAssemblyのWeb以外のことぜんぶ話すWebAssemblyのWeb以外のことぜんぶ話す
WebAssemblyのWeb以外のことぜんぶ話すTakaya Saeki
 
日本語テストメソッドについて
日本語テストメソッドについて日本語テストメソッドについて
日本語テストメソッドについてkumake
 
Prometheus at Preferred Networks
Prometheus at Preferred NetworksPrometheus at Preferred Networks
Prometheus at Preferred NetworksPreferred Networks
 

Was ist angesagt? (20)

はじめてのGit forデザイナー&コーダー
はじめてのGit forデザイナー&コーダーはじめてのGit forデザイナー&コーダー
はじめてのGit forデザイナー&コーダー
 
BuildKitの概要と最近の機能
BuildKitの概要と最近の機能BuildKitの概要と最近の機能
BuildKitの概要と最近の機能
 
Gitのよく使うコマンド
Gitのよく使うコマンドGitのよく使うコマンド
Gitのよく使うコマンド
 
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
 
図解gitworkflows(7)
図解gitworkflows(7)図解gitworkflows(7)
図解gitworkflows(7)
 
例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
ノンプログラマでも今日から使える「Git」でバージョン管理
ノンプログラマでも今日から使える「Git」でバージョン管理ノンプログラマでも今日から使える「Git」でバージョン管理
ノンプログラマでも今日から使える「Git」でバージョン管理
 
コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
 
やりなおせる Git 入門
やりなおせる Git 入門やりなおせる Git 入門
やりなおせる Git 入門
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるな
 
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
 
Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編
 
乗っ取れコンテナ!!開発者から見たコンテナセキュリティの考え方(CloudNative Days Tokyo 2021 発表資料)
乗っ取れコンテナ!!開発者から見たコンテナセキュリティの考え方(CloudNative Days Tokyo 2021 発表資料)乗っ取れコンテナ!!開発者から見たコンテナセキュリティの考え方(CloudNative Days Tokyo 2021 発表資料)
乗っ取れコンテナ!!開発者から見たコンテナセキュリティの考え方(CloudNative Days Tokyo 2021 発表資料)
 
Kubernetes環境に対する性能試験(Kubernetes Novice Tokyo #2 発表資料)
Kubernetes環境に対する性能試験(Kubernetes Novice Tokyo #2 発表資料)Kubernetes環境に対する性能試験(Kubernetes Novice Tokyo #2 発表資料)
Kubernetes環境に対する性能試験(Kubernetes Novice Tokyo #2 発表資料)
 
Python 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそうPython 3.9からの新定番zoneinfoを使いこなそう
Python 3.9からの新定番zoneinfoを使いこなそう
 
WebAssemblyのWeb以外のことぜんぶ話す
WebAssemblyのWeb以外のことぜんぶ話すWebAssemblyのWeb以外のことぜんぶ話す
WebAssemblyのWeb以外のことぜんぶ話す
 
Oss貢献超入門
Oss貢献超入門Oss貢献超入門
Oss貢献超入門
 
日本語テストメソッドについて
日本語テストメソッドについて日本語テストメソッドについて
日本語テストメソッドについて
 
Prometheus at Preferred Networks
Prometheus at Preferred NetworksPrometheus at Preferred Networks
Prometheus at Preferred Networks
 

Ähnlich wie Gitの便利ワザ

実践 Git - 低レベルに知る Git
実践 Git - 低レベルに知る Git実践 Git - 低レベルに知る Git
実践 Git - 低レベルに知る GitYouhei Nitta
 
20120516 第7回ウフィカ社内ハンズオン Git基礎
20120516 第7回ウフィカ社内ハンズオン Git基礎20120516 第7回ウフィカ社内ハンズオン Git基礎
20120516 第7回ウフィカ社内ハンズオン Git基礎Makoto Yamazaki
 
Git pyfes201207-presen
Git pyfes201207-presenGit pyfes201207-presen
Git pyfes201207-presenKouhei Maeda
 
20120324 git training
20120324 git training20120324 git training
20120324 git trainingTakeshi AKIMA
 
Gitを使ってみませんか
Gitを使ってみませんかGitを使ってみませんか
Gitを使ってみませんかAtsuhiro Takiguchi
 
Python for Data Analysis第1回勉強会(+git入門)
Python for Data Analysis第1回勉強会(+git入門)Python for Data Analysis第1回勉強会(+git入門)
Python for Data Analysis第1回勉強会(+git入門)Makoto Kawano
 
Gitを理解するためにおさえておきたい3つの図(工事中)
Gitを理解するためにおさえておきたい3つの図(工事中)Gitを理解するためにおさえておきたい3つの図(工事中)
Gitを理解するためにおさえておきたい3つの図(工事中)Teloo
 
Git勉強会 2016 Gitで卒論を管理しよう回
Git勉強会 2016 Gitで卒論を管理しよう回Git勉強会 2016 Gitで卒論を管理しよう回
Git勉強会 2016 Gitで卒論を管理しよう回kinme modoki
 
ソフトウェア工学2023 08 GitHub
ソフトウェア工学2023 08 GitHubソフトウェア工学2023 08 GitHub
ソフトウェア工学2023 08 GitHubToru Tamaki
 
Metahub for github
Metahub for githubMetahub for github
Metahub for githubSuguru Oho
 
ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!Yohei Fushii
 

Ähnlich wie Gitの便利ワザ (20)

実践 Git - 低レベルに知る Git
実践 Git - 低レベルに知る Git実践 Git - 低レベルに知る Git
実践 Git - 低レベルに知る Git
 
Git 勉強会
Git 勉強会Git 勉強会
Git 勉強会
 
20120516 第7回ウフィカ社内ハンズオン Git基礎
20120516 第7回ウフィカ社内ハンズオン Git基礎20120516 第7回ウフィカ社内ハンズオン Git基礎
20120516 第7回ウフィカ社内ハンズオン Git基礎
 
Get along with Git
Get along with GitGet along with Git
Get along with Git
 
Git pyfes201207-presen
Git pyfes201207-presenGit pyfes201207-presen
Git pyfes201207-presen
 
20120324 git training
20120324 git training20120324 git training
20120324 git training
 
Gitを使ってみませんか
Gitを使ってみませんかGitを使ってみませんか
Gitを使ってみませんか
 
Python for Data Analysis第1回勉強会(+git入門)
Python for Data Analysis第1回勉強会(+git入門)Python for Data Analysis第1回勉強会(+git入門)
Python for Data Analysis第1回勉強会(+git入門)
 
Git overview (v 0.96)
Git overview (v 0.96)Git overview (v 0.96)
Git overview (v 0.96)
 
Tsume git
Tsume gitTsume git
Tsume git
 
Git
GitGit
Git
 
Git勉強会
Git勉強会Git勉強会
Git勉強会
 
Gitを理解するためにおさえておきたい3つの図(工事中)
Gitを理解するためにおさえておきたい3つの図(工事中)Gitを理解するためにおさえておきたい3つの図(工事中)
Gitを理解するためにおさえておきたい3つの図(工事中)
 
Git (実践入門編)
Git (実践入門編)Git (実践入門編)
Git (実践入門編)
 
Git勉強会 2016 Gitで卒論を管理しよう回
Git勉強会 2016 Gitで卒論を管理しよう回Git勉強会 2016 Gitで卒論を管理しよう回
Git勉強会 2016 Gitで卒論を管理しよう回
 
Gitの紹介
Gitの紹介Gitの紹介
Gitの紹介
 
ソフトウェア工学2023 08 GitHub
ソフトウェア工学2023 08 GitHubソフトウェア工学2023 08 GitHub
ソフトウェア工学2023 08 GitHub
 
Metahub for github
Metahub for githubMetahub for github
Metahub for github
 
Git 仕組み 入門
Git 仕組み 入門Git 仕組み 入門
Git 仕組み 入門
 
ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!ホームディレクトリに埋もれた便利なコードをさがせ!
ホームディレクトリに埋もれた便利なコードをさがせ!
 

Gitの便利ワザ