TES Blog

株式会社テクニカルエンジニアリングサポートに所属する社員が、自身が携わるテクノロジーやイベントに関する情報を発信しています。

Gitコマンドあれこれ

個人的に忘れっぽいコマンドとか、あまり普段使わないようなコマンドを備忘録として載せます。

git rebaseの使い方

コンフリクト解消した後どうするんだっけ…ってたまになる。

1.マスターを最新化する

git checkout master
git pull

2.トピックブランチにリベースする

git checkout {{ トピックブランチ名 }}
git rebase master

3.リベースした時にコンフリクトが発生時

# コンフリクトを解消
git add .
git rebase --continue

4.コンフリクト解消後すでにリモートにpushしてある時

# リベースコンテニュー後に下記を実行
git push -f origin {{ リモートブランチ名 }}

※force pushなので気をつけること

Git Stashの使い方(編集内容一時退避)

編集内容を退避させる

git stash save

※saveは省略可能

退避した内容の復活と、復活させたstash内容の削除を同時に行う

git stash pop stash@{0}

※最新の退避内容を復活&削除したい場合は stash@{0} が不要

複数行のコミットコメントを行う

git commit -F- <<EOM
> コミットコメント要約
>
> コミットコメント詳細
> 詳細あれこれ
> EOM

対象ブランチ間同士の差分系

こんなに差分取ることなんて早々ない。

差分のあるファイルを対象に、ファイル名だけを取得

git diff {{ ブランチ名1 }} {{ ブランチ名2 }}  --name-only

差分の種類を取得(追加・更新・削除など)

git diff --name-status {{ ブランチ名1 }} {{ ブランチ名2 }}

git logの表示形式で差分を取得

git log -p {{ ブランチ名1 }}...{{ ブランチ名2 }}

コミットハッシュ値とコミットコメントのみの差分を取得

git log --pretty=format:"%H %s" {{ ブランチ名1 }}...{{ ブランチ名2 }}

ソースレベルでブランチ同士の差分を取得

git diff {{ ブランチ名1 }} {{ ブランチ名2 }}

空コミットを行ってPRを作成する

プルリク駆動で便利!

1.--allow-emptyで空のコミットを作成

git commit --allow-empty -m "PR作成用空コミット"

2.通常どおりpushする

3.空コミットでpushされたブランチでPRを作成

4.その後、コミットしたい部分をaddする

5.次に変更を行った部分をコミットする場合、--amendで空コミットを上書き

git commit --amend -v

6.force pushで空コミットしたブランチに対応した内容を反映させる

git push -f origin {{ リモートブランチ名 }}

※force pushなので気をつけること

指定ファイルをgitの追跡対象から外す

1.除外する

git update-index --assume-unchanged {{ ファイルパス }}

2.除外を解除する

git update-index --no-assume-unchanged {{ ファイルパス }}

3.除外しているファイルを確認する

git ls-files -v | grep ^h

直前のコミット取り消し

コミットの取り消しとワークディレクトリの編集内容も削除

git reset --hard HEAD^

ワークディレクトリの内容はそのままでコミットだけ取り消し

git reset --soft HEAD^

※ステージングに上げた状態(addした状態)になる

そこからadd状態を取り消すなら

git reset

cherry-pickの使い方

コミット単位でcherry-pick

単一のコミット内容のみ反映する。

git cherry-pick 1 {{ コミット番号 }}

マージコミット単位でcherry-pick

-m オプションを使用する。

git cherry-pick -m 1 {{ マージコミット番号 }}

マージ単位となるので、例えば一つのPRに複数件のコミットがある場合は、すべてのコミット内容が反映対象になります。

[JavaScript]イベントにもasync/awaitを使おう

はじめに

ECMAScriptが2015年から毎年バージョンアップするようになり、JavaScriptの仕様は大きく変わりました。 特に非同期処理まわりは、Promise(ECMAScript2015~)、async/await(ECMAScript2017~)が導入されたことで、 コールバック地獄の回避や可読性の向上などを実現できるようになりました。

また、JavaScriptではクリックやマウスホバーなどのイベントを検知する機能があります。 通常、イベント登録時に、イベント発火時に実行される処理をコールバックとして渡します。 実は、この従来の書き方をasync/awaitに置き換えると、一見すると同期処理的に書けるようにできます。

本記事では、以下の例のように、async/awaitへ置き換える話を説明します。

// いままでの書き方
const target = document.querySelector("#button");
target.addEventListener("click", () => {
  alert("クリックされた!");
});
// async/awaitを使った書き方
const target = document.querySelector("#button");
// ↓async/awaitを使えるように定義した関数(詳細は後述)。
// クリックされるまで、次の処理へ進まず非同期的に待機する。
await awaitForClick(target);
alert("クリックされた!");

考え方

awaitは、Promiseがsuccessされるまで、後続の処理へ進みません。 よって、イベント発火時にPromiseをresolveさせれば良いことになります。 具体的には、こんな感じです。
※今回はクリックイベントに限定していますが、抽象化すれば他のイベントでも応用出来ると思います。

const awaitForClick = target => {
  return new Promise(resolve => { // 処理A
    const listener = resolve;     // 処理B
    target.addEventListener("click", listener, {once: true}); // 処理C
  });
};

処理A:awaitForClick関数は、awaitで待機させるようPromiseのインスタンスを返すようにします。
処理B:イベント発火時にPromiseをresolveするリスナー(コールバック)を定義します。
処理C:処理Bで定義したコールバックを使って、イベント登録します。

これによって、awaitForClick関数は、引数に渡した要素がクリックされるまで、 次の処理へ進まなくなります。

なお、{once: true}で登録すると、1度しか発火しなくなります。 今回、それをオプションで渡しているのは、resolve関数を2回以上呼んでも意味が無いためです。 (resolve関数は、2回目以降何も起こりません)

使用例

クイズの回答を入力する画面で使うケースを紹介します。

JSFiddleでも動かせます。https://jsfiddle.net/fu0c3rnu/22/

<div id="question"></div>
<input type="text" id="user-input">
<button id="answer-button">回答!</button>
(async () => {
  const awaitForClick = target => { // 処理A
    return new Promise(resolve => {
      const listener = resolve;
      target.addEventListener("click", listener, {once: true});
    });
  };

  // 処理B
  const quiz = [
    {question: "日本で一番北に位置する都道府県は?", answer: "北海道",},
    {question: "日本の通貨は「円」。では、中国は?", answer: "元",},
    {question: "与えても無駄という意味のことわざ「豚に○○」。○○とは?", answer: "真珠",},
  ];

  let points = 0;
  for (const {question, answer} of quiz) {
    $("#question").text(question);               // 処理C
    await awaitForClick($("#answer-button")[0]); // 処理D
    const input = $("#user-input").val();        // 処理E
    if (!input || input !== answer) {            // 処理F
      alert(`残念!答えは${answer}でした!`);
    } else {
      points++;
      alert("正解です!");
    }
  }
  alert(`あなたの点数は${quiz.length}点中、${points}点でした!`); // 処理G
})();

処理A:awaitForClick関数を定義します。
処理B:出題する問題を定義します。
処理C:問題文を画面上に出します。
処理D:引数に渡しているボタン要素がクリックされるまで待機します。
処理E:入力された文字列を取得します。
処理F:答え合わせをし、アラートを出します。合っていれば点数を加算します。
処理G:点数をアラートで表示させます。

見ての通り、上から順番に実行されており、同期的処理のコードのように見えます。 処理の流れが追いやすく直感的なので、可読性が上がることが期待できますね。

おわりに

async/awaitを使うことで、同期処理ぽく書けるやり方を説明しました。 また、使用例としてクイズの回答を入力する画面を提示しました。 今回詳しく見ていませんが、モーダルウィンドウでも、いい感じに使えます。
https://jsfiddle.net/njny5xxo/3/

なお、今回のやり方はasync/awaitを実装しているブラウザでしか使えません。 各ブラウザの対応状況は、こちらで確認できます。
https://caniuse.com/#feat=async-functions
例によって、IE11では使えませんので、Babelなどを使う必要があります。