メインコンテンツまでスキップ

Git Cheat Sheet

· 約6分
Mikyan
白い柴犬

問題の背景

チームで開発する際、よくあるパターンとして、

  • developブランチから、featureブランチAを切って実装、PullRequestを作成し、レビュー待ち
  • その間に、featureブランチAにfeatureブランチBを切って、新しい機能を実装します
  • featureブランチAのレビューを経て承認され、スカッシュマージによってdevelopブランチへ統合され
  • この時、featureブランチBのコミットがfeatureブランチAの元のコミットに含まれてしまうことがあって、developブランチと多くのマージコンフリクトが発生してしまいました。

問題発生の原因

  • スカッシュマージによって個々のコミットがまとめられたため、ブランチBには依然としてブランチAの個々の変更が残っていること
  • その結果、developブランチに既に存在するスカッシュコミットとブランチBの変更が重複して適用され、コンフリクトが発生したこと

解決策:リベースによる解決

ブランチBをブランチA由来のコミットを取り除いて、developブランチ上のスカッシュコミットに合わせてリベースすることで、効率よく解決できます。

具体的には、以下の手順で行います:

git checkout feature/branch-b
git rebase --onto develop HASH_BASE feature/branch-b

このコマンドは、ブランチ B の中で HASH_BASE より後のコミットだけを、develop ブランチ上に再適用します。 HASH_BASEは、ブランチ A が develop から分岐した時点のコミットハッシュにすると、元ブランチ A のコミットがブランチ B に含まれなくなります。

リベース中にコンフリクトが発生した場合、各コンフリクト箇所で適切に修正し、 以下のコマンドでリベースを続行します。

git add <修正済みファイル>
git rebase --continue

リベースが正常に完了したら、ブランチ B の変更を develop ブランチへPRを作成してマージしましょう。

この方法により、履歴がクリーンになり、将来的なマージやデバッグ作業が大幅に楽になります。

Remote ブランチにコミットしました

問題の背景

リモートブランチをLocalにFetchせずに、チェックアウトし、

git checkout origin/branch-a

をすると、そのまま作業し、コミットしたら、プッシュできない。下記のエラーメッセージ表示されました:

error: src refspec feature/branch does not match any
error: failed to push some refs to 'github.com:organization/project.git'

問題発生の原因

Fetchが忘れて、RemoteブランチをCheckoutするとき、実際のHEADはそのブランチではなく、detached HEADの状態です。 すると、ブランチに所属せず、特定のコミットを指している状態です。

git checkout origin/main
# または
git checkout <コミットID>
HEAD → origin/main の最新コミットを直接指す(ローカルブランチではない)

ブランチは指していない
→ この状態でコミットすると、その履歴はどのブランチにも属しません。

そのまま作業して、コミットできるか、そのコミットはブランチ属していない、浮いた状態です。 git log, git reflogで確認できますが、後で消える可能性がある あくまで一時的な作業や、過去のコミットを試す時に使うモード

解決策

  1. ブランチからそのコミットハッシュをcherry-pickしたら解決
git log
# copy the コミット hash abc1234
git checkout branch
git cherry-pick abc1234
git push origin branch
  1. このコミットから新しいブランチを作成で解決
git branch feature/tmp abc1234

リベースの後で--force-with-leaseでプッシュ

git rebaseの後、--force でプッシュが必要でしょう。 このとき、--force-with-leaseでプッシュするとより安全にプッシュできます。

git push --force-with-lease

すべてのCommitを一つにする

GitHubで他の人が作ったボイラープレートをクローンして、自分のプロジェクトを始めることはよくあります。しかし、元のコミット履歴は不要なので、削除したほうがよいでしょう。 以下の手順でクリーンなリポジトリを作成できます:

方法1: 履歴のない新しいブランチを作成

# Navigate to your repository
cd your-repo

# Create a new orphan branch (no commit history)
git checkout --orphan clean-master

# Add all files
git add -A

# Create the first commit
git commit -m "Initial commit"

# Delete the old master branch
git branch -D master

# Rename the current branch to master
git branch -m master

# Force push to your remote repository
git push -f origin master

方法2: .gitフォルダを削除して再初期化

# Navigate to your repository
cd your-repo

# Remove the .git folder (this deletes all history)
rm -rf .git

# Initialize a new repository
git init

# Add all files
git add -A

# Create the first commit
git commit -m "Initial commit"

# Add your remote repository
git remote add origin https://github.com/yourusername/your-repo.git

# Push to your repository
git push -u origin master

google-analtyics-add-custom-properties

· 約1分
  • Setting deviceId as a user property via gtag('set', 'user_properties', {'deviceId': deviceId}); means it will be associated with all subsequent events, including automatic ones. This is generally the recommended way to handle persistent user-level identifiers.

The custom_map in the config call within ClientTrackingInitializer (window.gtag('config', GA_TRACKING_ID, {'custom_map': {'dimension1': 'deviceId'}})) is used to map an event parameter or user property named deviceId to a custom dimension (in this case, dimension1) in your GA4 reports. For this to effectively map a user property, the custom dimension in

GA4 should be user-scoped.

Why this setup should generally work for your goal:

When gtag('set', 'user_properties', {'deviceId': deviceId}) is called, any events fired after this (including automatic page_view events if this set happens before the config that triggers them, or subsequent page_view events on SPA navigations) will have this user property associated.

User properties are automatically sent with events to GA4.

意思決定の全てはROI

· 約2分
Mikyan
白い柴犬

複数人が関わっているプロジェクトのやり方、難易度はグッと上がるです。 なぜなら、人々のコミュニケーション、すり合わせ、タスク間の依存関係、を考えなければならないです。しかもこれらのプロジェクトのインパクトが高い、できれば大きな利益が出る、うまくできないと大きな損失が出る可能性があるのできちんと管理する必要があります。

チームでのプロジェクトの進め方は、個人プロジェクトの管理方法に加えて、以下三つの要点があります:

  • プロジェクトを分解をする
    • MECEで分解
    • 前後依頼を確定
  • 各タスクを関与する人を確定、評価するかどうかを確定
  • 各マイルストーンの確認時点を定める

プロジェクト管理についての理解1、一人プロジェクト

· 約5分
Mikyan
白い柴犬

これまでいくつかの会社で、さまざまなプロジェクトの管理やリードに関わってきました。
その中で得た知見を、将来の自分のためにも簡単にまとめておきたいと思います。

プロジェクトとは、「限られたリソースを使い、限られた期間で、特定の目的を達成する取り組み」です。
その目的を実現するためには、適切な管理が欠かせません。

プロジェクトの規模によって管理方法は大きく異なるため、私は以下の3つに分類できると考えています。

  • 一人プロジェクト
  • チームプロジェクト
  • 複数組織が関わるプロジェクト

今回はこの中でも、「一人プロジェクト」の管理についてまとめてみます。


一人プロジェクトとは?

プロジェクトの定義を広く捉えれば、さまざまな取り組みがプロジェクトとして扱えます。
たとえば、以下のようなものも一人プロジェクトに該当します。

  • 個人旅行の計画
  • ブログの運営
  • 上司に依頼された勉強会の企画

一人で進めるプロジェクトは、特に管理が軽視されがちです。
単なるタスクのように感覚的に進めてしまうことも多いでしょう。

しかし、「これはプロジェクトだ」と意識し、適切に管理することで、より楽しく、より良い結果を得ることができます。


一人プロジェクト管理で意識すべき3つのポイント

1. 目的を明確にする

  • 「なぜそれをやるのか?」を繰り返し問いかけ、問題を言語化します。
  • 曖昧なまま進めると、途中で迷子になったり、やり直しが発生したりします。

特に他人から頼まれたプロジェクトでは、目的が明確にされていないことが多いです。

例:勉強会の幹事を任された場合

  • チームのコミュニケーションを活性化するため?
  • AIなど最先端技術を学ぶ場として?
  • プレゼン能力を伸ばすため?
  • チームカルチャーを育てるため?

目的によって、トピック選定、参加メンバー、運営方針がすべて変わってきます。
だからこそ、最初に目的を明確にすることが最重要です。


2. マイルストーンに分解する

  • タスクが小さく見えても、実際は難しい部分や不確実な要素が隠れていることがあります。
  • あらかじめ全体像を把握し、マイルストーン(節目)に分解しておくことで、計画的に進めることができます。

また、マイルストーンは進捗の報告タイミングとしても活用できます。


3. 報連相(報告・連絡・相談)を怠らない

一人で進めるからこそ、「見える化」が重要です。
上司や依頼者に対して、今どこまで進んでいるか・どんな課題があるかを適切に共有しましょう。

これには以下のメリットがあります:

  • 認識違いがあっても、早い段階で軌道修正できる
  • 環境や要件の変化にも柔軟に対応できる
  • 自分の成果が評価されやすくなる

おわりに

一人で動くプロジェクトこそ、意識的に「プロジェクト」として扱うことで成果が変わってきます。

  • 目的の明確化
  • マイルストーンの設計
  • 可視化と報連相

この3つを意識すれば、小さな取り組みでも効果的に、そして気持ちよく進めることができるでしょう。

Redis

· 約1分
Mikyan
白い柴犬

一文でRedisの機能やユースケースをまとめてみる。

Redis とは

Redisは様々なデータ構造に対応したインメモリデータストアです。

具体的に言うと、下記のデータ構造を対応しています:

  • Strings (simple binary-safe blobs)
  • Lists (linked lists, with operations like LPUSH, LRANGE, etc.)
  • Hashes (maps/dictionaries of field→value pairs)
  • Sets (unordered collections of unique elements)
  • Sorted Sets (elements ordered by a score, i.e. your “sorted array”)
  • Bitmaps (compact bit arrays)
  • HyperLogLogs (probabilistic cardinality counters)
  • Streams (append-only log data structures)
  • Geospatial indexes (store and query latitude/longitude points)

データ構造の対応ではなくて、便利な操作機能も提供しており、普段のデータベースで実装しにくい機能を簡単に実装できます。

How to setup SFTP in EC2 allowing file upload

· 約2分
Mikyan
白い柴犬

SFTP use SSH protocal, allowing user to transfer files safely. It is a subsystem of SSH, so it runs in port 22.

The name contains FTP, however it is not implements FTP protocal

  • It achieves the same function with FTP
  • It is widely supported by FTP clients

When you want to transfer files with server, it might be a good choice.

How to setup a sftp user allowing it to upload files into specific folder

The following scripts helps setup a SFTP user in

Save it to .sh file, execute the following commands

chmod +x setup_sftp_user.sh
sudo ./setup_sftp_user.sh vendor

It will prompt you to set the password and configure the rest automatically.

#!/bin/bash

# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo "Please run as root or use sudo"
exit 1
fi

# Check if username is provided
if [ -z "$1" ]; then
echo "Usage: $0 <username>"
exit 1
fi

USER=$1

# Create user
useradd -m $USER
passwd $USER

# Setup SFTP directories
mkdir -p /var/sftp/$USER/uploads
chown root:root /var/sftp/$USER
chmod 755 /var/sftp/$USER

chown $USER:$USER /var/sftp/$USER/uploads
chmod 755 /var/sftp/$USER/uploads

# Backup sshd_config
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

# Add SSH config for user
cat <<EOL >> /etc/ssh/sshd_config

Match User $USER
ChrootDirectory /var/sftp/$USER
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
EOL

# Restart SSH daemon
systemctl restart sshd

# Confirm success
echo "SFTP user '$USER' has been set up successfully."

Best Practice

· 約1分
Mikyan
白い柴犬

To simplify & unify the system logic, the following convention are considered as best practice:

  • Store everything in UTC
  • Use UTC everywhere in backend
  • Use UTC, with ISO-8601 format in API layer
  • Frontend: Convert to user's local time

transformer

· 約20分
  1. 機械学習におけるTransformer(トランスフォーマー)

現在、最も注目されているのは、深層学習モデルの一種である「Transformer」です。これは、2017年にGoogleの研究者によって発表された画期的なモデルで、特に自然言語処理(NLP)の分野に大きな変革をもたらしました。

Transformerの主な特徴とすごい点:

Attention Mechanism(注意機構): これがTransformerの核となる技術です。従来のモデル(RNNやLSTMなど)は、文章を前から順番に処理していくため、長い文章になると前の情報を忘れやすいという問題がありました。しかし、Attention Mechanismは、入力された文章の中のどの単語とどの単語が関連しているかを計算し、「注目」することで、離れた単語間の関係性も効率的に捉えることができます。これにより、文脈をより深く理解し、より自然な言語処理が可能になりました。

並列処理の実現: 従来のRNNなどが逐次処理(単語を一つずつ処理)であったのに対し、TransformerはAttention Mechanismによって文章中の全ての単語を同時に処理する並列処理が可能です。これにより、大量のデータを高速に学習できるようになり、大規模なモデルの構築が可能になりました。

Encoder-Decoder構造: Transformerは、大きく「Encoder(エンコーダ)」と「Decoder(デコーダ)」の2つの部分で構成されています。

Encoder: 入力された文章(例えば、翻訳元の言語の文章)の重要な特徴を抽出し、その情報をベクトル表現に変換します。

Decoder: Encoderが抽出した特徴に基づいて、出力される文章(例えば、翻訳先の言語の文章)を生成します。

長期的な記憶能力: Attention Mechanismにより、長い文章でも文脈を失うことなく処理できるため、要約や文章生成など、長期的な依存関係を考慮する必要があるタスクで高い性能を発揮します。

汎用性の高さ: 元々は機械翻訳のために開発されましたが、その強力な能力から、ChatGPTやBard、Bingなどの**大規模言語モデル(LLM)**の基盤技術として広く採用されています。文章生成、要約、質問応答、感情分析など、多様な自然言語処理タスクで優れた性能を発揮します。また、画像生成や音声処理など、自然言語以外の分野にも応用されています。

「注意すべき単語」を選ぶ方法

人間が文章を読む際に、文脈に応じて重要な単語に自然と注目するような働きを、数学的にモデル化したものです。

具体的には、以下の3つのベクトルが重要な役割を果たします。

Query(クエリ): 今、注目している単語(例えば、ある単語を生成しようとしているとき、その単語に対応する情報)

Key(キー): 入力された文章中の、すべての単語(または単語の表現)

Value(バリュー): Keyに対応する情報(各単語が持つ意味的な内容)

Transformerでは、これらのベクトルを用いて、以下のような計算が行われます。

類似度の計算

まず、注目している単語のQueryベクトルと、入力文中の各単語のKeyベクトルとの「類似度」を計算します。これは一般的に、内積(ドット積)で行われます。QueryとKeyが似ていればいるほど、類似度が高くなります。

例えば、「猫が魚を食べた」という文章で、「食べた」という単語のQueryを考えます。このQueryは、入力文中の「猫」「が」「魚」「を」などのKeyとそれぞれ類似度を計算されます。

ソフトマックス関数による正規化

計算された類似度は、そのままでは数値の範囲が広すぎるため、ソフトマックス関数を通して正規化されます。これにより、類似度の合計が1になるような確率分布に変換されます。

この確率が、それぞれの単語に対する「注意の重み(Attention Weight)」となります。つまり、どの単語にどれだけ注目すべきかを示す度合いです。

先の例で言えば、「食べた」というQueryに対して、「魚」というKeyの類似度が最も高ければ、「魚」に最も大きな注意の重みが割り当てられます。

Valueの加重平均

最後に、計算された注意の重みを、各単語のValueベクトルにかけ合わせ、それらをすべて合計します。

これにより、「注意の重み付けされたValueの加重平均」が得られます。この加重平均されたベクトルが、今注目している単語にとって最も関連性の高い文脈情報を含んだものとなります。

Encoder(エンコーダ)の詳細

Encoderは、入力系列の各単語を数値ベクトルに変換し、その単語と文脈全体との関係性を捉え、入力系列全体の意味を包括的に表現する役割を担います。

Encoderの内部構造:

Encoderは、通常、複数の identical な層(レイヤー)が積み重ねられた構造をしています。各層は主に以下の2つのサブ層から構成されます。

Multi-Head Self-Attention(マルチヘッド自己注意機構)

役割: 入力系列内の各単語が、同じ入力系列内の他のすべての単語とどれだけ関連があるかを計算し、その関連性に基づいて、各単語の表現を更新します。

Self-Attention(自己注意): 「自己」という名前が示す通り、Query、Key、Valueの全てが、同じ入力系列の単語から導出されます。これにより、例えば「Apple(企業名)は、新しいApple(果物)を発表した」のような文で、「Apple」が文脈によって異なる意味を持つことを理解できます。

Multi-Head(マルチヘッド): 複数の異なる「注意の視点」(Head)を持つことで、単語間の多様な関係性(例:文法的な関係、意味的な関係など)を同時に捉えることができます。それぞれのヘッドが異なるAttention Weightを計算し、それらを連結して最終的な出力とします。

出力: この層の出力は、入力単語のベクトル表現が、その単語と文脈中の他の単語との関連性によって「文脈化」されたものになります。

Feed-Forward Network(フィードフォワードネットワーク)

役割: Multi-Head Self-Attentionの出力である「文脈化された単語表現」に対して、非線形な変換を適用し、より高次元の抽象的な特徴を抽出します。

構造: 通常、活性化関数(例:ReLU)を挟んだ2層の全結合ネットワーク(Fully Connected Layer)です。各単語の表現は、このネットワークを独立して通過します。

重要な補足: Positional Encoding(位置エンコーディング)

Transformerは、RNNのように単語を順番に処理するのではなく、並列に処理します。このため、単語の位置情報が失われてしまいます。これを補うために、各単語の入力ベクトルにPositional Encodingと呼ばれる、単語の位置に応じた情報を付加します。これにより、Transformerは単語の並び順(「猫が魚を食べた」と「魚が猫を食べた」の違いなど)を認識できるようになります。

Encoderの最終的な出力:

Encoderスタックの最後の層から出力されるベクトル群は、入力文章全体の意味的・文法的な情報が凝縮された「文脈表現」となります。この情報は、Decoderに渡されます。

もちろん、TransformerのEncoder-Decoder構造について、もう少し詳しく掘り下げて説明します。

TransformerのEncoder-Decoder構造は、主にシーケンス・トゥ・シーケンス(Sequence-to-Sequence: Seq2Seq)タスク、つまり、ある系列(シーケンス)の入力を別の系列の出力に変換するタスク(例:機械翻訳、要約など)において、その威力を発揮します。

全体の流れのイメージ Encoderが「入力文の理解」を担当します。 入力された文章(例:英語の文)を読み込み、その文章のすべての情報(意味、文法構造、単語間の関係性など)を凝縮した「文脈ベクトル」のような表現(実際には複数のベクトル)を生成します。

Decoderが「出力文の生成」を担当します。 Encoderが作り出した「文脈ベクトル」と、これまでに生成した出力単語(例:日本語に翻訳された単語)に基づいて、次に続く単語を予測し、最終的な出力文章を生成します。

  1. Encoder(エンコーダ)の詳細 Encoderは、入力系列の各単語を数値ベクトルに変換し、その単語と文脈全体との関係性を捉え、入力系列全体の意味を包括的に表現する役割を担います。

Encoderの内部構造:

Encoderは、通常、複数の identical な層(レイヤー)が積み重ねられた構造をしています。各層は主に以下の2つのサブ層から構成されます。

Multi-Head Self-Attention(マルチヘッド自己注意機構)

役割: 入力系列内の各単語が、同じ入力系列内の他のすべての単語とどれだけ関連があるかを計算し、その関連性に基づいて、各単語の表現を更新します。

Self-Attention(自己注意): 「自己」という名前が示す通り、Query、Key、Valueの全てが、同じ入力系列の単語から導出されます。これにより、例えば「Apple(企業名)は、新しいApple(果物)を発表した」のような文で、「Apple」が文脈によって異なる意味を持つことを理解できます。

Multi-Head(マルチヘッド): 複数の異なる「注意の視点」(Head)を持つことで、単語間の多様な関係性(例:文法的な関係、意味的な関係など)を同時に捉えることができます。それぞれのヘッドが異なるAttention Weightを計算し、それらを連結して最終的な出力とします。

出力: この層の出力は、入力単語のベクトル表現が、その単語と文脈中の他の単語との関連性によって「文脈化」されたものになります。

Feed-Forward Network(フィードフォワードネットワーク)

役割: Multi-Head Self-Attentionの出力である「文脈化された単語表現」に対して、非線形な変換を適用し、より高次元の抽象的な特徴を抽出します。

構造: 通常、活性化関数(例:ReLU)を挟んだ2層の全結合ネットワーク(Fully Connected Layer)です。各単語の表現は、このネットワークを独立して通過します。

重要な補足: Positional Encoding(位置エンコーディング)

Transformerは、RNNのように単語を順番に処理するのではなく、並列に処理します。このため、単語の位置情報が失われてしまいます。これを補うために、各単語の入力ベクトルにPositional Encodingと呼ばれる、単語の位置に応じた情報を付加します。これにより、Transformerは単語の並び順(「猫が魚を食べた」と「魚が猫を食べた」の違いなど)を認識できるようになります。

Encoderの最終的な出力:

Encoderスタックの最後の層から出力されるベクトル群は、入力文章全体の意味的・文法的な情報が凝縮された「文脈表現」となります。この情報は、Decoderに渡されます。

  1. Decoder(デコーダ)の詳細 Decoderは、Encoderが生成した入力文脈表現と、これまでに生成した出力単語に基づいて、次の出力単語を予測し、最終的な出力系列を生成する役割を担います。

Decoderの内部構造:

Decoderもまた、複数の identical な層が積み重ねられた構造をしています。各層は主に以下の3つのサブ層から構成されます。

Masked Multi-Head Self-Attention(マスクドマルチヘッド自己注意機構)

役割: 出力系列の生成において、未来の単語(まだ生成されていない単語)に「注意」を向けないようにするための自己注意機構です。

Masked(マスクド): Decoderは単語を一つずつ、左から右へ(順方向へ)生成していきます。そのため、ある時点での単語を生成する際には、その時点より後の単語の情報は参照できません。Masking(マスキング)とは、この「未来の情報を見せない」ための仕組みで、Attentionの計算において、未来の単語に対応するKey-Queryの類似度をゼロ(または非常に小さな値)に設定することで、注意の重みが未来の単語に割り当てられないようにします。

出力: これまでに生成された単語の文脈を反映した表現を出力します。

Multi-Head Encoder-Decoder Attention(マルチヘッドエンコーダ-デコーダ注意機構)

役割: ここがEncoderとDecoderをつなぐ重要な部分です。Encoderが生成した入力文章の文脈情報と、Decoderがこれまでに生成した出力単語の情報を関連付けます。

Query, Key, Valueの出所:

Query: DecoderのMasked Multi-Head Self-Attention層の出力(これまでの出力単語の文脈化された表現)から生成されます。

Key: Encoderスタックの最終層の出力(入力文章の文脈表現)から生成されます。

Value: Encoderスタックの最終層の出力から生成されます。

働き: Decoderは、今生成しようとしている単語にとって、入力文章のどの部分が最も重要かを判断し、その情報に「注意」を向けます。例えば、機械翻訳で「I love sushi」を翻訳する際に、"sushi"という単語を生成する段階で、英語の「sushi」という単語に強く注意を向けるような働きをします。

出力: Encoderからの情報とDecoder自身の情報が融合された表現。

Feed-Forward Network(フィードフォワードネットワーク)

役割: Encoderと同じく、非線形な変換を適用し、より高次元の抽象的な特徴を抽出します。

Decoderの最終的な出力:

Decoderスタックの最後の層から出力されるベクトルは、最終的に線形変換層とソフトマックス関数を通じて、次に生成されるべき単語の確率分布に変換されます。最も確率の高い単語が次の出力として選択され、その単語が次のデコードステップの入力として(Positional Encodingと共に)利用されます。このプロセスが、特別な終了トークン(例: )が生成されるまで繰り返されます。