GitHub CLI Cheatsheet
Repos
Use this GitHub CLI reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Creating
gh repo create runs interactively with no arguments. With a name it needs a visibility flag.
gh repo create my-app --public gh repo create my-app --private --description "internal tool" gh repo create org-name/my-app --internal gh repo create my-app --public --clone # create, then clone locally gh repo create my-app --private --source=. --push # push the cwd's repo up gh repo create my-app --public --source=. --remote=upstream gh repo create my-app --template cli/gh-extension-precompile --public gh repo create my-app --public --gitignore Go --license mit --add-readme
| Flag | Effect |
|---|---|
--public / --private / --internal | Visibility, one is required non-interactively |
-s, --source <path> | Use an existing local repo as the source |
--push | Push local commits after creating, needs --source |
-c, --clone | Clone the new empty repo into the current directory |
-p, --template <repo> | Create from a template repository |
--include-all-branches | With --template, copy every branch, not just the default |
-r, --remote <name> | Remote name to add, defaults to origin |
-d, --description, -h, --homepage | Metadata |
-g, --gitignore, -l, --license | Template names, e.g. Node, mit |
--add-readme | Seed a README so the repo is not empty |
-t, --team <name> | Grant an org team access |
--disable-issues, --disable-wiki | Turn those features off at creation |
--source and --clone are mutually exclusive: one pushes an existing directory up, the other pulls a new empty repo down.
Cloning and Forking
The OWNER/REPO shorthand works everywhere a repo argument is accepted, and a bare REPO means your own.
gh repo clone cli/cli gh repo clone cli/cli ~/src/gh-cli gh repo clone my-repo # your own account gh repo clone github.example.com/team/app # enterprise host gh repo clone cli/cli -- --depth=1 # anything after -- goes to git gh repo clone cli/cli -- --recurse-submodules
Cloning a fork adds an upstream remote pointing at the parent automatically:
gh repo clone my-fork --upstream-remote-name parent
gh repo clone my-fork --no-upstream # skip the upstream remotegh repo fork # fork the current repo gh repo fork cli/cli --clone gh repo fork cli/cli --remote # add a git remote for the fork gh repo fork --remote --remote-name fork # name it 'fork', keep origin gh repo fork cli/cli --org my-org --fork-name cli-patched gh repo fork cli/cli --default-branch-only
--remote defaults the new remote to origin and renames the original to upstream. Pass --remote-name when you would rather keep origin pointing at the parent.
Viewing and Browsing
gh repo view # README plus metadata, in the terminal gh repo view cli/cli gh repo view cli/cli --web # open in a browser gh repo view cli/cli --branch trunk gh repo view cli/cli --json name,stargazerCount,defaultBranchRef gh repo view cli/cli --json description --jq .description
gh browse is the fast path to a URL, and -n prints instead of opening.
gh browse # repo home page gh browse 217 # issue or PR 217 gh browse cmd/gh/main.go # a file at the current branch gh browse main.go:312 # a file at a line gh browse main.go:312 --blame # blame view at that line gh browse main.go --branch bug-fix gh browse main.go --commit=77507cd gh browse --settings # -a actions, -r releases, -w wiki, -p projects gh browse -n -R cli/cli # print the URL only
main.go:312 is the form worth memorizing. It is how you hand a colleague a permalink to the exact line you are looking at.
Listing
gh repo list # your repos, 30 by default gh repo list cli --limit 100 gh repo list my-org --visibility private gh repo list my-org --language go --no-archived gh repo list my-org --topic infra --source # non-forks only gh repo list my-org --fork gh repo list my-org --json name,pushedAt --jq 'sort_by(.pushedAt) | reverse'
| Flag | Filter |
|---|---|
-L, --limit | Max results, default 30 |
--visibility | public, private, or internal |
-l, --language | Primary language |
--topic | One or more topics |
--source / --fork | Only non-forks / only forks |
--archived / --no-archived | Only archived / omit archived |
Editing Settings
gh repo edit changes repository settings without opening the web UI.
gh repo edit --description "a better description" --homepage https://example.com gh repo edit --add-topic cli --add-topic golang gh repo edit --remove-topic legacy gh repo edit --default-branch main gh repo edit --enable-issues=false --enable-wiki=false gh repo edit --enable-squash-merge --enable-merge-commit=false gh repo edit --enable-rebase-merge=false --delete-branch-on-merge gh repo edit --enable-auto-merge gh repo edit --squash-merge-commit-message pr-title-description gh repo edit --template # mark as a template repository gh repo edit --enable-secret-scanning gh repo edit cli/cli --visibility private \ --accept-visibility-change-consequences
Boolean flags take an explicit =false to turn a setting off. --visibility refuses to run without --accept-visibility-change-consequences, because making a repo private can detach forks and drop stars.
Default Repo and Syncing
In a directory with several remotes, gh asks which repo commands should target. Pin it once:
gh repo set-default cli/cli
gh repo set-default --view
gh repo set-default --unsetWithout a default set, every gh pr/gh issue call in a forked clone prompts. Setting it to the upstream is usually what you want, since that is where PRs and issues live.
gh repo sync # pull upstream into the local default branch gh repo sync --branch release-2.x gh repo sync my-fork # sync the remote fork from its parent gh repo sync my-fork --source cli/cli gh repo sync --force # hard reset, discards divergent commits
Without --force, gh repo sync refuses when the branches have diverged rather than clobbering work. With it, the destination branch is hard reset to the source.