search
LoginSignup
2

More than 1 year has passed since last update.

Organization

うっかり創業者のコードを上書きしない技術

この記事は SmartHR Advent Calendar 2019 14日目の記事です。

はじめに

私は 3人目あるいは 4人目のエンジニアとして、 2016年2月に SmartHR に入社しました。
あれから約4年、今となっては順調に権限移譲の進んでいる SmartHR ですが、当時は正社員が 7人しかおらず、全社員が様々な仕事を行う小さな企業でした。
当然エンジニアである副社長の @kakipo はプロダクトコードを書いていますし、非エンジニアである @miyasho88 も SmartHR にコードを書いては PR を投げていました。

社長による PR
image.png

こういった、創業者がコードに込めた思いというのはとても重要であり、おいそれと上書きしてよいものではありません。
この記事では、入社から 4年弱の期間、私がいかにして創業者のコードを上書きしないで済んだのか、その方法をお伝えします。

うっかり上書きしないために

さて、では実際にどのようにしてコードの上書きを避けるのか説明します。その答えはいたって簡単で、 Git Hook にスクリプトを仕込むことで解決します。
commit する際に修正箇所の最終編集者を確認、創業者として指定したアカウント名が変更に含まれている場合はエラーを出して commit を中止する、という流れになります。
このスクリプトを実行するためには、創業者が commit に利用したアカウント名がわかる必要がありますので、それはなんとかして手に入れてください。

なお、本記事で扱うコードはほぼデフォルトの macOS Catalina 上でのみ動作を確認しておりますので、そのほかの環境では正常に動作しない可能性がありますのでご了承ください。

処理の流れ

スクリプト内で行われる処理の流れとしては以下のようになります。

  1. git hook の pre-commit でスクリプトが実行されます
  2. git diff から変更のあった行を取得します
  3. git blame を使って変更のあった行を誰が書いているのか確認します
  4. 指定したユーザ名が含まれる行を変更している場合にはメッセージを出力して git commit を中止します

コード

プロダクト直下から .git/hook/pre-commit に以下のコードを追記します

BOSS_NAMES=YOUR_BOSS_NAME # カンマ区切りで複数指定可能です
file_names=(`git diff --cached --name-only`)

for file in ${file_names[@]}; do
    git_diffs=(`git --no-pager diff --cached --no-ext-diff -U1000000 ${file} | $(cd $(dirname $0) && pwd)/diff-lines.sh | grep -E "^[^\"].*\:[0-9]+\:\-"`)

    for git_diff in ${git_diffs[@]}; do
        line=(`echo ${git_diff//:/ }`)
        origin=`git blame -L${line[1]},+1 HEAD^ ${file} | awk '{print $2}' | sed -e 's/^(\(.*\)/\1/'`

        if [[ ${BOSS_NAMES} == *${origin}* ]]; then
            echo "You will overwrite ${origin}'s code in *****:${line[1]}"
            is_boss_exist=true
        fi
    done
done

if [ "${is_boss_exist}" ]; then
    echo "Commit aborted."
    exit 1
fi

なお、ここでは簡単のために、 gitで変更ファイルの差分行番号を取得するには? - どこでも見れるメモ帳 で書かれているコードをお借りして行番号を取得しています

そのため、上記のブログで使われている diff-lines.sh.git/hook ディレクトリに保存し、 chmod +x .git/hook として実行権限を付与する必要があります

実際の動作

output.gif

ちゃんと abort されましたね :tada:
どこで誰のコードを消したり上書きしようとしているか一目瞭然です。便利。

最後に

今回はうっかり創業者のコードを上書きしないために Git Hook を使ってコミットを中断させました。
しかし、動画作成のためにいろいろと探してみたのですが、 社長のコードはほぼ残っておらず、結果的として 2015年に作られた 12番目の PullRequest をチェックアウトすることとなりました。 とても残念です
いつの間にか大量に書き換えていた事実に驚愕です。

記憶があれば、来年は おまえは今まで書き換えた創業者のコードをおぼえているのか? をお送りいたします。

明日じゃなくて来年です。みなさま良いお年を!

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2