git started
Fill these in once. Every command below rewrites itself with your details, so you can copy and run without editing anything. Saved in this browser only.

git started

Commands only. The explanations happen in the room. Keep this on half your screen, terminal on the other.
Do this first Hit Your details above and type your GitHub username. Every command on this page fills itself in, so you can copy and run without editing.

1  Your own repo

Local git, then push it to your profile.
1

Make a folder, turn it into a repo

ls -a to see .git. That folder is the repo.

2

Write something, look at it through git

Says untracked. Git sees it but is not watching it yet.

3

Stage it, commit it

Do this twice more with different edits before moving on.

4

Log in to GitHub

GitHub.com → HTTPS → Yes to authenticate git → browser. That "Yes" is what stops password prompts later.

5

Push it to GitHub

FlagAnswers
--source=.this folder (omit for an empty repo)
--publicwho sees it (--private otherwise)
--pushupload now (omit to push later)
--remote=originthe short name you push to
--descriptionwhat it is

Flags go in any order. Only the repo name is positional.

6

See what got wired up

Bare git push works because --push set the upstream. Without it: git push -u origin main once.

2  Fork, branch, PR

Contribute to a repo you do not own. accelerate-muj/git-started
1

Try it the obvious way. It fails.

Permission denied. You got read, not write, so your work is stuck on your laptop. Now cd .. and delete that folder, or you will spend ten minutes typing into the wrong one.

2

Fork and clone in one

Fork is GitHub's File → Make a Copy. Must show your username on origin, and accelerate-muj on upstream.

3

If you forked with the web button instead

A remote is a long URL saved under a short name, like Mom in your phone. origin = your fork, you can push. upstream = ours, fetch only.

4

Sync, then branch

"Already up to date" is a fine answer. The * in git branch confirms where you are. Modern equivalent: git switch -c add-{{user}}.

5

Make your file, then sign it

Filename must be your GitHub username. Open it, write your version of Sonnet 18 — modern English, Hindi, a parody, anything — and end it with Written by {{name}}.

Only this one file Do not sign phase-2/sonnet-18.md or edit anything else. One file per username is what stops thirty pull requests colliding. Shared files are Phase 3.
6

Look at what changed

The first git diff shows nothing. It only watches files git already tracks, and yours is brand new. After git add every line appears with a +, and + means addition.

7

Commit, then push to your fork

-u links this branch to that remote branch once, so from then on bare git push works. git add . needs the space; git add. fails.

8

Open the PR

FlagAnswers
--titlethe line shown in the PR list
--bodythe description under it
--filluse my last commit message for both
--draftunfinished, cannot merge yet
--reviewerask a specific person to look
--webfill the form in a browser instead
--repoforce the destination if gh guesses wrong

Because upstream is set, gh already knows the repo, the source branch and the destination. gh pr create --fill is the shortest version that works.

Push before you PR A pull request is a comparison between two branches that are already on GitHub, not an upload. The order is fixed: commit → push → PR.
9

After it merges

3  Teams and conflicts

Same repo, same file, everyone at once. No fork this time. Roughly 50 minutes, and the conflicts are the exercise rather than an accident.
Leader

Create the team repo

A template is not a fork. You get the files with a fresh history, one commit, and no link back to the original — what you want when starting from a skeleton rather than contributing to someone's project.

Pick a leader who owns the repo and merges the PRs. Not the best programmer in the group; it is an administrative job, and it is what maintainers of every open source project do all day.

Leader

Add each teammate

Start early, invites take time. Or Settings → Collaborators → Add people.

1

Accept the invite

Note the id, then:

gh repo accept is not a command It does not exist. Use the two above, or click the link on github.com/notifications. Until you accept, your push is rejected with a confusing permission error.
2

Clone and branch

No fork and no upstream this time. You push to origin directly because you are inside the project. That is the difference between working with colleagues and contributing as a stranger.

3

Edit the shared file

Open team-sonnet.md and do two things:

  1. Rewrite your assigned line of the sonnet. The leader hands out line numbers, or call them out around the table.
  2. Add your username to the Credits block at the bottom, on the line directly under the comment.
Everyone writes in the same place on purpose That second instruction is what guarantees the conflict. It is the whole exercise.
4

Commit, push, open the PR

No --repo now. Same repo, branch → main.

5

When GitHub says your branch has conflicts

Nothing has broken. The first PR merged cleanly and yours was built on a main that no longer exists. Somebody's name is sitting where you put yours, and git will not guess which of you should win.

6

Resolve it

## Credits <<<<<<< HEAD - @first-person-who-merged ======= - @you >>>>>>> Rewrite line 7, add my name to credits

Three parts. Above ======= is what is already on main; below it is what you are adding. The markers are plain text git inserted, nothing is watching them.

A conflict is not a question of who wins Almost always the answer is both. Keep both names, delete the three marker lines.

git add is how you say resolved. There is no separate resolve command, which surprises everybody. Panicking? git merge --abort puts everything back.

7

Review and merge each other

To send it back instead: gh pr review PR-NUMBER --request-changes --body "Line 7 does not scan"

One PR at a time After each merge the next person pulls main and fixes their conflict. Five at once and nobody can untangle it. Notice what merging keeps doing to your teammates — merge order is a decision with consequences for other people, and that is most of the job.
+

If you have time: rebase instead of merge

Merge keeps your branch as it happened and adds a joining commit; honest, and the graph tangles. Rebase replays your commits on top of the new main so history reads as one line. New commits, new hashes, which is why the push needs forcing. The rule most teams settle on: rebase your own unmerged branch, merge shared branches.

--force-with-lease, never plain --force They look interchangeable. --force overwrites the remote branch whatever is on it, so if a teammate pushed while you were resolving, you have silently destroyed their commit. --force-with-lease checks the remote is still where you last saw it and refuses if anyone touched it.
+

If you have time: branch protection

Now nobody can push straight to main, including the leader.

You should be able to answer What do <<<<<<<, ======= and >>>>>>> separate? Which command marks a conflict resolved? Why was your push rejected after a rebase? What does --force-with-lease check that --force does not? Your teammate merged first and your branch is stale — merge or rebase?

Help

What you seeFix
Permission denied on push, Phase 2 You cloned ours, not your fork:
git remote set-url origin https://github.com/{{user}}/git-started.git
Permission denied on push, Phase 3 Invite not accepted:
gh api user/repository_invitations then gh api -X PATCH user/repository_invitations/ID
'add.' is not a git command git add . with a space
unknown command "accept" for "gh repo" It does not exist. Use the invitations API, or accept in the browser.
fatal: not a git repository cd into the project folder. pwd shows where you are.
error: pathspec did not match Missing -c: git switch -c <branch> makes a new one, without it git looks for an existing one
git diff shows nothing, Phase 2 Correct. It only watches tracked files and yours is new. git add . then git diff --staged
PR opened against your own fork gh guessed wrong. Force it: --repo accelerate-muj/git-started
remote upstream already exists Harmless. Ignore it.
! [rejected] main -> main git pull origin main then push again
CONFLICT (content): Merge conflict in ... Expected in Phase 3. Keep both, delete markers, git add ., commit.
Leftover <<<<<<< in the file Search for <<< and delete every marker line
refusing to merge unrelated histories git pull origin main --allow-unrelated-histories
"There isn't anything to compare" You committed to main. Branch and push that instead.
gh pr merge fails PR still has conflicts. Author fixes first.
Password asked for and rejected gh auth login, say yes to the git credentials question
gh: command not found Close the terminal, open a new one
Stuck in an editor you cannot exit It is vim. Esc then :wq then Enter.
Want to undo and start again git merge --abort. Nothing is lost.

Nothing matches? Run git status. It cannot break anything and it tells you where you are. Then put your hand up.

Phase 4 and onwards

Today stops here. The handbook does not.
4
Undo →

Every way to take something back, and the only two commands that genuinely destroy work.

Start here. Most people are scared of git because they think a wrong command loses work. It almost never does.

The other twelve
5Rewriting historyInteractive rebase, squashing, splitting a commit.
6Forensicsbisect finding what broke the build while you make tea.
7Merging deeplyWhat today's conflict actually was.
8Remotes, big reposRefspecs, worktrees, submodules, LFS.
9PlumbingInside .git. The one where it clicks.
10TrustAnyone can commit under your name. Signing.
11Config, automationAliases, attributes, hooks.
12GitHub as a platformEverything that is not git.
13gh CLI in fullThe whole surface, plus gh api.
14Actions and CI/CDMaking the repo do the work.
15Being a maintainerReviewing, triage, saying no, burnout.
16Scale and originsTen days in 2005, and why git is shaped like this.