Skip to content

4. Working with GitHub

Beginner → Intermediate · 14 min read

Git works entirely on your machine. GitHub is a hosting service for Git repositories, plus everything a team needs around them: pull requests, code review, issues, CI with Actions, releases. Your laptop and GitHub each hold a full copy of the repository, and you sync them with push and fetch.

To show real output, the "GitHub" on this page is a local bare repository standing in for github.com/asha-rao/chat-app, with two developers, Asha and Ravi, each with their own clone. The commands are identical against real GitHub.

4.1 Authenticate once

GitHub doesn't accept your account password for Git. Pick one of these:

gh auth login            # choose GitHub.com → HTTPS → "Login with a web browser"
gh auth status

The GitHub CLI stores a token and configures Git to use it. You'll want gh anyway for pull requests (4.6).

ssh-keygen -t ed25519 -C "asha@example.com"     # press Enter to accept the default path
cat ~/.ssh/id_ed25519.pub                       # paste into GitHub → Settings → SSH and GPG keys
ssh -T git@github.com                           # "Hi asha-rao! You've successfully authenticated"

Then use git@github.com:asha-rao/chat-app.git URLs instead of https://....

GitHub → Settings → Developer settings → Fine-grained tokens, scoped to the repositories you need. Paste it when Git asks for a password; Git Credential Manager (installed with Git for Windows) remembers it.

4.2 Push an existing project

Create an empty repository on GitHub (gh repo create chat-app --private --source=. --push does it all in one command), or connect an existing one:

git remote add origin https://github.com/asha-rao/chat-app.git
git remote -v
git push -u origin main
git status -sb
Output
origin  https://github.com/asha-rao/chat-app.git (fetch)
origin  https://github.com/asha-rao/chat-app.git (push)
branch 'main' set up to track 'origin/main'.
To https://github.com/asha-rao/chat-app.git
 * [new branch]      main -> main
## main...origin/main
  • origin is just the conventional name for "the remote I cloned from / push to". A repo can have several.
  • -u (upstream) links your local main to origin/main, so later a plain git push and git pull know where to go, and git status can tell you if you're ahead or behind.
  • origin/main is a remote-tracking branch: your local, read-only bookmark of where main was on GitHub the last time you talked to it.

4.3 Clone

Ravi gets his own full copy, history included:

git clone https://github.com/asha-rao/chat-app.git
Output
Cloning into 'chat-app'...
done.

Clone sets up origin and the tracking branch automatically. For big repositories, git clone --depth 1 fetches only the latest snapshot (fine for CI and quick experiments).

4.4 Fetch vs pull, and the rejected push

Ravi pushes a commit. Meanwhile Asha commits a README and tries to push:

git push
Output
To https://github.com/asha-rao/chat-app.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/asha-rao/chat-app.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

GitHub refuses because accepting Asha's push would throw away Ravi's commit. First, look before you leap:

git fetch                      # download new commits; changes nothing in your files or branches
git status -sb
git log --oneline --graph --all
Output
From https://github.com/asha-rao/chat-app
   620a8dc..8c90f6a  main       -> origin/main
## main...origin/main [ahead 1, behind 1]
* b267a28 Add README
| * 8c90f6a Add temperature
|/  
* 620a8dc Add app

"Ahead 1, behind 1": the histories have diverged. Now integrate Ravi's commit. pull is fetch + merge (or rebase); with --rebase Asha's local commit is replayed on top of Ravi's, keeping history linear:

git pull --rebase
git log --oneline --graph --all
git push
Output
Successfully rebased and updated refs/heads/main.
* 6a566ee Add README
* 8c90f6a Add temperature
* 620a8dc Add app
To https://github.com/asha-rao/chat-app.git
   8c90f6a..6a566ee  main -> main
Command Downloads Changes your branch Use it when
git fetch Yes No You want to see what changed first
git pull Yes Yes: merges, creating merge commits on divergence Your team prefers merge commits
git pull --rebase Yes Yes: replays your local commits on top Most of the time (set pull.rebase true)

Rebasing here is safe: the commits being replayed are your own, not yet pushed (the golden rule from page 2).

4.5 Forks and upstream

For open-source projects (or repositories you can't push to), you fork: GitHub copies the repository to your account. You push to your fork and open a pull request back to the original.

gh repo fork some-org/rag-toolkit --clone        # fork on GitHub and clone your fork
git remote -v                                     # origin = your fork, upstream = the original
git fetch upstream
git switch -c fix/typo-in-docs upstream/main      # branch from the latest original
# ...fix, commit...
git push -u origin fix/typo-in-docs
gh pr create --repo some-org/rag-toolkit

Keep the fork's main branch in sync with git fetch upstream and git rebase upstream/main (or the "Sync fork" button on GitHub).

4.6 Pull requests from the terminal

A pull request (PR) asks to merge one branch into another, with a place for review, discussion and CI checks. The daily loop with gh:

git switch -c feature/streaming
# ...commit work...
git push -u origin feature/streaming
gh pr create --fill                     # title and body from your commits; --draft for work in progress
gh pr checks --watch                    # wait for CI
gh pr view --web                        # open it in the browser
gh pr checkout 42                       # review someone else's PR locally
gh pr review 42 --approve               # or --request-changes -b "..."
gh pr merge 42 --squash --delete-branch

Good PRs are small (under ~400 changed lines), do one thing, and explain why in the description, plus how to test it. For AI projects, include example prompts and outputs or eval scores before and after.

4.7 What else GitHub gives you

Feature What it's for in a GenAI project
Issues and Projects Track bugs, prompt regressions and experiments
Actions CI: lint, tests and evals on every PR; deployments (page 6)
Secrets (repo / environment) API keys for CI, never in the code
Push protection & secret scanning Blocks pushes containing known key formats (OpenAI, Anthropic, AWS…)
Dependabot PRs that update vulnerable dependencies
Releases Tagged versions with notes and build artifacts
Pages Free hosting for docs and static sites
Codespaces A cloud dev environment from the repo's devcontainer

Interview questions

What's the difference between git fetch and git pull?

fetch downloads new commits and updates remote-tracking branches like origin/main without touching your working tree or local branches. pull is fetch followed by integrating origin/main into your branch, by merge or (with --rebase) by replaying your local commits on top.

Your push was rejected with 'fetch first'. What happened and what do you do?

Someone pushed commits you don't have, so your push would overwrite them. Fetch, look at what changed, then integrate with git pull --rebase (or merge), resolve any conflicts, run the tests and push again. Don't force-push to a shared branch.

What is origin/main?

A remote-tracking branch: your local, read-only record of where main was on the origin remote at the last fetch. git status compares your branch to it to report ahead/behind, and it only updates when you fetch, pull or push.

Fork vs clone vs branch?

A clone is a full local copy of a repository. A branch is a line of work inside one repository. A fork is a server-side copy of someone else's repository under your account, used when you can't push to the original; you push to your fork and open a pull request upstream.

Practice

  • Create a private repository with gh repo create, push a project and open a PR from a branch.
  • Simulate two developers with two clones in different folders and reproduce the rejected push.
  • Fork an open-source GenAI project, fix a typo in its docs and open a pull request.

Next: 5. Team workflows Back to: Git & GitHub overview · Notes overview