Git 2.x シリーズの 6 つの素晴らしいフィーチャー

私が Git リリース ノートをレビューしてからしばらく経ちましたが 、だからといって私が最新のノートを熱心に読んでおらず、毎日の作業に新たな優れモノを取り入れていなかった訳ではありません。自分の誕生日 (拍手!) と、先日の Bitbucket Server のリリースを祝うため、本日は私が Git 2.x シリーズ (2.6 まで) で気に入っているフィーチャーを全てご紹介します。どれか役に立つようなことがあれば、是非ご一報ください。

リベース前に変更内容をスタッシュ

Git 2.6 では、rebase コマンドが皆さんから良い意味での注目を浴びました。以下にご紹介するのは、より興味深い新しいフラグの1つです :

git rebase --autostash

これからは、rebase 操作の開始時に未コミットの変更内容を一時的にスタッシュするか、操作を失敗させるかを指定できます。この行動を恒久的にするには、次の新しい設定オプションを用います:rebase.autostash

true に設定すると、Git は rebase 操作の開始前に未コミットの変更内容をスタッシュし、操作の終了時に再び変更内容を適用します。この機能をオンにした場合は、スタッシュした内容が元の状態に戻る際のコンフリクトの可能性に備える必要があります。

autostash フラグをオンにした場合は、次の 2.7 リリースによる新しい --no-autostash コマンドラインのオプションを用いることで、一時的にこれを無効化できます。

複数クローンの優れた取り扱い: Git Worktree

Git 2.5 では、新たな worktree コマンドが導入されています。これは、同じルート リポジトリのチェックアウト済みワークツリーを複数保持することを可能にします。素晴らしいですね。

このコマンドが誕生する以前、コンテキストを切り替えて異なるストリームを同時に作業するには次のいくつかの方法がありました:

  • 現在の未コミットの変更内容をスタッシュして、異なるブランチを checkout (git stash を利用)。
  • 現在のブランチに work-in-progress (即ち WIP) コミットを作成して、作業内容の保存とブランチの切り替えを実行。
  • リポジトリの完全なクローンを別に作成し、2 つの進行中の開発努力を別々かつ並行して進める。
  • ココで解説したように、環境変数である GIT_WORK_TREE またはGIT_DIR を設定。

worktree であれば、任意のチェックアウト済み branch、いわば ref を備えたルートプロジェクトのサブフォルダーを作成し、終了するまで作業を続けることができます。このコマンドのおかげで、- アウトオブバンド – クローンを別途に作成する必要がなくなります。

それでは、あなたが develop ブランチの作業に楽しく取り組んでいたところ、膨大な変更内容を伴う rewrite ブランチの作業を数日間にわたって行うよう命じられたとしましょう。この場合でも、この大掛かりな作業に向けて worktree を作成し、他の進行中の作業をそのままにしておくことが可能となります。このコマンドの構文は、以下の通りです:

git worktree add [-f] [--detach] [-b ] []

よって、今挙げた例では、次のようなコマンドができあがります:

git worktree add rewrite-folder rewrite

このコマンドは、チェックアウト済みブランチの rewrite を含む、rewrite-folder (ここに疑問の余地はありませんね) という名のサブフォルダーをプロジェクトのルートに作成します。

まるで Git プロジェクトのルートにあるかのごとく、このサブフォルダーからはプッシュあるいはプルすることが可能であり、作業が終了後には単に rewrite-folder を削除するだけで済みます。.git/worktrees に保管された管理ファイルはいずれ取り除かれますが、徹底してそのデータを取り除きたい場合は、以下を実行します:

git worktree prune [-n] [-v] [--expire ]

git commit --fixup を利用して、素早い修正を

私がこの点に注目したのは、Git のコントリビューターである Luke Diamand が最新の Git Rev News のインタビューにおいて、このところ最も気に入っている Git 機能は git commit --fixup であると語っていたからでした。

これを利用するには、次の設定を把握する必要があります。まず、あなたがあるフィーチャーもしくはバグ修正に取り組んでいるとします。まだ、そのコードは誰とも共有していないのですが、あるべきではないコードを削除するか、余分な (乱れた) コミットを作成することなくバグ修正を行うなどの理由から、前回の非 HEAD コミットの 1 つを変更する必要があることに気付いてしまいます。ここで役立つのが、commit --fixup です:

以下のように表示される、ID 026b6b5 のコミットがあると仮定しましょう:

026b6b5 [2 days ago] Implement feature A [Author]

自分のワークツリーに若干の変更を行い、これをそのフィーチャーコミットの "fixup" としてマークを付けます:

git commit -a --fixup 026b6b5

このコマンドが作成するコミットは、次のように表示されます:

4b7076f [6 seconds ago] (HEAD -> feature-a) fixup! Implement feature A [Author]

このブランチをプッシュする前の最終ステップとして、--autosquash を用いたインタラクティブな rebase を行います。Git は上述の fixup! のような注釈付きコミットを拾い、修正内容を適切な場所に組み込んでくれます:

git rebase --interactive --autosquash master

このコマンドは、正しいアクションが既に記入されたリベースのインタラクティブシート上で、エディターを開いてくれます。お使いの .gitconfig において、グローバル変数である rebase.autosquash=true を設定済みの場合、--autosquash オプションは省略できます。

show-branch --topics でトピックブランチを追跡

Git ドキュメントによると、show-branch コマンドは " <rev>s または <globs>s と名づけられたコミットから始まるコミット家系図を半視覚的に表示する" と解説されています。

--topics フラグを加えると、与えられたブランチには無いコミットのみが表示されます。これは、メインブランチに既に表示されているコミットを素早く隠す際に便利です。2.5 で加えられた改善によって、以下のコマンドが成り立ちます:

git show-branch --topics HEAD

与えられたコミットを、全てのローカルブランチと比較してみましょう。例えば、このブログを含んだプロジェクトでは、次のような結果となります:

Screen Shot 2015-10-28 at 9.36.06 AM

ネガティブな "grepping"

時々、メッセージ内に具体的なストリングを持たないコミットを探したい場合があります。ここで役立つのは、新しいフラグである --invert-grep です。例えば、特定の課題 ID を含まない全てのコミットを探すには、以下を行います:

git log --invert-grep --grep=PRJ-25

これによって、コミットメッセージ内に PRJ-25 を含まない、全てのコミットが返されます。見事ですね。

Atomic なプッシュ

はだかの git push のデフォルト行動を定義するには、push.default 設定パラメーターを設定します。同時に複数のブランチもしくはタグをプッシュするという具合に、プッシュコマンドが 1 つ以上の ref を更新しているケースにおいて、今後は更新が確実に全て成功、もしくは全て失敗するよう、新しいオプションとして --atomic を指定できます。

結論

以上で全てです。興味深い内容はありましたか?皆さんは日々の開発作業で、他にも難解なフラグを用いていますか?私はいつでも新たな秘訣やフラグを習得したいと思ってますので、@durdn または @atlassiandev 宛てにツイートして頂くか、ここにコメントを残してください。




*本ブログは Atlassian Developers の翻訳です。本文中の日時などは投稿当時のものですのでご了承ください。
*原文 : 2015 年 10 月 26 日投稿 "Six cool features of the Git 2.x series"