iTranslated by AI
Smart Git Management (gh, ghq, git-cz, lazygit)
I've been into watching environment setup videos by overseas engineers lately, so I'm thinking of trying Mapify.
The fact that it generates answers based on official documentation, as mentioned in "The document reading feature was convenient," is also very handy!
Introduction
I want to manage code smartly! I want to look cool! 😎
⭐️ Fun struggles ⭐️
- Having to leave the terminal to set up a GitHub repository...?
- Wait, where did I put this directory??
- The penance of typing long paths to move to a project directory
- Too many prefixes, I can't remember them all~
- What... the commit message prefix is different for every project..?
- Forgot the emoji & messed up the commit message 😭
-
A life of repeatedly typing
cd ../to get back to the project root...
I'm going to solve all of these!!! 💪
Getting Started Smartly
Let's start by solving these.
- Having to leave the terminal to set up a GitHub repository...?
- Wait, where did I put this directory??
- The penance of typing long paths to move to a project directory
In this way, you will be able to prepare GitHub and local repositories via CLI.

Specifically, the following steps are being performed:
- Create a GitHub repository with the gh command
- Clone and
git initlocally using the ghq command - Get a list of projects managed by ghq, select one with fzf, and move to the project directory
# Create a GitHub repository
gh repo create [project-name] --private
# Clone locally & git init
ghq get [project-name]
# Get a list of repositories managed by ghq with ^G, select with fzf and move (^G is pre-configured in .zshrc)
# If not configured, you can do the same with the following command
cd $(ghq list -p | fzf)
I will explain the installation and usage of each tool.
Operating GitHub via CLI (gh)
When you want to perform GitHub operations from the CLI, use the GitHub CLI (gh command).
The following article is helpful for installation.
When you want to create a repository:
# Private repository
gh repo create [project-name] --private
# Public repository
gh repo create [project-name] --public
If you want to delete a repository:
gh repo delete [project-name]
You can do it quickly like this.
You can also manage PRs and Issues, so please check gh --help for details.
gh --help (English version)
Work seamlessly with GitHub from the command line.
Usage
gh <command> <subcommand> [flags]
Core commands
auth: Authenticate gh and git with GitHub
browse: Open the repository in the browser
codespace: Connect to and manage codespaces
gist: Manage gists
issue: Manage issues
org: Manage organizations
pr: Manage pull requests
project: Work with GitHub Projects
release: Manage releases
repo: Manage repositories
GitHub Actions commands
cache: Manage GitHub Actions caches
run: View details of workflow runs
workflow: View details of GitHub Actions workflows
Alias commands
co: Alias for "pr checkout"
Additional commands
alias: Create command shortcuts
api: Make an authenticated GitHub API request
attestation: Work with artifact attestations
completion: Generate shell completion scripts
config: Manage configuration for gh
extension: Manage gh extensions
gpg-key: Manage GPG keys
label: Manage labels
ruleset: View info about repository rulesets
search: Search for repositories, issues, and pull requests
secret: Manage GitHub secrets
ssh-key: Manage SSH keys
status: Show information about relevant issues, pull requests, and notifications across repositories
variable: Manage GitHub Actions variables
Help topics
actions: Learn about working with GitHub Actions
environment: Environment variables that can be used with gh
exit-codes: Exit codes used by gh
formatting: Options for formatting JSON output from gh
mintty: Information about using gh with MinTTY
reference: Comprehensive reference of all gh commands
Flags
--help Show help for command
--version Show gh version
Examples
$ gh issue create
$ gh repo clone cli/cli
$ gh pr checkout 321
Further help
Use "gh <command> <subcommand> --help" for more information about a command.
Read the manual at https://cli.github.com/manual
Learn about exit codes with "gh help exit-codes"
There is also a command to open the current repository in a browser, which is handy for sharing URLs or screen sharing.
# Open the current repository in the browser
gh browse
✌️✌️✌️✌️ Solved ✌️✌️✌️✌️
Now I'm with the terminal forever ❤️❤️
- Having to leave the terminal to set up a GitHub repository...?
Managing Local Repositories (ghq)
What is ghq?
ghq is a tool for managing local repositories.
Since ghq manages the cloning path, you can clone without being conscious of your current directory.
It's great because it eliminates the need to move directories every time you want to clone.
It's also convenient to be able to get a list of managed repositories with the following command:
# List of repositories managed by ghq
ghq list
Installing ghq
brew install ghq
The directory path for repositories managed by ghq is specified in [ghq] root in ~/.gitconfig.
[ghq]
root = /Users/username/src
Cloning with ghq
You can clone repositories you manage using just the repository name.
ghq get project-name
When cloning repositories other than your own, include the owner's name.
ghq get user-name/project-name
ghq get places the cloned items in the following path:
[Directory specified in .gitconfig] + [github.com/user-name/project-name]
For example, if you clone mozumasu/dotfiles, it would look like this:
/Users/mozumasu/src/github.com/src/mozumasu/dotfiles
ghq --help (English version)
NAME:
ghq - Manage remote repository clones
USAGE:
ghq [global options] command [command options]
VERSION:
1.7.1 (rev:5bf53dc)
AUTHORS:
motemen <motemen@gmail.com>
Songmu <y.songmu@gmail.com>
COMMANDS:
get, clone Clone/sync remote repositories
list List local repositories
rm Remove local repositories
root Show repositories' root
create Create a new repository
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--help, -h show help
--version, -v print the version
Being able to clone to a predefined path without worrying about the current directory is low cognitive load and comfortable.
✌️✌️✌️✌️ Solved ✌️✌️✌️✌️
- Wait, where did I put this directory??
Quickly Move to Project Directories (ghq, fzf)
What is fzf?
fzf is a fuzzy finder tool that allows you to search and select items from a list using fuzzy matching.
You'll understand once you use it. Just use it.

Installing fzf
Install it with the following command:
brew install fzf
You might feel that ghq paths are quite long, but if you set up an alias so you can move quickly by pressing ^g, it won't be a burden anymore.
# 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
I use fzf as the fuzzy finder and bat for previews. Please replace these parts with your preferred tools.
You can install bat with the following command:
brew install bat
I am using the code provided in this article. It's a very helpful article that includes detailed explanations of the code. Thank you! 🙏
Solved! 🎉
- The penance of typing long paths to move to a project directory
Committing Smartly
Next up is this topic.
- Too many prefixes, I can't remember them all~
- What... the commit message prefix is different for every project..?
- Forgot the emoji & messed up the commit message 😭

The image shows the following steps being performed:
- Staging files with Lazygit
- Executing git-cz via Lazygit to commit
- Pushing with Lazygit
- Opening the GitHub repository for the current directory in a browser using
ghq browse
Making Commit Messages Beautiful (git-cz)
git-cz allows you to create commit messages that follow the standard specification called Conventional Commits.
In short, it's a tool that beautifies commit messages by enforcing prefixes and formatting.
Since you can create commit messages by selecting prefixes in an interactive format as shown below, git-cz solves the problems of not being able to remember prefixes or forgetting to add emojis.

Installing git-cz
npm install -g git-cz
Setting Prefixes for Each Project
If there are specific prefixes for each project, you can set them by placing a changelog.config.js in the project root.
Example of a Zenn repository
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: "Adding a new article",
emoji: "🚀",
value: "add",
},
update: {
description: "Updating or adding content to an article",
emoji: "🎸",
value: "update",
},
publish: {
description: "Publishing an article",
emoji: "🔖",
value: "publish",
},
unpublish: {
description: "Unpublishing an article",
emoji: "🙈",
value: "unpublish",
},
delete: {
description: "Deleting an article",
emoji: "🗑",
value: "delete",
},
fix: {
description: "Fixing typos or omissions in an article",
emoji: "🐛",
value: "fix",
},
chore: {
description: "Changes to CI/CD or package updates, etc.",
emoji: "🤖",
value: "chore",
},
fix: {
description: "Fixing bugs",
emoji: "🐛",
value: "fix",
},
docs: {
description: "Updating documentation",
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:",
},
};
- Too many prefixes, I can't remember them all~
- What... the commit message prefix is different for every project..?
You can also prepare global settings.
Place global settings in ~/.chanlog.config.js.
~/.chanlog.config.js (Global settings)
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: "New feature",
emoji: "🎸",
value: "feat",
},
chore: {
description: "Changes related to build or libraries",
emoji: "🤖",
value: "chore",
},
ci: {
description: "Changes related to CI",
emoji: "🎡",
value: "ci",
},
docs: {
description: "Updating documentation",
emoji: "✏️",
value: "docs",
},
fix: {
description: "Fixing bugs",
emoji: "🐛",
value: "fix",
},
perf: {
description: "Performance improvements",
emoji: "⚡️",
value: "perf",
},
refactor: {
description: "Refactoring",
emoji: "💡",
value: "refactor",
},
style: {
description: "Changes that do not affect the meaning of the code (white-space, formatting, etc.)",
emoji: "💄",
value: "style",
},
test: {
description: "Test code",
emoji: "💍",
value: "test",
},
// Added for personal use
package: {
description: "Package",
emoji: "📦",
value: "package",
},
config: {
description: "Configuration file",
emoji: "⚙",
value: "config",
},
WIP: {
description: "Work in progress",
emoji: "🚧",
value: "WIP",
},
},
messages: {
type: "Select prefix:",
subject: "Enter commit title (summary) (optional):\n",
body: "Enter detailed description of changes (optional):\n",
breaking: "Enter breaking changes (optional):\n",
issues: "Enter related issues (optional), e.g. #123:",
},
};
Making Git Management Easy (Lazygit)
We will use the TUI tool lazygit, which makes Git management easy.

It comes in very handy when you want to easily split or fix commits!
You can display the list of keybindings with ?. Even if you can't remember Git commands, let alone Lazygit operations, you're in safe hands.

It can be used in both the terminal and Neovim.
You can easily stage, commit, and push files as shown below.

Installing Lazygit
brew install jesseduffield/lazygit/lazygit
Since typing lazygit every time is a bit of a hassle, it's convenient to set up an alias.
abbr -S lg='lazygit' >>/dev/null
Common operations in Lazygit
Stashing files before committing (Stash)
-
Stash all differences
s
-
Stash only staged files
- Stage files with
Spacekey - Stash the staged files with
S→s
- Stage files with
-
Reflect Stash to the stage
- Select the Stash window and select the Stash you want to reflect with
Space - The stashed content will be reflected
- Select the Stash window and select the Stash you want to reflect with
The following gif shows staging a stash and reflecting it.

Fixing forgotten changes (git commit --amend)
You can add staged files to the previous commit with A.

Editing commit messages
Move the cursor to the commit message you want to edit and press r to edit it.

You can now fix commit messages! 🙌
- Forgot the emoji & messed up the commit message 😭
Changing the content of a commit (fixup)
If you want to modify a specific commit, follow these steps:
- Stage the content you want to add to the commit
- Move the cursor to the target commit and press
F(a fixup commit is created) - Move the cursor to the target commit again and press
S(auto squash)
If you are not sure what fixup is, please refer to the following article.
Undoing changes after staging (restore --staged)
You can also cancel changes after staging.
- Move the cursor to the file you want to return to its staged state
-
d→u

Moving commits to another branch (cherry-pick)
I often commit to the wrong branch 😭
If you have committed to the wrong branch, you can move the commit to another branch using the following steps:
- Move to the branch you committed to by mistake with
Spacekey - Move the cursor to the commit you want to move and press
C - Move to the branch you want to bring the commit to with
Spacekey - Press
Vto paste the commit

Using git-cz from Lazygit
The Lazygit configuration file is at ~/.config/lazygit/config.yml.
I have configured it as follows so that I can execute git cz with C.
# 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 # delta needs to be installed to use this setting
Also, I use delta to make the diff display easier to read.
brew install git-delta
Getting Back to the Project Root Smartly
Finally, let's solve this.
- A life of repeatedly typing
cd ../to get back to the project root...
Getting Back to the Project Root
Actually, the git command has a useful command called git rev-parse --show-toplevel.
If you set this as an alias as follows, you can move to the project root with proot.
abbr -S proot='cd $(git rev-parse --show-toplevel)' >>/dev/null
or
alias proot='cd $(git rev-parse --show-toplevel)'
Going Back to the Previous Directory
You can return to the previous directory with cd -.
If you moved from the project root, you can return to the project root with cd - as well.
Normally, it might be good to switch between cd - to return and proot if cd - doesn't get you back.
Additionally, adding the following option to your zsh configuration file will allow you to change directories without typing cd.
setopt auto_cd
However, in the case of cd -, you cannot return to the previous directory with just -.
If you want to move with just -, you need to set an alias like the following:
abbr -S -qq -='cd -'
You no longer need to repeat ../ anymore! 🎵
- A life of repeatedly typing
cd ../to get back to the project root...
git-cz and cz-git (Updated on 12/6)
Preparing .gitignore Smartly (gibo)
gibo is a CLI tool for creating .gitignore templates.
The name seems to come from gitignore boilerplates.
You can check the list of available templates with gibo list.
You can create a .gitignore using gibo dump [template name].
I use a function like the one below:
alias gia='create_gitignore'
# Create .gitignore with gibo
create_gitignore() {
local input_file="$1"
# If no argument, add to .gitignore
if [[ -z "$input_file" ]]; then
input_file=".gitignore"
fi
# Select template
local selected=$(gibo list | fzf \
--multi \
--preview "gibo dump {} | bat --style=numbers --color=always --paging=never")
# Exit if nothing is selected
if [[ -z "$selected" ]]; then
echo "No templates selected. Exiting."
return
fi
# Add selected templates to the specified file
echo "$selected" | xargs gibo dump >> "$input_file"
# Display the resulting file with bat
bat "$input_file"
}
You can specify multiple templates with Tab to create a .gitignore like this:

Conclusion
I hope this makes your CLI life even a little more comfortable.
Day 5 of the Advent Calendar is ucan's article "History and Evolution of JavaScript Build Tools."
As a tool enthusiast, it's a topic I can't take my eyes off.
Please look forward to tomorrow too! 🎄
Also, thank you for the comments on Zenn and Twitter! I'm very happy to be able to update my own knowledge.
Discussion
こんにちは、自分もgit-czを使っていましたが、最近はcz-git(czg) の方を利用しています。
主な機能差分は以下にまとめられています。(実際そこまで大きな差はない気がしていますが)
FYI程度でした。よければ見てみてください。
情報いただきありがとうございます!OSSを見たり試したりするのが好きなので教えていただけて嬉しいです!
👀軽量化されていてプロジェクトへの導入のハードルも下がりますね...!
日曜日くらいに使い倒してみます!
これでabbrの標準出力を出さないようにしてますが、
--quieterオプションをつけると同じことができるので是非。おお!!この書き方見やすくて最高にクールですね!
自分の設定ファイルが
>>/dev/nullだらけで見づらいな〜と思っていたので助かります😭本文にも追記させていただきます!もし問題等あれば教えていただけますと幸いです。🙏
記事ありがとうございます!よくまとまっててターミナル好きの自分にとても参考になりました。
ご参考までに、MacOSにおいては設定ファイルのパスが違うようなのでもしMac前提で書かれているなら変更したほうがいいかもしれません。
コメントいただきありがとうございます!
Macのデオフォルトの設定ファイルのパスを知らなかったです😳
記事の方にも説明を追記させていただきました。
おかげさまで設定ファイルのパスの知識をアップデートできました!\(^^)/
いつもためになる記事をありがとうございます!
冒頭の「ghqでgit管理しているプロジェクト一覧を取得し、fzfで選択してプロジェクトディレクトリへ移動」するためのスクリプトで紹介されてるものだと、
cdが子プロセスで実行されるため、親プロセスでディレクトリの移動ができなさそうです。下記のスクリプトで同じことができましたので、共有です!
cd $(ghq list -p | fzf)おわ~~~本当ですね!!めっちゃミスってました!!
教えていただきありがとうございます!!!