読者です 読者をやめる 読者になる 読者になる

へっぽこびんぼう野郎のnewbie日記

けろけーろ(´・ω・`)!

差分だけ保存しておいて、あとで差分だけ反映させたいというとき

導入

次のようなファイルが2つあるとする

TODOリスト(偽).txt

日記を書く
明日に備えてゆっくり寝る
起きる

TODOリスト(真).txt

日記を書く
エロ動画を見る
明日に備えてゆっくり寝る
起きる

このとき、

  • この(真)の方は人目のつくところに置いておきたくない
  • しかしなるべくサイズは小さくしたい
  • しかもしょっちゅう真の方のTODOリストは編集する

というとき、どうするべきだろうか

リストを別カテゴリにして管理すればいいだろうか?
いや、真の方は圧縮してわからないところに隠してしまえばいいだろうか?
でも編集するとき、同じことを2回も編集しなければいけないのではないだろうか?
Gitのcheckoutの逆とかが、もっと簡単にできればいいんじゃないだろうか?

diffコマンドとpatchコマンドという神

知っての通り、diffコマンドというのは、差分を表示してくれるすばらしく偉大なツールです
以下のように使うことができます

$ diff TODOリスト(真).txt TODOリスト(偽).txt
2d1
< エロ動画を見る

(左側のファイルに『エロ動画を見る』という文字があるんやでという意味)

中身が同じなら何も出力しません

$ diff TODOリスト(真).txt TODOリスト(真).txt

ちょっとここでdiffに-uオプションをつけてみましょう
するとこういうフォーマットで出力されます

$ diff -u TODOリスト(真).txt TODOリスト(偽).txt
--- TODOリスト(真).txt	2016-02-26 00:38:33.000000000 +0900
+++ TODOリスト(偽).txt	2016-02-26 00:34:40.000000000 +0900
@@ -1,4 +1,3 @@
 日記を書く
-エロ動画を見る
 明日に備えてゆっくり寝る
 起きる

なんと、これは$ git log -pなどと同じ出力方法のようです

$ git log -p
commit f03faacb0fd6cf7946cc71f31986c147d9023214
Author: 【ぼく】
Date:   Fri Feb 26 00:37:14 2016 +0900

    編集した

diff --git "a/TODO\343\203\252\343\202\271\343\203\210\357\274\210\347\234\237\357\274\211.txt" "b/TODO\343\203\252\343\202\271\343\203\210\357\274\210\347\234\237\357\274\211.txt"
index 802a999..5cf2c87 100644
--- "a/TODO\343\203\252\343\202\271\343\203\210\357\274\210\347\234\237\357\274\211.txt"
+++ "b/TODO\343\203\252\343\202\271\343\203\210\357\274\210\347\234\237\357\274\211.txt"
@@ -1,4 +1,3 @@
 日記を書く
-エロ動画を見る
 明日に備えてゆっくり寝る
 起きる

このへんが同じ

@@ -1,4 +1,3 @@
 日記を書く
-エロ動画を見る
 明日に備えてゆっくり寝る
 起きる

そしてpatchというコマンドは、
このdiffで作られた差分を「適応してくれる」という偉大なコマンドなのです

試しにやってみます
『差分を保存して、あとで差分を適応している』の図です。
すばらしいことに、消すことができました
f:id:haruharu1:20160226004544p:plain

当然ながらもどすこともできます
f:id:haruharu1:20160226004851p:plain

このようにすることで、
一度差分ファイルを作っておけば、
あとは自動的に「自分が見たいとき・編集したいときだけパッチをあてて、それ以外のときはパッチを隠しておく(クラウドとかに)」なんてことをして、一人マージすることができます

感想

これは、こんなちんけな使い方だけではなく、
たとえば

「このファイルは、チームでgitで管理してるけど、ローカル環境ではちょっと差し替えて、密かにこう使いたい」などというときとか
「この実装はいまは必要ないからソースからは消すけど、将来的に必要になったらここに差し込みたい」みたいなときとか、
「バージョン管理されてないファイルについて、修正のプルリクめいたものを送りたい」ときとか
「git checkoutするとファイルが全部元に戻ってしまうけど、そうではなくて、ファイルのこのへんの差分だけ戻したい」ときとか
「共有ファイルとして多人数が非同期的に編集できる、Gitめいたシステムを作りたい」ときとか
にいいかもしれないです

基本的にGitがほとんど一方向的なのに対して、patchは双方向的なので、やり直しとかがしやすそうです

ディレクトリとかも一気に変えれるので便利そうです