reference · git 2.4x · gh cli

Everything a developer needs to know about Git & GitHub

Git is the version control tool that runs on your machine. GitHub is a service built around it — hosting, pull requests, issues, and automation. This guide covers both: the commands you'll type daily, the workflow teams actually use, and what to do when something breaks.

01 Setup & identity

One-time configuration after installing Git or moving to a new machine.

IdentityTell Git who you are

$ git config --global user.name "Ada Lovelace"
$ git config --global user.email "ada@example.com"
$ git config --global init.defaultBranch main
$ git config --global core.editor "code --wait"
$ git config --list                  # see everything currently set

AuthenticationConnect to GitHub over SSH

$ ssh-keygen -t ed25519 -C "ada@example.com"
$ eval "$(ssh-agent -s)"
$ ssh-add ~/.ssh/id_ed25519
# paste ~/.ssh/id_ed25519.pub into GitHub → Settings → SSH and GPG keys
$ ssh -T git@github.com          # verify — should greet you by username
Note HTTPS remotes work too, but GitHub no longer accepts your account password — use a gh auth login (below) or a personal access token as the password.

SigningVerified commits (optional)

$ git config --global commit.gpgsign true
$ git config --global user.signingkey <KEY-ID>

02 Core workflow

The loop you repeat dozens of times a day: change files, stage, commit, sync.

CommandWhat it does
git initTurn the current folder into a Git repository.
git clone <url>Copy a remote repository, including its full history, to your machine.
git statusShow what's changed, staged, and untracked.
git add <file>Stage a file's changes for the next commit.
git add -pStage interactively, chunk by chunk — the safer default for mixed changes.
git commit -m "…"Save staged changes as a snapshot in history.
git commit --amendFold new changes into the last commit instead of making a new one.
git pushSend local commits to the remote.
git pullFetch and merge the remote's new commits into your branch.

ExampleFirst push of a new branch

$ git switch -c feature/search-filter
$ git add .
$ git commit -m "Add category filter to search"
$ git push -u origin feature/search-filter   # -u links local ↔ remote branch

03 Branching & merging

Branches are just movable pointers to commits — cheap to make, cheap to throw away.

git branch

List, create, or delete branches. git branch -d name deletes safely; -D forces it.

git switch <branch>

Move to an existing branch. git switch -c name creates and moves in one step.

git merge <branch>

Bring another branch's commits into the current one, preserving both histories.

git rebase <branch>

Replay your commits on top of another branch — linear history, no merge commit.

Merge vs. rebaseWhen to use which

Merge preserves exactly what happened, including a merge commit — good for shared branches like main. Rebase rewrites your commits onto a new base — good for tidying a feature branch before opening a PR. Never rebase a branch other people have already pulled from.

$ git switch main && git pull
$ git switch feature/search-filter
$ git rebase main                 # replay feature commits on latest main
$ git rebase -i HEAD~3            # interactively squash/reorder the last 3 commits

Resolving a conflictWhat the markers mean

<<<<<<< HEAD
const timeout = 3000;
=======
const timeout = 5000;
>>>>>>> feature/search-filter

Edit the file down to the version you want, delete the marker lines, then:

$ git add path/to/file.js
$ git commit                      # finishes a merge
# — or, mid-rebase —
$ git rebase --continue

Cherry-pickTake one commit without the rest of a branch

$ git cherry-pick a1b2c3d

04 Remotes & syncing

A remote is just a named URL. origin is convention, not magic.

$ git remote -v                              # list remotes and their URLs
$ git remote add origin git@github.com:you/repo.git
$ git remote set-url origin <new-url>         # fix a typo'd or migrated URL
$ git fetch --all --prune                     # update refs, drop deleted remote branches
$ git push origin --delete old-feature         # delete a remote branch
$ git branch --set-upstream-to=origin/main main # fix "no tracking branch"
Fetch vs. pull git fetch downloads new commits but doesn't touch your working files. git pull is fetch + merge (or --rebase) in one step. When in doubt, fetch first and look before merging.

05 Undoing things

Git rarely deletes anything permanently — but a few commands get close. Know which is which.

CommandUndoesRisk
git restore <file>Uncommitted edits to a file, back to last commit.Local edits lost
git restore --staged <file>Unstages a file; edits are kept.None
git reset --soft HEAD~1Undoes the last commit; changes stay staged.Low
git reset --hard HEAD~1Undoes the last commit and all working changes.High — data loss
git revert <commit>Adds a new commit that undoes an old one — safe on shared branches.None
git clean -fdDeletes untracked files and folders.High — data loss
Danger zone reset --hard and clean -fd destroy uncommitted work with no confirmation. Run git status first, and consider git stash instead if you might want those changes back.

StashShelve work-in-progress without committing

$ git stash                    # shelve tracked changes
$ git stash -u                 # include untracked files too
$ git stash list
$ git stash pop                # reapply the most recent stash and drop it
$ git stash apply stash@{1}    # reapply a specific one, keep it in the list

ReflogThe safety net for "I think I lost a commit"

$ git reflog                   # every place HEAD has pointed, even after reset --hard
$ git reset --hard HEAD@{2}    # jump back to a prior state

06 Inspecting history

$ git log --oneline --graph --all    # the shape of the whole repo at a glance
$ git log -p -- path/to/file.js       # full diff history of one file
$ git diff                            # working tree vs. last commit
$ git diff --staged                   # staged changes vs. last commit
$ git show a1b2c3d                    # everything in one commit
$ git blame path/to/file.js           # who last touched each line, and when
$ git bisect start
$ git bisect bad                      # current commit is broken
$ git bisect good v1.2.0               # this old tag was fine — binary-search the regression

Reading a diff

diff --git a/src/config.js b/src/config.js
@@ -12,7 +12,7 @@ export const settings = {
-  timeout: 3000,
+  timeout: 5000,
   retries: 3,
 };

07 Fork & pull-request workflow

How contributions actually travel on GitHub, whether it's your own team's repo or an open-source project you don't have write access to.

  1. Fork the repository on GitHub (skip this if you already have write access — branch directly instead).
  2. git clone git@github.com:you/repo.git — clone your fork.
  3. git remote add upstream git@github.com:original-owner/repo.git — track the source.
  4. git fetch upstream && git rebase upstream/main — start from the latest.
  5. Create a feature branch, commit your work, git push origin feature/my-change.
  6. Open a pull request on GitHub, targeting the upstream repo's default branch.
  7. Address review comments with more commits (or an amend + force-push), then it gets merged.
Keeping a fork current upstream is the original repo, origin is your fork. Rebasing onto upstream/main before opening a PR avoids conflicts caused by staleness rather than real disagreement.

08 GitHub CLI — gh

Everything above the Git layer — issues, PRs, Actions — from the terminal instead of the browser.

$ gh auth login                         # one-time browser or token auth
$ gh repo clone owner/repo
$ gh repo create my-project --public --source=. --push
$ gh pr create --title "Add search filter" --body "Closes #42"
$ gh pr list --state open
$ gh pr view 42 --web                   # open it in the browser
$ gh pr checkout 42                     # pull someone else's PR branch locally
$ gh pr merge 42 --squash --delete-branch
$ gh issue create --title "Bug: filter resets on refresh"
$ gh issue list --label bug
$ gh workflow list
$ gh run watch                         # tail the currently running Actions job
$ gh gist create notes.md --public

09 Repo files & conventions

Files GitHub recognizes by name and gives special treatment.

FilePurpose
.gitignorePatterns for files Git should never track (build output, secrets, node_modules/).
README.mdRendered on the repo's homepage — what it is, how to run it.
LICENSELegal terms for reuse; GitHub detects and labels common ones automatically.
CONTRIBUTING.mdLinked automatically when someone opens an issue or PR.
CODEOWNERSMaps paths to reviewers; auto-requests review on matching PRs.
.github/ISSUE_TEMPLATE/Structured forms shown when someone opens a new issue.
.github/PULL_REQUEST_TEMPLATE.mdPre-fills the PR description box.
.github/workflows/*.ymlGitHub Actions pipelines — see below.

10 GitHub Actions, minimally

A workflow file that runs tests on every push and pull request.

# .github/workflows/ci.yml
name: CI
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npm test

Commit it under .github/workflows/ and GitHub picks it up automatically — check progress under the repo's Actions tab, or with gh run watch.

11 Commit & PR etiquette

The habits that make a shared history and review queue pleasant to work in.

Commit messagesConventional prefixes

PrefixUse for
feat:A new feature.
fix:A bug fix.
docs:Documentation only.
refactor:Code change that isn't a fix or a feature.
test:Adding or correcting tests.
chore:Build, tooling, dependency upkeep.

Branch names

feature/search-filter
fix/login-redirect-loop
chore/bump-eslint

Opening a PRWhat makes one easy to review

  • Small and focused — one concern per PR, not a week of unrelated changes.
  • Descriptive title, and Closes #42 in the body to auto-link and close the issue on merge.
  • Explain why, not just what — the diff already shows what changed.
  • Once review has started, prefer new commits over force-pushing so reviewers can see what changed since their last pass.
Branch protection Most teams require passing checks and at least one approval before main accepts a merge, and block direct pushes to it entirely. Set this under the repo's Settings → Branches.

12 Troubleshooting

Errorfatal: not a git repository

You're outside a repo, or above its root. cd into the project, or run git init if it's genuinely new.

ErrorPermission denied (publickey)

GitHub doesn't recognize your SSH key. Confirm it's added under Settings → SSH and GPG keys, then re-test:

$ ssh -T git@github.com

SituationCommitted to the wrong branch

$ git branch rescue-branch      # save a pointer to this commit
$ git reset --hard HEAD~1        # remove it from the current branch
$ git switch rescue-branch       # continue where you meant to be

SituationStuck in a detached HEAD

You checked out a commit or tag directly instead of a branch. Any new commits here aren't on a branch and can be orphaned. Save them with:

$ git switch -c rescued-work

SituationLocal and remote branches have diverged

$ git pull --rebase     # replay your commits on top — usually the cleaner history
# or, to preserve exactly what happened on both sides:
$ git pull                # creates a merge commit

SituationPushed a large binary or a secret by accident

Deleting the file in a new commit isn't enough — it's still in history. Use git filter-repo or the BFG Repo-Cleaner to strip it from every commit, force-push, and — for secrets — rotate the credential regardless.

13 Full cheat sheet

Every command above, in one scannable table.

CommandDescription
git initCreate a new local repository
git clone <url>Copy a remote repository locally
git statusShow staged/unstaged/untracked changes
git add <file> / -p / .Stage changes
git commit -m "…"Record a snapshot of staged changes
git commit --amendEdit the previous commit
git push / -u origin <branch>Send commits to the remote
git pull / --rebaseFetch + merge (or rebase) remote commits
git fetch --all --pruneUpdate remote refs without merging
git branch / -d / -DList / delete a branch
git switch <branch> / -cChange branch / create and change
git merge <branch>Combine another branch into this one
git rebase <branch> / -iReplay commits on a new base / edit interactively
git cherry-pick <sha>Apply one specific commit here
git restore / --stagedDiscard working changes / unstage
git reset --soft/--hardMove HEAD, keeping or discarding changes
git revert <sha>Undo a commit with a new, safe commit
git stash / pop / listShelve and restore work-in-progress
git reflogHistory of every HEAD movement — the ultimate undo
git log --oneline --graphVisualize commit history
git diff / --stagedShow unstaged / staged changes
git blame <file>Show who last changed each line
git bisectBinary-search history for a regression
gh pr create / list / mergeManage pull requests from the terminal
gh issue create / listManage issues from the terminal
gh run watchTail a running Actions workflow