たばりばりスタイル

Ruby経験をもとにGo案件に参画した方法と感想

僕は今年の 1 月から Go を使う案件に参画しています。

それまでは 2 年ほど Ruby on Rails を使った開発に携わっていましたが、去年あたりから静的型付け言語を経験したいと思い、Go をメインで扱う案件に参画することに決めました。

Go を選んだ理由は、他静的型付け言語に比べて下記の点で良さそうだと思ったためです。

  • 流行っている *1
  • Java/ScalaC# などの他言語と比べ、覚えることが少なそう
  • フリーランス案件で Go の案件は高単価が多い *2

Ruby の経験

SIer 時代はスクリプト作成や Chef/Itamae などの DSL で簡易的に使うレベル感で 1 年半ほど。Web 系に転職してからは、Ruby on Rails を使った Web サービスの開発を 2 年ほど経験しています。

Go 案件に参画した方法

「Go 未経験でも他サーバーサイド言語の経験・理解があれば歓迎する」という案件を中心に商談を行いました。

数年前より Go 経験 x 年以上 ~ みたいな求人も増えてきた感じがしますが、他言語の経験者を歓迎する求人も探せばまだ見受けられます。まだ流行り始めてから浅いため、今がチャンスかもしれません。数年後は厳しくなるかもと予想しています。

他言語から移る場合は、商談ではなぜ Go をやりたいかを聞かれることが多いと思うので、回答は考えておいた方がいいと思います。

僕の回答例は、下記のような感じです。

  • 静的型付け言語を業務で使ってみたいと考えた
    • コードを読む際に、型が見える方が読みやすいから
    • コードを書く際に、意図しない値を渡さないようにチェックできるから
  • キャッチアップが好きで、新しくて流行りな Go を業務で覚えたいと考えた
  • Go の開発ではクリーンアーキテクチャが採用されることが多い印象なのでその辺の知見にも興味があった

また、商談では、新規開発やスクラム開発、自動テストコード作成、インフラやフロントエンドなどの経験など、どの言語でも共通して使える経験があればアピールしておいた方がいいと思います。

Ruby on Rails と Go の開発を比べて

僕はいまでも Ruby / Rails を使った開発が好きです。コーディング試験があれば Ruby を使うと思いますし、正直 ActiveRecordRSpec がないサーバサイド開発にはやりにくさも感じてしまいます。

ただ Go にもすごく魅力を感じているので、しばらくは Go 案件で手に馴染ませたいと考えています。 もし今後 Ruby 案件に戻る選択をしたとしても、Go での経験が活きることもあるだろうし、もう少し Go を触る環境にいるつもりです。

開発面で比較すると、Rails を使った開発は用意された様々な便利 API を覚えて、効率よく使うことが求められる感じがします。一方 Go での開発は必要最低限の薄い Web フレームワークを使うことが多いため、必要な処理を自分で実装することが求められる感じがします。

個人的には、天下の ActiveRecord から離れたことでいかに多くのことを Rails に助けられていたかを感じています。SQL なんてほぼほぼコードで書いた記憶もありませんでしたが、Go で有名な ORM (GORM) ではがっつり SQL を書きます。JOIN 句とかほぼ SQL を丸々書きます。まだ慣れません。。

Rails のテスト環境や RSpec がないこともすごく寂しいです。これらは考慮する点を減らして、テストコードを書く時間に集中できる、凄く良い環境を用意してくれていたんだなと感じました。

ただ、Go での開発では interface(抽象)や goroutine、クリーンアーキテクチャなどこれまで経験してこなかった技術を学べるので、この辺は刺激があって楽しいです。Go と仲良くなれるまでは頑張ります!

まとめ

Ruby 経験者が Go 案件に参画するには、他言語経験者を歓迎する Go 案件にコンタクト取ってみるのが良いと思います。

また、Rails と Go の開発を比較すると、求められる事が少し違う感じがしました。これは他の人の意見も聞いてみたい…。

以上です。

*1:有名なメガベンチャーを始め、多くの企業で採用されてる

*2:以前利用していたエージェントから聞いた

「トラブル知らずのシステム設計エラー制御・排他制御編」の排他制御編を読んだ

ここ最近、参画先でバッチ作成タスクにアサインされました。ここで作成するバッチはサービス稼働中に実行する必要があり、データの整合性を考慮する必要がありました。
このタスクを通して、データの整合性を考慮する際の知識が不足していると感じたため、「トラブル知らずのシステム設計エラー制御・排他制御編」とういう本を買って読んでみました。こちらエラー制御・排他制御編でふたつのテーマがあるのですが、今回は排他制御編のみ読んでいます。

感想

実際にありそうな様々な事例に対して、新人エンジニアが立ち向かうストーリー方式で、図をガンガン使って排他制御の設計について解説してくれます。

排他制御って誰から習うの、どうやって学習できるの?って思ってる方には入門として良い書籍だと思いました。

特に後半のオンライン処理とバッチ処理での考慮点などは、今回アサインされたタスクの考慮点とすごく近くて参考にしました。

雑なメモ

排他制御とは、共有資源に対して複数トランザクションから操作がある場合、同時アクセスによって起こる不整合を防ぐため、あるトランザクションがアクセスしている場合、他トランザクションからはアクセスできないように、並列に処理させる制御のこと

楽観ロック
  • 他者による更新はめったに起きない前提のロック
  • 業務トランザクション終了時(更新時)にロックを検知させる
  • SELECT FOR UPDATE を使い、ロックキーを比較、問題なれば UPDATE。別トランザクションは UPDATE 完了まで Wait になるので、上書きし合うことはない
  • 同一業務を複数人で実施しない、更新の競合発生してもやり直しが容易な場合におすすめ

ロックキー: データ更新されたか否かを判断するために利用する情報。よく利用されるのは、バージョン、タイムスタンプ、全列データの比較。
ここではバージョンをおすすめ。特徴は確実性が高い、新たなカラムが必要、バージョン更新を忘れないようにしなければいけない

悲観ロック
  • 他者による更新が頻繁に起きうる前提
  • 業務トランザクション開始時(取得時)にロックを検知させる
  • SELECT FOR UPDATE でロック状態を確認し、非ロック状態なら自身の情報でロック状態に変更。業務トランザクションを行う。ロック状態なら排他エラー。別トランザクションはロック状態 UPDATE 完了まで Wait になるので、上書きし合うことはない
  • 同一業務を複数人で実施する、更新の競合発生するとやり直しが難しい場合におすすめ

最後

データの整合性について考える際には、再度読み直したくなる本でした。買ってすごく満足です。

確定申告完了!フリーランスエンジニア1年生を雑に振り返る

2020/04 からフリーランスエンジニアとして働き始め、約 1 年が経過したので振り返ってみたいと思います。

ここでのフリーランスエンジニアとは

企業には正社員として所属せず、個人事業主として企業と準委任契約を結び、エンジニアとしての時間給で働くエンジニアを指しています。
基本はリモート中心でオフィスへの出勤はしないものの、営業時間に合わせた稼働時間に縛れるので、働き方は正社員とほとんど変わりません。

この 1 年どうやって仕事を取っていたか

下記の 2 つの方法で仕事を取っていました。

エンジニアの人手は不足しているとよく言われていますが、フリーランスも同じような状況です。
参画した現場では準委任契約で良いから参画してくれそうなエンジニアを知らないか?と聞かれることは少なくありません。 ※ ただ個人的には、スクール等の影響もあって未経験エンジニアが大量に業界に流れて来ているのを感じるため、数年後に供給が追いつくのではと考えています。

確定申告完了!確定申告の感想

独立前はこれが存在するだけで独立しない理由になるくらい面倒なものだと思ってました。ただ終えてみると、意外にあっさりしてました。 Freee を使えばググりながらイケます。もし事前に帳簿付けが終わっていれば数時間程度では納税まで完了できそうです。

独立前に事業用クレカ、口座を作っていたのは凄くよかったと思います。生活用クレカや口座まとめていると明細の振り分けに時間がかかりそう...

e-taxマイナンバーカードを利用するので、ぎりぎりで焦りたくない人は先に作っておいた方が良いと思いました。

フリーランスに向いていると思う人の特徴

1 年やってみて、フリーランスに向いているなと思った人の特徴です。

経理作業をしっかりできる人

正社員で勤めていた頃と比べ、確定申告や納税、契約関連書類の送付、など、独立後は期限がある作業がいくつか発生してきます。困った時はとりあえず経理部に相談すれば OK だった正社員時代とは違い、自分でしっかりと経理作業ができる人でないと辛いかもしれません。技術が大好きで、技術だけに時間を費やしたいんだって人には向かないのかなと個人的には思いました。ある程度外注はできるとしても、最終的な責任は自分に来ると思いますので。。。

楽観的な人、または実力に自信のある人

フリーランス、特に準委任契約で参画する場合は決まった期間で稼働し、必要とされれば契約更新していく流れになると思います。僕のような悲観的なタイプだと、更新してもらえるか不安になったりすることがあります。

更新されるか不安=貢献度に自信がない だと思うので、ある程度実力がある方は感じない悩みかもしれません。

もし更新されない場合は、次の参画先を探す必要もあり、エネルギー使うので、更新月になると力が入ってしまいます。

※ ただ、これまでの現場でスキル面で切られたことは一度も無かったため、僕が気にしすぎているだけの話かもしれません。

力試ししたい人

必要なら契約・更新、不要ならお断り・終了、とわかりやすいのがフリーランスの良いところだと思います。正社員と違って、簡単に切ってもらえるのがフリーランスです。実力が伴っていなくて切られた方も知っていますし、案件がなかなか決まらない方が居ることもよく聞きました。

現状のスキルでどれだけ参画できる企業が存在するのか、どれくらい市場にマッチしたスキルを持っているのか、力試ししたい人にフリーランスの働き方は良い選択だと思いました。

今後やりたいこと

節税対策

確定申告や納税を経験してから、税金や優遇制度について考える時間が増えました。確定申告後の 1 か月は、技術のキャッチアップそっちのけで、ファイナンスの書籍をあさっていました。

その中で節税をしっかり行いたいと思い、今後のためにマイクロ法人の設立を考えています。 事業税や消費税またその免除条件、厚生年金や退職金制度などメリット・デメリットをある程度理解できたタイミングで進めようと思っています。

フリーランスの繋がりを増やす

エンジニアとして働いていると、良い人いない?と聞かれることが多いと思います。その際に紹介できる知人、または逆に僕を紹介してくれる知人を増やしたいなと思っています。 フリーランスを続ける上で、僕がもっとも恐れているのは加齢やスキルの陳腐化で、参画先がなくなることです。そこをカバーするのに、繋がりを利用できたら良いなと思っています。 なので参画した企業にいるフリーランスの方とはチャンスを見つけて連絡先を交換するようにしています。

まとめ

フリーランスエンジニア 1 年生が終わるので、雑に振り返ってみました。まだ 1 年しか経っていないので今後考えは変わっていきそうです。

フリーランスエンジニア(準委任)の直営業による案件獲得方法について

僕は現在参画している企業と仲介を挟まず直接準委任契約を結んでいます。

エージェント経由の経験しかない方とこの話をすると、どうやって案件を獲得したか必ずと言っていいほど聞かれます。 特に難しいことはしていないのですが、エージェント経由だと勝手に案件降ってくるので、イメージ湧かない気持ちはわかります。

今回は僕がどのように案件を獲得したかをまとめたいと思います。

直契約の案件獲得方法

まず、直契約で参画する方法には大きく 2 パターンあると思っています。

  • 人脈を使ってリファラルで参画
  • 全く人脈のない企業に直営業して参画

今回、僕は後者の直営業の方で参画していますので、こちらについてまとめたいと思います。

※ 実はありがたいことに、前参画先で一緒に働いていた方からリファラルの話もあったのですが、直営業を経験したいという理由からお断りさせていただきました。*1

全く人脈のない企業に直営業

直営業とだけ聞くと、営業スキルが必要な感じもしますが、全くそんなことはありません。

やることは転職に近い感じです。普通にエンジニアの求人を出している企業にコンタクトをとるだけです。

僕は Wantedly しか使っていないのですが、Wantedly には業務委託の求人が存在します。そこに応募し、準委任契約で参画したいことを伝えます。

普通に商談 (面接) して、希望単価を伝え、問題がなければオファーを貰い、契約に進む形です。契約時の書類周りは、基本的に企業側が用意してくれると思いますが、商談の際に確認しておくと安心かもしれません。

今回(2021/01~)から参画する企業を探している時は、3 件応募して 2 件オファーを貰いました。

今回の営業・商談結果

案件 技術スタック 商談結果 補足
HR テック系企業 Go/AWS オファー獲得 -> 成約 業務委託慣れしており、開発組織が大きい、Go 歴が長い
ヘルステック系企業 Go/GCP オファー獲得 -> お断り 技術的にもメンバー的にも良さそうな環境だが、将来的には正社員入社を望まれたため
ファッションテック系企業 Go/AWS オファー貰えず 少数精鋭な感じで良かったがオファー貰えず。採用枠は 1 名だが複数候補がいたよう

単価は隠していませんが、タダで公開だと勿体無いので省略。聞きたい人は直接聞いて貰えれば教えます。

直接契約だとマージンが発生しない分、貰える額が多くなると思うので、興味がある方はぜひ。

以上です。

*1:僕はキャリアも浅く、文系出身ということもあり、エンジニアの知り合いが少ないです。そのため、今後リファラルだけで食いつなぐことは厳しいと思っており、早いうちに直営業を経験したいと思っていました。

GORMで値オブジェクトチックな構造体を埋め込む

GORM には embedded というタグが用意されており、値オブジェクト(Value Object)チックな構造体を他の構造体に簡単に埋め込むことができそうなので、メモ。

gorm.io

値オブジェクト

値オブジェクトとは、住所情報のように、不変かつ交換可能なオブジェクトです。 "港区 六本木 1-1-x" という同じ値オブジェクトが 2 つ存在する場合、その 2 つは同等である必要があります。

今回は住所情報を持つ値オブジェクトチックな構造体を表現する Address Struct を用意し、他の構造体に埋め込む実装を行います。

"チック" と表現しているのは、今回の実装では値の再代入を禁止する方法がないため、完全な値オブジェクトと言えないと判断したためです。

Address Struct

住所情報を持つ Address Struct を用意する。Address Struct は Street (住所の通り情報) と City (住所の都市情報) を内部で持ち、それらを組み合せて使うメソッドが用意しています。

package valueobject

type Address struct {
    Street string
    City   string
}

// IsClose は引数で受ける住所情報と自身の住所情報を比較し、住所が近いかを真偽値で返す.
func (a *Address) IsClose(address Address) bool {
    return a.City == address.City
}

// ToString は住所情報を結合した文字列を返す.
func (a *Address) ToString() string {
    return a.Street + " " +  a.City
}

Customer Struct

実際に値オブジェクトを埋め込ませる構造体として Customer Struct を用意します。Customer Struct は Address (住所情報) を持つ構造体です。

ここで GORM の embedded タグを使って Address Struct を埋め込みます。

embeddedPrefix はカラム名プレフィックスを省略するのに使います。

package entity

import (
    vo "github.com/tabakazu/value_object_sample/valueobject"
)

type Customer struct {
    ID      uint       `gorm:"primaryKey"`
    Name    string     `gorm:"column:name"`
    Address vo.Address `gorm:"embedded;embeddedPrefix:address_"`
}

// これは下記と同等になる
// type Customer struct {
//     ID      uint       `gorm:"primaryKey"`
//     Name    string     `gorm:"column:name"`
//     AddressStreet string
//     AddressCity   string
// }

DB と連携

実際に実装した Struct と DB のデータをマッピングしてみます。

事前に下記のテーブル、データを用意します。

CREATE TABLE `customers` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COMMENT '名前',
  `address_street` varchar(255) COMMENT '住所 通り',
  `address_city` varchar(255) COMMENT '住所 都市',
  `created_at` datetime(6) NOT NULL,
  `updated_at` datetime(6) NOT NULL,
  `deleted_at` datetime(6) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

INSERT INTO `customers` (name,address_street,address_city,created_at,updated_at))
VALUES ("John Snow", "Roppongi 1-1-x", "Minato-ku", NOW(), NOW());

実際に DB からデータを取得します。埋め込んだ値オブジェクトも正しくマッピングされており、定義した各メソッドを呼び出せます。

//  DB からデータ取得
var cus entity.Customer
db, _ := gorm.Open(mysql.Open(os.Getenv("MYSQL_URL")), &gorm.Config{})
db.First(&cus, "name = ?", "John Snow")

// Address で定義された City を取得
cus.Address.City //=> "Minato-ku"

// Address で実装した IsClose メソッド
otherAddress := valueobject.Address{City: "Minato-ku"}
cus.Address.IsClose(otherAddress) // => true
otherAddress := valueobject.Address{City: "Shibuya-ku"}
cus.Address.IsClose(otherAddress) // => false

// Address で実装した ToString メソッド
cus.Address.ToString() // Roppongi 1-1-1 Minato-ku

// Address の比較
otherAddress := vo.Address{City: "Minato-ku", Street: "Roppongi 1-1-x"}
cus.Address == otherAddress // true
otherAddress := vo.Address{City: "Minato-ku", Street: "Roppongi 1-1-y"}
cus.Address == otherAddress // false

データ挿入時も問題なく動作します。

cus := entity.Customer{
    Username: "Tyrion Lannister",
    Address: vo.Address{
        City:   "Minato-ku",
        Street: "Roppongi 1-1-x",
    },
}

db, _ := gorm.Open(mysql.Open(os.Getenv("MYSQL_URL")), &gorm.Config{})
if err := db.Create(&cus).Error; err != nil {
    fmt.Println(err)
} else {
    fmt.Println("Success")
}
// Success

良き値オブジェクトを発見した時は是非使いたい機能でした。

以上です。

2020年の振り返り。無事コロナ禍を生き残りました

コロナ禍を無事生き残れたので、2020 年の振り返りを書きます。

2020 年の振り返り

どんなことをやっていたのか

3 月 - ヘルステック系 Web ベンチャー退職

1 年ほど勤めていたヘルステック系 Web ベンチャーを退職しました。 新規開発プロジェクトで、設計からリリースまで経験できたのですごく良い経験になりました。

参画していたプロジェクトも落ち着き、組織編成などでチームリソースも充実していたので、タイミングが良さそうと判断し、退職しました。

4 月 - 独立開始 & ビジネス系試験サービスのシステム開発に業務委託として初参画、契約終了

開業届を提出し、エージェント経由で紹介してもらった企業に参画しました。技術がモダンで、サービスが面白かったので参画を決めました。

独立後初参画だったためやる気満々でしたが、参画から数日後に緊急事態宣言が発令され、予算縮小による業務委託の一斉終了で 1 ヶ月での契約終了となりました。幸先悪い感じでの独立になりました。

ただ期間は少なかったですが、SendGrid や CloudScheduler(GCP) などの未経験 SaaS を経験できたことや、1 つの新機能(詫び石的な機能)を設計から実装まで行えたので、楽しかったです。

次のタスクとして GraphQL を利用した API 実装にアサインされていたので、本音を言えばもう少し参画したかった...。

5 月 - ヘルステック系サービスのシステム開発に業務委託として参画

GW 明けからは、再度エージェント経由で紹介してもらい、別企業に参画しました。この参画先には、新規開発フェーズから参画し、各種主要機能、認証機能、決済機能、Slack 通知、GAS や AWS との連携部分の対応を行いました。

初めてスクラムマスターのいるチームで本格的な?スクラム開発が経験できて楽しい部分がある一方で、学習コストの問題で、SPA 化しない、TS は利用しない、状態管理に Redux を使わない、functional component ではなく class ベースで記述するなど、んーと思う部分もあり、サービスリリースで初期開発が落ち着いたタイミングの 12 月末で契約終了とさせていただきました。

11 月 - 次の参画先探しの営業を開始

独立後からエージェント経由で参画先を探していたのですが、単価交渉などでエージェントを仲介しなければいけない、案件探しと契約書周りの調整以外でエージェントを利用するメリットを感じない、などの理由から個人で営業する形を開始しました。

これまでのキャリアではサーバサイド開発で Rails しか使ったことしかなく、動的型付け言語 + 高機能フレームワークの開発経験しかないことがコンプレックスだったため、静的型付け言語 + 薄いフレームワークで開発できる Go の案件を中心に探しました。

12 月 - エージェント経由の参画終了、次の参画先決定

11 月から営業を開始、3 件営業して 2 つのオファーをもらうことができました。 どちらも Go でサーバサイド開発を行う案件です。どちらも魅力的な参画先でしたが、業務委託として参画する上で働きやすそうな環境かどうかを基準に選びました。

これまで Go 言語の業務経験はありませんでしたが、サーバサイドの開発経験、TDD やスクラム開発の経験、クラウド連携の経験など、比較的モダン寄りな技術スタックがあれば、話は聞いてもらえる感じでした。

単価については、これまでの単価にエージェントのマージン分 (推定) を足した金額で交渉。問題なく契約できました。

エージェント経由だと発生しない書類のやり取りなどで時間が取られましたが、色々勉強になりました。

まとめ

意気揚々と独立して、その 1 ヶ月後にコロナにぶつかり怪しいところもありましたが、しっかり生き残ることができ、自信につながりました。 来年からは Rails から離れ、未経験な言語にチャレンジすることになりますが、しっかりキャッチアップし、参画先に貢献できるように頑張りたいと思います。

だいたいこんな感じの 2020 年でした!こんな僕でも 2020 年を乗り越えれました。 来年も 1 月から新しい環境にチャレンジしていく形なので、引き続き生き残れるように頑張ります。

個人的によく使うGitコマンドのユースケースごとの備忘録

普段使い PC 上だと history を参照してある程度必要な操作はできるのですが、新しい支給 PC を利用するシーンなどでは Git コマンドを忘れてググることが多かったので、備忘録として残しておきます。

ちなみに直近でよく使った Git コマンドは下記です。

$ history | grep '^git ' | awk '{ print $1, $2 }' | sort | uniq -c | sort -r | head
1619 git commit
 820 git add
 535 git checkout
 281 git diff
 219 git push
  81 git reset
  78 git log
  74 git clone
  72 git branch
  70 git status
  57 git remote
  25 git rebase
  19 git pull
  18 git cherry-pick
  17 git merge
  15 git show
  10 git config
   9 git stash
   5 git revert
   4 git secrets

git commit でよく使うケース

直前の commit にまとめたいケース

$ git add README.md
$ git commit --amend --no-edit

直前のコミットのメッセージを編集したいケース

$ git commit --amend

変更部分を表示してコミットしたいケース

$ git commit -v

git add でよく使うケース

特記事項なし

git checkout でよく使うケース

checkout は peco と組み合わせた alias を使って下記コマンドを使っています。かなり便利です。

alias gc='git branch | peco | xargs git checkout'

リモートのブランチに checkout したいケース

$ git pull
$ git checkout "target_remote_branch_name"

git diff でよく使うケース

別ブランチとの差分を確認したいケース

$ git diff "target_branch_name" --name-only # ファイル名のみ
$ git diff "target_branch_name" README.md # 特定ファイルの差分のみ

git push でよく使うケース

$ git push origin HEAD
$ git push origin HEAD -f # force

git reset でよく使うケース

各種取り消ししたいケース

$ git reset # add 取り消し
$ git reset HEAD^ # 直前のコミットを取り消し
$ git reset --hard # add 取り消し & 現在の変更内容を破棄

git log でよく使うケース

$ git log --oneline README.md | head # ログを 1 行表示

git clone でよく使うケース

特記事項なし

git branch でよく使うケース

不要ブランチを削除したいケース

$ git branch -D "target_branch_name"

git status でよく使うケース

特記事項なし

git remote でよく使うケース

既存リモート URL 一覧を表示したいケース

$ git remote -v

git rebase でよく使うケース

複数コミットをまとめたいケース

$ git rebase -i HEAD~3 
# $ git rebase --abort # conflict した場合に利用

git pull でよく使うケース

リモートで更新されたブランチを pull したいケース

<master> $ git checkout "develop" # 対象ブランチに checkout
<develop> $ git pull origin "develop" # ブランチ名を指定して pull

git cherry-pick でよく使うケース

普通に cherry-pick

<master> $ git checkout "target_branch"
<target_branch> $ git cherry-pick a1b2c3d4

git merge でよく使うケース

feature/123 ブランチに develop ブランチをマージしたいケース (feature/123 <- develop)

<master> $ git checkout feature/123
<feature/123> $ git merge develop

git show でよく使うケース

特記事項なし

git config でよく使うケース

user 設定したいケース

$ git config --global user.name tabakazu
$ git config --global user.email tabakazu@example.com

git stash でよく使うケース

変更を一時退避して、戻したいケース

$ git stash save # 変更を一時退避
$ git stash list # 退避した変更の一覧
$ git stash pop "stash@{0}" # 退避した変更の取り出し

git revert でよく使うケース

普通に revert

$ git revert a1b2c3d4

git secrets でよく使うケース

クラウド破産しないように git-secrets を使う - Qiita

その他

fork 先を追従したいケース

GitHubでFork/cloneしたリポジトリを本家リポジトリに追従する - Qiita

$ git remote add upstream https://github.com/rails/rails.git
$ git remote add upstream git@github.com:rails/rails.git
$ git checkout master
$ git fetch upstream
$ git merge upstream/master

コミット数ランキングを表示したいケース

git shortlog -s -n

以上です。