rukurxの日記

自分の日々の作業や調べたことのメモ

GitでプッシュしたコミットのAuthorとCommitterを変更する

Gitの設定でglobalにuser.nameとuser.emailを定義していると、 新しくcloneしてきたリポジトリのコミットにglobalのものが使われてしまう。

プライベートでも業務でも同じアカウント使っていれば問題ないが、別々だとPush後に慌てることになる。

自分がいつも慌ててるなんて言ってないですからね...

AuthorとCommitterを置換するGitコマンド

$ git filter-branch -f --env-filter \
  "GIT_AUTHOR_NAME='<name>'; \
   GIT_AUTHOR_EMAIL='<email>'; \
   GIT_COMMITTER_NAME='<name>'; \
   GIT_COMMITTER_EMAIL='<email>';" \
  <変更対象のコミットの範囲>

変更対象が直近5コミット分の場合は HEAD~5..HEAD になる。 範囲を HEAD だけにした場合は全てのコミットが対象になるので注意。

直近2コミット分のAuthorとCommitterのnameとemailを変更する

まずは、変更前のGitログの状態を確認する。 AuthorとCommitterが見やすいようにオプションはfullを使う。日付も見たい場合は fuller にする。

$ git log --pretty=full
commit 1a5bt8907d771fe348i5bb72130cd8c106f79f01 (HEAD -> master)
Author: hoge <hoge@users.noreply.github.com>
Commit: hoge <hoge@users.noreply.github.com>

    README.md修正2

commit 1df03d52f42048f50a708e5cdd4c01b1r8c651f3
Author: hoge <hoge@users.noreply.github.com>
Commit: hoge <hoge@users.noreply.github.com>

    README.md修正1

commit b1773g0971805ab21241b6e34e5hb403bfaef24b
Author: hoge <hoge@users.noreply.github.com>
Commit: hoge <hoge@users.noreply.github.com>

    init

AuthorとCommitterを変更する

$ git filter-branch -f --env-filter \
  "GIT_AUTHOR_NAME='tanaka'; \
   GIT_AUTHOR_EMAIL='tanaka@example.com'; \
   GIT_COMMITTER_NAME='tanaka'; \
   GIT_COMMITTER_EMAIL='tanaka@example.com';" \
  HEAD~2..HEAD

Gitログを確認する

$ git log --pretty=full
commit 1a5bt8907d771fe348i5bb72130cd8c106f79f01 (HEAD -> master)
Author: tanaka <tanaka@example.com>
Commit: tanaka <tanaka@example.com>

    README.md修正2

commit 1df03d52f42048f50a708e5cdd4c01b1r8c651f3
Author: tanaka <tanaka@example.com>
Commit: tanaka <tanaka@example.com>

    README.md修正1

commit b1773g0971805ab21241b6e34e5hb403bfaef24b
Author: hoge <hoge@users.noreply.github.com>
Commit: hoge <hoge@users.noreply.github.com>

    init

AuthorとCommitが変更されていますね!

でも、これでは間に関係ないコミットが入ってる場合できないので、間違えてコミットしたAuthor/Committer名に該当したコミットだけを対象に変更するようにしたい。

条件に該当したコミットのAuthorとCommitterだけ置換するGitコマンド

Gitのコマンドの中ではシェルの条件分使えるのでそれを利用する。

$ git filter-branch --commit-filter '
        if [ "$GIT_COMMITTER_NAME" = "<target name>" ];
        then
                GIT_COMMITTER_NAME="<name>";
                GIT_AUTHOR_NAME="<name>";
                GIT_COMMITTER_EMAIL="<name@example.com>";
                GIT_AUTHOR_EMAIL="<name@example.com>";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi' <対象コミットの範囲>

直近2コミットの中に "tanaka" というcommitter名でコミットされたコミットログを変更する。

$ git filter-branch --commit-filter '
        if [ "$GIT_COMMITTER_NAME" = "tanaka" ];
        then
                GIT_COMMITTER_NAME="Taro Yamada";
                GIT_AUTHOR_NAME="Taro Yamada";
                GIT_COMMITTER_EMAIL="yamada@example.com";
                GIT_AUTHOR_EMAIL="yamada@example.com";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi' HEAD~2..HEAD

Gitログを確認する

$ git log --pretty=full
commit 1a5bt8907d771fe348i5bb72130cd8c106f79f01 (HEAD -> master)
Author: Taro Yamada <yamada@example.com>
Commit: Taro Yamada <yamada@example.com>

    README.md修正2

commit 1df03d52f42048f50a708e5cdd4c01b1r8c651f3
Author: Taro Yamada <yamada@example.com>
Commit: Taro Yamada <yamada@example.com>

    README.md修正1

commit b1773g0971805ab21241b6e34e5hb403bfaef24b
Author: hoge <hoge@users.noreply.github.com>
Commit: hoge <hoge@users.noreply.github.com>

    init

条件に一致するコミットのみ変更がされてますね! 個人的にはAuthorやCommiter名で引っ掛けて対象のコミットだけ変更するやり方の方が安心感あっていいなと思います。

参考

idesaku.hatenablog.com

Git - 歴史の書き換え

sohtaro.com

PHPのFakerを使ってテストデータを自動生成する

PHPユニットテストを書いていると、適当なテストデータが必要になる。 毎回テストとかHoge的なテストデータを使っていたので、ちゃんとしたテストデータを使いたかった。 PHPにはFakerというランダムにテストデータを生成してくれるライブラリがあるので早速使ってみた。

github.com

PHPのFaker自体はPerlData::FakerRuby Faker にインスパイアされたものらしい。 PHPでも使えるようにしてもらえて感謝。

$ mkdir faker-sample
$ cd faker-sample
  • FakerをComposer経由でインストールする
$ composer require fzaninotto/faker
$ php -a
Interactive shell

php > // Fakerのオートーロードをrequireする
php > require_once 'vendor/fzaninotto/faker/src/autoload.php';
php > // Faker\Generatorインスタンスを生成する
php > $faker = Faker\Factory::create();
php > echo $faker->name;
Dr. Zachery Ledner V
php > echo $faker->address;
860 Jaskolski Gateway Apt. 806
Rutherfordville, ID 44854-0067
php > echo $faker->text;
Nemo ipsa placeat aut et nostrum perferendis et. Neque dolor accusantium sint sit.
php >

デフォルトではロケールen_USになっているため、英語になる。 ただし、textは何故かラテン語...

php > require_once 'vendor/fzaninotto/faker/src/autoload.php';
php > $faker = Faker\Factory::create('ja_JP');
php > echo $faker->name;
伊藤 春香
php > echo $faker->address;
9584833  佐賀県西之園市東区吉本町佐藤2-4-6
php > echo $faker->text;
Nemo maxime suscipit ut. Enim veritatis enim libero quas necessitatibus id. Et ad aspernatur iusto. Accusamus ut dolores consequuntur.
php >

日本語にするとより自動生成されたテストデータがリアルなものに感じます。 それでもtextはまだラテン語...

ソースを読んでみると都道府県や名前情報を配列でもっている。

Fakerの都道府県定義
Fakerの都道府県定義

Fakerで自動生成できるデータは日本語では現在以下の6種類ある。 日本語形式でなくてもよければ他にも使える。

  • 住所
  • 企業
  • インターネット
  • 電話番号
  • テキスト

どんなものを自動生成してくれるかと、呼び出し方はここのソース読むとわかる。 直下の 各ロケール内のクラスが継承している親クラスと、使いたいロケール内にあるクラスのメソッドをプロパティとして呼び出すことで使うことができる。

  • 人(Person)の場合
php > // 共通メソッド(Person.php)
php > echo $faker->name;
藤本 晃
php > echo $faker->firstName;
学
php > echo $faker->firstNameMale;
修平
php > echo $faker->firstNameFemale;
幹
php > echo $faker->lastName;
近藤
php > echo $faker->title;
Dr.
php > echo $faker->titleMale;
Mr.
php > echo $faker->titleFemale;
Prof.
php > // ja_JPロケールで定義されているメソッド (ja_JP/Person.php)
php > echo $faker->kanaName;
ワタナベ マアヤ
php > echo $faker->firstKanaName;
リョウヘイ
php > echo $faker->firstKanaNameMale;
トモヤ
php > echo $faker->firstKanaNameFemale;
リカ
php > echo $faker->lastKanaName;

使えるテストデータの種類が多いのでPHPUnitでテストする際には必須級のライブラリです。インストールと使い方もとても簡単なのでガンガン使っていきたいと思います。既にかなりお世話になってるけど。

コマンドラインから使えるチートシートを試してみた

コマンドラインを使うことが多いけど、あまり頻繁に使わないコマンドやオプションはすぐに忘れてしまうので、気軽にコマンドラインから呼び出せるチートシートないかと思っていたら、忘れた頃に発見!

github.com

そのまんま cheat って名前だった…

Macにインストールするので、brew search で検索する。

$ brew search cheat # 検索 
==> Formulae
cheat

Homebrewでも管理されているので、brewコマンドでインストールする。 sqlite使ってる様で一緒にインストールされた。

$ brew install cheat # インストール

cheatコマンドを実行するとUsageが表示される。

$ cheat
Usage:
  cheat <cheatsheet>
  cheat -e <cheatsheet>
  cheat -s <keyword>
  cheat -l
  cheat -d
  cheat -v

基本的には cheat <cheatsheet> で確認したいチートシートを指定する。

$ cheat git

どんなコマンドのチートシートがあるか確認したい場合は -l オプションを使うと一覧が表示される。

$ cheat -l

Gitのrebaseなどの特定のオプションについて確認したい時は -s オプションを使うことで該当箇所だけみることができる。多分searchのsと思われる。

$ cheat -s rebase
git:
  # Interactive rebase for the last 7 commits
  git rebase -i @~7

hg:
  hg pull --rebase

自分専用の内容にしたい場合は -e オプションで編集できる。

$ cheat -e git

オプション -v はcheatコマンドのバージョンを出力する。

$ cheat -v
cheat 2.2.3

オプション -dチートシートの格納先を出力する。

$ cheat -d
/Users/hoge/.cheat
/usr/local/Cellar/cheat/2.2.3/libexec/lib/python2.7/site-packages/cheat/cheatsheets

環境変数を使うことで色々と変更できる。

github.com

これで毎回ブラウザに切り替えたりして、ググったりしなくていいので捗りそうです。一応ネットに繋がってなくても使えるのでその辺も便利かもしれないです。

Composer使ったのでメモ

Composerとは

Composerはライブラリの依存関係を管理してくれるツールです。 ライブラリAを使おうとしたら、内部的にライブラリBやCを使っていることがあります。ライブラリAを使うために自分でBやCをインストールしたりするのは手間がかかります。

getcomposer.org

Composerを使ってライブラリAをインストールすると、いい感じに依存しているライブラリBとCもインストールしてくれます。

# パッケージAをインストールすると、依存するパッケージB, Cもインストールしてくれる
$ composer require パッケージA

ただし、依存するライブラリBとCがcomposerに対応している必要があります。

Composerをインストールする

公式サイトのダウンロードページからダウンロードする。 getcomposer.org

Composerでプロジェクトを作成する

$ composer init

設定を色々と聞かれた後に composer.json ファイルが作成される。 composer.jsonにはライブラリの依存関係が記載されている。 Composer.jsonがあるディレクトリで以下コマンドを実行すると、依存しているライブラリをインストールしてくれます。

$ composer install

プロジェクトの作成はテンプレートを使うこともできる。

# laravelの場合
$ composer create-project --prefer-dist laravel/laravel PROJECT_NAME

パッケージをインストールする

$ composer require パッケージ名:タグ
例)
$ composer require package:dev-master

パッケージの情報はcomposer.jsonに記載され、インストールしたバージョン等の情報はcomposer.lockに記載される。 composer.lockファイルはComposerでライブラリをインストールする際に作成される。 composer.jsonに記載されている、インストールしたパッケージのバージョンなどの情報が保存されている。 composer.lockを共有することで、他の人があとでcomposerを使ってインストールすると同じバージョンのライブラリをインストールしてくれる。

パッケージを削除する

$ composer remove パッケージ名

composer.jsonとcomposer.lockからもパッケージ名が削除される。

パッケージを全て最新化する

$ composer update

パッケージを新しくしたい時に実行する。composer.lockの内容を無視して、composer.jsonにあるパッケージを最新の状態でインストールして、composer.lockも更新される。 composer.jsonに記載されているパッケージが全て最新になる。

特定のパッケージだけ最新化する

$ composer require パッケージ名

気軽にupdateするとcomposer.jsonに記載されている全てのパッケージが更新されてしまうので、パッケージ名を指定して更新する。 パッケージをインストールするときと同じ。

オートローダを作成・更新する

$ composer dump-autoload

autoload.phpが作成・更新される。

参考

qiita.com

PHP7で追加されたスペースシップ演算子(<=>)について

PHPのコードレビューをしていたら見慣れない演算子 <=> を発見!

なんやこれと思ったら、PHP7で追加された スペースシップ演算子(spaceship operator) という比較演算子でした。

スペースシップ演算子は左辺と右辺を比較した結果として、-1, 0, 1 のいずれかを返します。

  • 左辺より右辺が大きければ -1 を返す。
  • 左辺の右辺が同じなら 0 を返す。
  • 左辺の方が右辺より 1 を返す。

PHPインタラクティブモードで実際に返却される値を確認する。

$ php -a
Interactive shell

php > // 数値比較
php > echo 0 <=> 1;
-1
php > echo 1 <=> 1;
0
php > echo 1 <=> 0;
1
php > // trueとfalse比較(trueは1, falseは'')
php > echo false <=> true;
-1
php > echo true <=> true;
0
php > echo true <=> false;
1
php > // 文字列比較(アルファベット順)
php > echo 'a' <=> 'b';
-1
php > echo 'a' <=> 'a';
0
php > echo 'b' <=> 'a';
1

どうやらソートする際によく使われる様子。

  • 今までの書き方
<?php

  $numbers = [5, 1, 3, 2, 4];

  usort($numbers, function($a, $b) {
    if ($a < $b) {
      return -1;
    } elseif ($a == $b) {
      return 0;
    } else if ($a > $b) {
      return 1;
    }
  });

  print_r($numbers);
  • スペースシップ演算子を使った場合
<?php

  $numbers = [5, 1, 3, 2, 4];

  usort($numbers, function($a, $b) {
    return $a <=> $b;
  });

  print_r($numbers);

スペースシップ演算子自体はPerlRubyなどの他の言語にもあるみたいですね。他の言語もやらないと…

参考

stackoverflow.com qiita.com www.sitespiral.jp

PHPをコマンドライン上で対話式に実行する

PHPの対話シェル(REPL)を使うには -a オプションを指定する。

$ php -a
Interactive shell

php >

通常のPHPの実行したときと同様に、計算結果の出力やクラスを定義したりできるので、ちょっとした機能の確認に使うと便利そう。

$ php -a
Interactive shell

php > echo 1+1;
2
php > class Hoge {
php {   public function getClassName() {
php {      return __CLASS__;
php {   }
php { }
php > $hoge = new Hoge();
php > echo $hoge->getClassName();
Hoge
php > exit
$

なんだかんだで実際開発してる時には使わないかも...

参考

PHP: 対話シェル - Manual

MacでのSSH接続を管理する

サーバーにSSH接続するたびに毎回ホスト名や鍵情報を書くのが面倒なので、任意につけたホスト名だけでログインできるようにする。 ついでに踏み台サーバーを経由した多段SSHの設定もする。

通常のSSH

$ ssh root@example.com -i ~/.ssh/example.key -p 22

長い...

Host名を指定したSSH

  • .ssh/configファイルを作成して管理する
# .sshディレクトリがなければ作成して、パーミッションを変更する
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ touch ~/.ssh/config
  • 接続先のホスト情報をconfigファイルに記載する
$ vim ~/.ssh/config
# 接続先サーバー情報
Host example
 HostName example.com
 User root
 IdentityFile ~/.ssh/example.key
 Port 22
 TCPKeepAlive yes
 IdentitiesOnly yes

これでssh接続の際にHostに書いた名前を指定するだけでsshできる。

$ ssh example

踏み台サーバーを使った多段SSH

例としてAWSのEC2に踏み台サーバー(jump)経由でsshする。

$ vim ~/.ssh/config
Host jump
 Hostname 192.168.0.1
 User user_name
 IdentityFile ~/.ssh/id_rsa
Host web01
 Hostname 192.168.1.1
 port 22
 User ec2-user
 IdentityFile ~/.ssh/example.pem
 ProxyCommand ssh -CW %h:%p jump
  • 読み書き権限を付与する
$ chmod 600 .ssh/example.pem

※ 事前にexample.pemをローカルに落としてくる必要がある

参考

qiita.com

qiita.com