💪

モテるGit管理 (gh, ghq, git-cz, lazygit)

2024/12/04に公開
4

この頃海外のエンジニアの環境構築動画を見るのにハマっているため、Mapifyから試してみようと思います。
ドキュメント読み込み機能が便利だった」にある公式ドキュメントベースで回答を生成してくれるのも便利ですね!

はじめに

コード管理スマートにしたい!カッコつけたい!😎

⭐️愉快なつらみたち⭐️

  • GitHubリポジトリを用意するためにターミナルから離れるの...?
  • あれ?ディレクトリどこにおいたっけ??
  • プロジェクトのディレクトリに移動するために長いパスを打つ苦行
  • プレフィックス多すぎておぼえられな〜い
  • プロジェクトごとにコミットメッセージのプレフィックスが違う..だと..?
  • 絵文字つけ忘れ&コミットメッセージ間違えちゃった😭
  • プロジェクトルートに戻るためにcd ../を繰り返し続ける人生...

こいつらを!全部!解決してやるぜぇ〜〜!!!💪

学習の初めをスマートに

手始めにこれらを解決しましょう。

  • GitHubリポジトリを用意するためにターミナルから離れるの...?
  • あれ?ディレクトリどこにおいたっけ??
  • プロジェクトのディレクトリに移動するために長いパスを打つ苦行

こんな感じでCLIでGitHubリポジトリとローカルのリポジトリを用意することができるようになります。

demo gh ghq

具体的には以下の手順を行なっています。

  1. ghコマンドでGitHubリポジトリを作成し
  2. ghqコマンドでローカルに clone & git init
  3. ghqでgit管理しているプロジェクト一覧を取得し、fzfで選択してプロジェクトディレクトリへ移動
# GitHubリポジトリを作成
gh repo create [プロジェクト名] --private

# ローカルにクローン & git init
ghq get [プロジェクト名]

# ^Gでghqで管理しているリポジトリ一覧を取得し、fzfで選択して移動 (^Gはあらかじめ.zshrcに設定)
# 設定していない場合は以下のコマンドで同じことができる
ghq list | fzf | xargs -I{} cd $(ghq root)/{}

それぞれのツールの導入やら使い方やらを解説していきます。


GitHubの操作をCLIで (gh)

GitHubの操作をCLIで行いたい時は GitHub CLI (gh コマンド) を使用します。

導入は以下の記事が参考になります。

リポジトリを作成したい時は

# プライベートリポジトリ
gh repo create [プロジェクト名] --private
# 公開リポジトリ
gh repo create [プロジェクト名] --public

リポジトリを削除したい場合は

gh repo delete [プロジェクト名]

みたいな感じでサクッとできます。

PRやらIssueやらも操作できるので詳しくはgh --helpを確認してみてください。

gh --help (日本語ver.)
GitHubとコマンドラインからシームレスに連携します。

使用法
  gh <コマンド> <サブコマンド> [フラグ]

コアコマンド
  auth:        ghとgitをGitHubに認証する
  browse:      ブラウザでリポジトリを開く
  codespace:   コードスペースに接続して管理する
  gist:        gistを管理する
  issue:       イシューを管理する
  org:         組織を管理する
  pr:          プルリクエストを管理する
  project:     GitHubプロジェクトを操作する
  release:     リリースを管理する
  repo:        リポジトリを管理する

GitHub Actionsコマンド
  cache:       GitHub Actionsキャッシュを管理する
  run:         ワークフロー実行の詳細を表示する
  workflow:    GitHub Actionsワークフローの詳細を表示する

エイリアスコマンド
  co:          "pr checkout"のエイリアス

追加コマンド
  alias:       コマンドショートカットを作成する
  api:         認証されたGitHub APIリクエストを行う
  attestation: アーティファクトの証明書を操作する
  completion:  シェル補完スクリプトを生成する
  config:      ghの設定を管理する
  extension:   gh拡張機能を管理する
  gpg-key:     GPGキーを管理する
  label:       ラベルを管理する
  ruleset:     リポジトリのルールセット情報を表示する
  search:      リポジトリ、イシュー、プルリクエストを検索する
  secret:      GitHubシークレットを管理する
  ssh-key:     SSHキーを管理する
  status:      リポジトリ全体の関連イシュー、プルリクエスト、通知に関する情報を表示する
  variable:    GitHub Actions変数を管理する

ヘルプトピック
  actions:     GitHub Actionsの操作について学ぶ
  environment: ghで使用できる環境変数
  exit-codes:  ghが使用する終了コード
  formatting:  ghからエクスポートされたJSONデータのフォーマットオプション
  mintty:      MinTTYでghを使用する際の情報
  reference:   すべてのghコマンドの包括的なリファレンス

フラグ
  --help      コマンドのヘルプを表示する
  --version   ghのバージョンを表示する

例
  $ gh issue create
  $ gh repo clone cli/cli
  $ gh pr checkout 321

詳細情報
  コマンドの詳細については`gh <コマンド> <サブコマンド> --help`を使用してください。
  マニュアルはhttps://cli.github.com/manualを参照してください。
  終了コードについては`gh help exit-codes`を使用して学んでください。

今いるリポジトリをブラウザで開くコマンドもあり、URLの共有や画面共有の時に便利ですね。

# 今いるリポジトリをブラウザで開く
gh browse

✌️✌️✌️✌️解決✌️✌️✌️✌️
これでターミナルとずっと一緒❤️❤️

  • GitHubリポジトリを用意するためにターミナルから離れるの...?

ローカルにあるリポジトリを管理 (ghq)

ghqとは

ghqはローカルにあるリポジトリを管理するためのツールです。

クローンするパスをghqで管理するため、自分が今いるディレクトリを意識せずクローンすることができます。
クローンするためにいちいちディレクトリ移動する必要がなくなるのがいいですね。
以下のコマンドで管理しているリポジトリの一覧を取得できるのも便利です。

# ghqで管理しているリポジトリ一覧
ghq list

ghqの導入

brew install ghq

ghqで管理するリポジトリのディレクトリのパスは~/.gitconfig[ghq] rootで指定します。

~/.gitconfig
[ghq]
 root = /Users/username/src

ghqでクローン

自分が管理しているレポジトリはリポジトリ名単体でクローンできます。

ghq get project-name

自分以外のリポジトリをクローンする時はリポジトリの所有者名をつけます。

ghq get user-name/project-name

ghq getは以下のパスにクローンしたものを配置します。

[.gitconfigで指定したディレクトリ] + [github.com/user-name/project-name]

例えば、mozumasu/dotfilesをクローンした場合は以下のようになります。

/Users/mozumasu/src/github.com/src/mozumasu/dotfiles
ghq --help (日本語ver.)
NAME:
   ghq - リモートリポジトリのクローンを管理

USAGE:
   ghq [グローバルオプション] コマンド [コマンドオプション]

VERSION:
   1.7.1 (rev:5bf53dc)

AUTHORS:
   motemen <motemen@gmail.com>
   Songmu <y.songmu@gmail.com>

COMMANDS:
   get, clone  リモートリポジトリのクローン/同期
   list        ローカルリポジトリの一覧
   rm          ローカルリポジトリの削除
   root        リポジトリのルートを表示
   create      新しいリポジトリを作成
   help, h     コマンドの一覧または特定のコマンドのヘルプを表示

GLOBAL OPTIONS:
   --help, -h     ヘルプを表示
   --version, -v  バージョンを表示

今いるディレクトリを意識せずに設定したパスにクローンできるのは認知不可が低くて快適ですね。
✌️✌️✌️✌️解決✌️✌️✌️✌️

  • あれ?ディレクトリどこにおいたっけ??

プロジェクトディレクトリにサクッと移動(ghq, fzf)

fzfとは

fuzzy finderの一つで、リストから曖昧検索して選択することができるツールです。
使えばわかります。使いましょう。
demo ghq fzf

fzfの導入

インストールは以下のコマンドで行います。

brew install fzf

ghqのパスが長いな〜と感じるかもしれませんが、
aliasを設定して^Gを押すとサクッと移動できるようにしておけば負担になることもありません。

~/.zshrc
# ghq
function ghq-fzf() {
  local src=$(ghq list | fzf --preview "bat --color=always --style=header,grid --line-range :80 $(ghq root)/{}/README.*")
  if [ -n "$src" ]; then
    BUFFER="cd $(ghq root)/$src"
    zle accept-line
  fi
  zle -R -c
}
zle -N ghq-fzf
bindkey '^g' ghq-fzf

自分はファジーファインダーにfzf, プレビューにbatを使用しています。この部分はお好きなものに書き換えてください。
コードはこちらの記事に載っているものを使用させていただだいています。コードの詳細な解説もあるありがたい記事です。感謝🙏

解決ッ!🎉

  • プロジェクトのディレクトリに移動するために長いパスを打つ苦行

コミットをスマートに

続いてのお題はこちら。

  • プレフィックス多すぎておぼえられな〜い
  • プロジェクトごとにコミットメッセージのプレフィックスが違う..だと..?
  • 絵文字つけ忘れ&コミットメッセージ間違えちゃった😭

demo lazygit git-cz
画像は以下の手順を行なっている様子です。

  1. Lazygitでファイルをステージング
  2. Lazygit経由でgit-czを実行してコミット
  3. LazygitでPush
  4. ghq browseで今いるディレクトリのGitHubリポジトリをブラウザで開く

コミットメッセージを美しく (git-cz)

git-czはConventional Commitsというコミットメッセージの標準規格に従ったコミットメッセージを作成することができます。
要はプレフィックスとフォーマットを強制してコミットメッセージを美しくしてくれるツールです。

以下のように対話形式でプレフィックスを選んでコミットメッセージを作成することができるため、プレフィックスが覚えられない&絵文字つけ忘れ問題もgit-czが解決してくれます。
git-cz

git-czの導入

npm install -g git-cz

プロジェクトごとにプレフィックスを設定

プロジェクトごとに固有のプレフィックスがある場合はプロジェクトのルートにchangelog.config.jsを設置し、プレフィックスを設定します。

zennのリポジトリの例
changelog.config.js
module.exports = {
  disableEmoji: false,
  format: "{type}: {emoji}{subject}",
  list: [
    "add",
    "update",
    "publish",
    "unpublish",
    "delete",
    "fix",
    "chore",
    "docs",
  ],
  maxMessageLength: 64,
  minMessageLength: 3,
  questions: [
    "type",
    "scope",
    "subject",
    "body",
    "breaking",
    "issues",
    "lerna",
  ],
  types: {
    add: {
      description: "新規記事の追加",
      emoji: "🚀",
      value: "add",
    },
    update: {
      description: "記事の追記や更新",
      emoji: "🎸",
      value: "update",
    },
    publish: {
      description: "記事の公開",
      emoji: "🔖",
      value: "publish",
    },
    unpublish: {
      description: "記事の非公開",
      emoji: "🙈",
      value: "unpublish",
    },
    delete: {
      description: "記事の削除",
      emoji: "🗑",
      value: "delete",
    },
    fix: {
      description: "記事の誤字・脱字の修正",
      emoji: "🐛",
      value: "fix",
    },
    chore: {
      description: "CI/CDの変更やパッケージのアップデートなど",
      emoji: "🤖",
      value: "chore",
    },
    fix: {
      description: "不具合の修正",
      emoji: "🐛",
      value: "fix",
    },
    docs: {
      description: "ドキュメントの更新",
      emoji: "✏️",
      value: "docs",
    },
  },
  messages: {
    type: "Select the type of change that you're committing:",
    subject: "Write a short, imperative mood description of the change:\n",
    body: "Provide a longer description of the change:\n ",
    breaking: "List any breaking changes:\n",
    issues: "Issues this commit closes, e.g #123:",
  },
};
  • プレフィックス多すぎておぼえられな〜い
  • プロジェクトごとにコミットメッセージのプレフィックスが違う..だと..?

もちろんグローバル設定も用意可能です。
グローバル設定は~chanlog.config.jsに配置します。

~/.chanlog.config.js (グローバル設定)
~/.chanlog.config.js
module.exports = {
  disableEmoji: false,
  format: "{type}{scope}: {emoji}{subject}",
  list: [
    "feat",
    "test",
    "fix",
    "chore",
    "docs",
    "refactor",
    "style",
    "ci",
    "perf",
    "package",
    "config",
    "WIP",
  ],
  maxMessageLength: 64,
  minMessageLength: 3,
  questions: [
    "type",
    "scope",
    "subject",
    "body",
    "breaking",
    "issues",
    "lerna",
  ],
  scopes: [],
  types: {
    feat: {
      description: "新機能",
      emoji: "🎸",
      value: "feat",
    },
    chore: {
      description: "ビルド関連やライブラリの変更",
      emoji: "🤖",
      value: "chore",
    },
    ci: {
      description: "CI関連の変更",
      emoji: "🎡",
      value: "ci",
    },
    docs: {
      description: "ドキュメントの更新",
      emoji: "✏️",
      value: "docs",
    },
    fix: {
      description: "不具合の修正",
      emoji: "🐛",
      value: "fix",
    },
    perf: {
      description: "パフォーマンス改善",
      emoji: "⚡️",
      value: "perf",
    },
    refactor: {
      description: "リファクタリング",
      emoji: "💡",
      value: "refactor",
    },
    style: {
      description: "コードの処理に影響しない変更(スペースや書式設定など)",
      emoji: "💄",
      value: "style",
    },
    test: {
      description: "テストコード",
      emoji: "💍",
      value: "test",
    },
    //自分用に追加
    package: {
      description: "パッケージ",
      emoji: "📦",
      value: "package",
    },
    config: {
      description: "設定ファイル",
      emoji: "⚙",
      value: "config",
    },
    WIP: {
      description: "作業途中",
      emoji: "🚧",
      value: "WIP",
    },
  },
  messages: {
    type: "プレフィックスを選択:",
    subject: "コミットのタイトル(概要)を入力(option):\n",
    body: "変更内容の詳細を入力(option):\n",
    breaking: "重大な変更を入力(option):\n",
    issues: "関連するisuueを入力(option), 例 #123:",
  },
};

Git管理を簡単に (Lazygit)

Git管理を簡単にするTUIツールlazygitを使用します。
lazygit

コミットを手軽に分けたり、修正したい!みたいな時に重宝します。
?でキーバインド一覧を表示できます。gitのコマンドはおろか、lazygitの操作なんて覚えられない!って人でも安心ですね。
lazygit help
ターミナルでもNeovimでも使用することができます。
下記のように簡単にファイルをステージング&コミットし、Pushすることができます。
lazygit

Lazygitの導入

brew install jesseduffield/lazygit/lazygit

lazygitって入力するのが大変なのでaliasを設定しておくと便利です。

~/.zshrc
abbr -S lg='lazygit' >>/dev/null

LazyGitでよくやる操作

コミット前のファイルを一時退避 (Stash)

  • 差分を全てStash

    • s
  • ステージングだけStash

    • スペースキーでファイルをステージング
    • ステージングしたファイルをSsでStash
  • Stashをステージに反映

    • Stashウィンドウを選択し、反映させたいStashをスペースで選択
    • Stashした内容が反映される

以下のgifではステージングのStashとStashの反映をしている様子です。

Stash

コミット漏れを修正 (git commit --amend)

ファイルをステージングした状態でA
lazygit_amend

コミットメッセージを修正

修正したいコミットメッセージにカーソルを合わせてrを押すとコミットメッセージを編集することができます。
lazygit_rename

コミットの内容を変更したい (fixup)

特定のコミットを修正したい場合は、以下の手順で行います。

  • コミットに加えたい内容をステージング
  • 修正したい対象のコミットにカーソルを合わせてFを押す (fixupコミットが作成される)
  • 修正したい対象のコミットに再度カーソルを合わてSを押す (auto squash)

fixupよくわからんって人は以下の記事を参考にしてください。

コミットメッセージの修正もできるようになりました🙌

  • 絵文字つけ忘れ&コミットメッセージ間違えちゃった😭

コミットを別ブランチに持っていく (cherry-pick)

私はよくブランチを間違えてコミットしてしまいます😭
別ブランチにコミットしてしまった場合は以下の手順で別ブランチにコミットを持っていくことができます。

  • 間違ってコミットしたブランチにスペースキーで移動
  • 移動したいコミットにカーソルを合わせてC
  • コミットを持っていきたいブランチにスペースキーで移動
  • Vでコミットを貼り付ける

cherry-pick

Lazygitからgit-czを使う

lazygitの設定ファイルは~/.config/lazygit/config.ymlにあります。
自分は以下のように設定して、Cでgit-czを実行できるようにしています。

~/.config/lazygit/config.yml
# https://github.com/jesseduffield/lazygit/blob/master/docs/Config.md

customCommands:
  - command: git cz
    context: files
    subprocess: true
    key: C

gui:
  language: "ja"
  showIcons: true

# log customize
git:
  branchLogCmd: "git log --graph --color=always --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' {{branchName}} --"
  allBranchesLogCmd: "git log --graph --color=always --pretty='%Cred%h%Creset -%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --all"
  paging:
    colorArg: always
    pager: delta --dark --paging=never

プロジェクトルートに戻る時もスマートに

最後にこれを解決しましょう。

  • プロジェクトルートに戻るためにcd ../を繰り返し続ける人生...

プロジェクトルートに戻る

実はgitコマンドにはgit rev-parse --show-toplevelという便利コマンドがあります。
これを以下のようにaliasに設定しておくとprootでプロジェクトルートに移動することができます。

~/.zshrc
abbr -S proot='cd $(git rev-parse --show-toplevel)' >>/dev/null

または

~/.zshrc
alias proot='cd $(git rev-parse --show-toplevel)'

直前のディレクトリに戻る

cd -で直前のディレクトリに戻ることができます。
プロジェクトルートから移動した場合はcd -でもプロジェクトルートに戻ることができます。

通常はcd -で戻って、cd -で戻れなかったらprootにして使い分けてもいいかもしれません。

追加でzshの設定ファイルに以下のオプションを追加しておくとcd無しでディレクトリ移動ができるようになります。
-だけで戻れるので楽ですね。

~/.zshrc
setopt auto_cd

これでもう../を繰り返す必要はありませんね🎵

  • プロジェクトルートに戻るためにcd ../を繰り返し続ける人生...

git-czとcz-git (12/6追記)

おわりに

少しでも皆様のCLI生活が快適になれば幸いです。

アドベントカレンダー5日目はucanさんの「JavaScriptビルドツールの歴史と進化」という記事です。
ツールオタクとしては目が離せない内容ですね。
明日もぜひお楽しみに🎄

また、コメントやTwitterにてコメントいただきありがとうございました!自身の知識のアップデートできて嬉しい限りです。

GitHubで編集を提案

Discussion

unvalleyunvalley

こんにちは、自分もgit-czを使っていましたが、最近はcz-git(czg) の方を利用しています。

主な機能差分は以下にまとめられています。(実際そこまで大きな差はない気がしていますが)
https://cz-git.qbb.sh/guide/why

FYI程度でした。よければ見てみてください。

mozumasumozumasu

情報いただきありがとうございます!OSSを見たり試したりするのが好きなので教えていただけて嬉しいです!

148 MB node_modules/git-cz
1.9 MB node_modules/cz-git

👀軽量化されていてプロジェクトへの導入のハードルも下がりますね...!
日曜日くらいに使い倒してみます!

さいぬさいぬ

abbr -S lg='lazygit' >>/dev/null

これでabbrの標準出力を出さないようにしてますが、--quieterオプションをつけると同じことができるので是非。

abbr -S --quieter lg='lazygit'
or
abbr -S -qq lg='lazygit'
mozumasumozumasu

おお!!この書き方見やすくて最高にクールですね!
自分の設定ファイルが>>/dev/nullだらけで見づらいな〜と思っていたので助かります😭

本文にも追記させていただきます!もし問題等あれば教えていただけますと幸いです。🙏