Git & GitHub Basics: Useful CLI Patterns
Tags: cli, github, git, beginners
Published: 2023-07-24 20:57:55

**TLDR: You can skip to the bottom of the article for cheatsheets of the terminology and the commands I used with all their meanings.**

This blog will be more of a reference to common patterns I use on the Command Line Interface (CLI). I use Git CLI and GitHub CLI so if you see **gh** instead of **git** that means it is a GitHub command.

## Installing GitHub CLI
I would recommend [installing the GitHub CLI](https://github.com/cli/cli#installation) which you can do on Linux as follows (sorry it is long):
```
type -p curl >/dev/null || (sudo apt update && sudo apt install curl -y)
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
&& sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& sudo apt update \
&& sudo apt install gh -y
```

Apparently, this script makes sure that curl is available, downloads a GitHub CLI archive keyring, sets the necessary permissions, adds the GitHub CLI repository configuration, updates package lists, and then installs the GitHub CLI package -simple!

Once you have that installed, you may not need to use it often but it will offer real quality of life improvements when interacting with GitHub. Find out more [here](https://docs.github.com/en/github-cli/github-cli).

Now that we have that sorted, let's get into some common use cases and patterns you might find useful!

## Starting from a Local Repository
If you are using a getting started guide or tutorial, there is a good chance you might be starting on your local machine from scratch using something like [create-next-app](https://nextjs.org/docs/getting-started/installation) or [create vite](https://vitejs.dev/guide/#scaffolding-your-first-vite-project) (both excellent options in my opinion).

1.  Use your create command e.g. `npx create-next-app@latest new-app`
2. Launch a VSCode window for the new directory e.g. `code new-app`
3. Initialise the repository using git: `git init`
4. Create the repository on GitHub:
Once you have completed these steps, you will have a Git repo on your local machine but you will most likely want to hook it up to GitHub which you can do using the GitHub CLI. If it is your first time using the CLI you will need to login:

```
gh auth login
```
If you are already logged in, you can create a remote copy of you git repository on GitHub using:

```
gh repo create
```
You will then be given series of prompts to interact with, for example:
- ? **What would you like to do?** Push an existing local repository to GitHub
- ? **Path to local repository** .
- ? **Repository name** my-app
- ? **Description** testing
- ? **Visibility** Public
- ✓ **Created repository** USERNAME/my-app **on GitHub**
- ? **Add a remote?** Yes
- ? **What should the new remote be called?** origin
- ✓ **Added remote** `https://github.com/USERNAME/my-app.git`

N.B. The dot `.` for **Path to local repository** means **use current directory**- assuming you are in the directory of the repo you wish to add to GitHub.

I really like this method because it is very ergonomic and gives you confidence that you are doing what you intended to do, with helpful confirmations each time it performs an action on your GitHub account.

5. After you have setup your local repo and create a remote on GitHub, it is time for your first commit:
```
git add .
git commit . -m "Initial Commit"
git push -u origin main
```
The above commands:
- Add / Stage all files to be committed
- Commit all the files
- Push the commit and setup a link between the main branch on the local repo and the same on the remote (GitHub)

You should only need to set the upstream branch once and then subsequent pushes can be done simply using `git push`.

## Starting from a Remote Repository
If you are not starting a project locally, you are probably starting remotely. This could mean that you just [forked a repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo) on GitHub or you just [created a repo](https://docs.github.com/en/get-started/quickstart/create-a-repo?tool=webui) on GitHub using their guided process.

1. Navigate to the **Code** section of your repo and find the **GitHub CLI** command:
```
gh repo clone USERNAME/my-app
```
2. Enter that into your terminal and then use `code my-app` to open it in VSCode.
3. Once in the repo and in VSCode you will want to use `npm i` to install any dependencies. 

N.B. If your project is using [Husky](https://typicode.github.io/husky/getting-started.html) you may need to add `npx husky install` to enable the hooks.

4. Once you have made some sort of change, you can push to the remote using:
```
git commit . -m "My Message"
git push
```
## Resuming Work on a Shared Repository
If you are going back to work on a shared repository with no local changes it is a good idea to pull any changes from the remote before you get going so you make sure you are working starting with the latest version of the repo:
```
git pull
```
## Start Working on a Feature Branch
Once you have your local and remote repo working together in harmony, you may want to muddy the waters by creating a new branch or feature branch. 

One benefit of having a feature branch is that you can experiment without taking down your running application, usually deployed from your main branch. 

Another benefit is that, if you do not have push access for the main branch, you can make a feature branch and push to that to your hearts' delight and before making a pull request on GitHub to have the feature branch merged in.

To create a branch called `new-feature` and start working on it, you can use one of the following methods:
### Copy branch to a new branch and then switch to it
```
git branch -c new-feature
git switch new-feature
```
### Create and checkout a new branch
```
git checkout -b new-feature
```
### Create and switch to a new branch
```
git switch -c new-feature
```
Basically, the `-c` flag is for **copy** or **create** and the `-b` flag is for **branch** but the effects of all these commands are eerily similar. **You will end up in your new branch within your editor.**

Next, you will want to push your newly created branch to a corresponding branch on the remote (GitHub). Again, there is more than one way to do this:
### By naming the branch
This works with or without the -u (set upstream) flag
```
git push -u origin new-feature
```
>The `-u` flag is useful if you want to make further pushes after using `git push` as it will set up tracking for you.
```
git push origin new-feature
```
### Using the currently checked out branch (HEAD)
```
git push origin HEAD
```
## Finish Working on a Feature Branch

### Create a Pull Request
After you have finished your feature you can go to GitHub and create a pull request or you can use **GitHub CLI**:

```
gh pr create
```
This will give you some prompts:
- ? **Title** My First Pull Request
- ? **Body** <Received>
- ? **What's next?** Submit

### Delete the branch
Deleting branches can be dangerous so always be sure. Luckily, git will stop you from deleting the branch you are on, so if you switch to the main branch, you will not be able to accidentally delete it. To delete branch `new-feature` from the local machine and GitHub (origin) do this:
```
git switch main
git branch -d new-feature
git push origin -d new-feature
```
These commands:
- Switch to the main branch
- Delete the local copy of the `new-feature` branch
- Delete the origin (or remote) copy of the `new-feature` branch using the `-d` delete flag

**N.B. You can also delete upstream branches using a `:` colon prefix e.g.:**
```
git push origin :new-feature
```
 
### CheatSheets
#### Git Terms
- **repo / repository** - Git / Code Directory
- **branch** - Copy of a Repository that can be independently worked on
- **HEAD** - Current Working Branch
- **origin** - Remote repository e.g. GitHub
- **commit** - A saved version of a Git that includes a message and information about what changed
- **ref** - A file containing commit information
- **pull request** - Ask someone to pull changes from your branch into another branch e.g. main

#### Git Actions
- **checkout** - Start working on a branch
- **switch** - Switch to a different branch
- **pull** - Pull any changes from one branch or place (e.g. Remote / Local) to another
- **push** - Push your changes to another place or branch
- **add** - Add a file to the observed files so Git can track its changes
- **commit** - Add file changes to a new commit that can be pushed to a branch

#### Commands
- `gh auth login` - Login to GitHub
- `gh repo create` - Create a new remote repo on GitHub
- `gh repo clone USERNAME/my-app` - Create a local clone of the 'my-app' repo from GitHub
- `gh pr create` - Create a pull request for the current branch
- `git add .` - Add all files for Git tracking
- `git commit . -m "Initial Commit"` - Commit All files with a message of "Initial Commit"
- `git push -u origin main` - Set upstream for 'main' branch to same named branch on origin (GitHub)
- `git push` - Push the current branch to origin (GitHub)
- `git pull` - Fetch any changes for the current repo and branch from origin (GitHub)
- `git branch -c new-feature` - Copy current branch to a new branch called 'new-feature'
- `git switch new-feature` - Switch to branch called 'new-feature'
- `git checkout -b new-feature` - Create and checkout a new branch called 'new-feature'
- `git switch -c new-feature` - Create and switch to a new branch called 'new-feature'
- `git push origin new-feature` - Push 'new-feature' branch to origin and create if not present
- `git push origin HEAD` - Push current (HEAD) branch to origin and create if not present
- `git branch -d new-feature` - Delete the 'new-feature' branch locally
- `git push origin -d new-feature` - Delete the 'new-feature' branch on remote / origin / GitHub
- `git push origin :new-feature` - Delete the 'new-feature' branch on remote / origin / GitHub