Git and GitHub Blueprint - Free 3.5-Hour Course Companion (17 Chapters with Timestamps and the Commands for Each - Branching, Pull Requests, Reset, Amend, Cherry-Pick, Squash, Interactive Rebase, Bisect, Stash, Diff, Log, .gitignore, Merge Conflicts)


This is the companion page to my Git and GitHub blueprint - a free three-hour-twenty-minute course that starts at git init and ends with you rewriting history on purpose and resolving merge conflicts without sweating. Everything on this blog - Terraform, Ansible, Kubernetes manifests, this very site - lives in Git, and the course is the Git I wish somebody had taught me in my first job.

The video shows every command being typed; this page is the cheat sheet: for each of the 17 chapters the timestamp, the commands, the one thing to remember, and a link to the official Git reference page. At the end there is the part the video leaves implicit - the rules for when rewriting history is safe.

Table of Content

  1. Part 1 - Foundations
  2. Part 2 - Rewriting history
  3. Part 3 - Practices
  4. The safety net - reflog, revert, force-with-lease, and when rewriting is allowed
  5. The GitHub errors everybody hits
  6. Conclusion



Git and GitHub blueprint course map - foundations, rewriting history, practices, with one command per chapter

1. Part 1 - Foundations

Chapter 1 - What is GitHub, install and configure (0:00 - 0:14)

Git is the version control system on your machine - every commit, branch and diff happens locally, offline. GitHub is a hosting service for Git repositories plus the collaboration layer - pull requests, issues, actions, permissions. You can use Git without GitHub; you cannot use GitHub without Git.

 1# install
 2winget install Git.Git            # Windows (ships Git Bash)
 3brew install git                  # macOS
 4sudo apt install git              # Ubuntu / Debian
 5git --version
 6
 7# one-time global config (0:07:40)
 8git config --global user.name "Rahul Wagh"
 9git config --global user.email "rahul@jhooq.com"
10git config --global init.defaultBranch main
11git config --global core.editor "code --wait"
12git config --global pull.rebase false          # or true if your team rebases
13git config --global --list

Authenticate to GitHub with SSH keys (ssh-keygen -t ed25519, add the public key under Settings → SSH and GPG keys - the GitHub guide) or with a personal access token over HTTPS - passwords stopped working in 2021, which is the error in support for password authentication was removed.

Chapter 1b - First repository, clone, commit, push (0:09 - 0:20)

 1# new project (0:09:31)
 2mkdir jhooq-demo && cd jhooq-demo
 3git init
 4echo "# jhooq demo" > README.md
 5git status                                  # untracked
 6git add README.md                           # staging area
 7git commit -m "Initial commit"              # (0:14:50)
 8git remote add origin git@github.com:rahulwagh/jhooq-demo.git
 9git push -u origin main                     # -u sets the upstream once
10
11# existing project (0:12:23)
12git clone git@github.com:rahulwagh/jhooq-demo.git

Remember - three places: the working directory (your files), the staging area / index (git add), the repository (git commit). git status tells you where every file is. Reference: git-commit.


Chapter 2 - Branching (0:20:52)

A branch is a movable pointer to a commit - cheap, instant, and the unit of work on any team -

1git branch                                  # list, * marks current
2git switch -c feature/login                 # create and switch (older: git checkout -b)
3# ... edit, add, commit ...
4git switch main
5git merge feature/login                     # fast-forward if main did not move, else a merge commit
6git branch -d feature/login                 # delete merged branch (-D forces)
7git push origin --delete feature/login      # delete on GitHub
8git branch -a                               # local + remote-tracking branches

Remember - main is for finished work; everything else happens on a branch. Deleting a hundred stale merged branches at once is this script. Reference: git-branch, git-merge.



Chapter 3 - Pull requests (0:37:11)

A pull request (PR) is GitHub's "please merge my branch" - with a diff, a conversation, reviews, and automated checks -

1git switch -c feature/login
2git commit -am "Add login form"
3git push -u origin feature/login
4# GitHub shows "Compare & pull request" → title, description, reviewers → Create pull request
5# reviewer requests changes → you commit and push again, the PR updates
6# approved → Merge pull request (merge commit) | Squash and merge | Rebase and merge
7git switch main && git pull                 # get the merged result locally

Remember - small PRs get reviewed; 2,000-line PRs get rubber-stamped. Choose one merge strategy per repository: squash keeps main one-commit-per-feature, merge commit keeps full history, rebase keeps it linear. GitHub's docs: about pull requests.

Chapter 4 - Git in Visual Studio Code (0:47:25)

The Source Control view (Ctrl+Shift+G) stages, commits, pushes, pulls, switches branches and shows diffs inline - the same Git, with buttons. The chapter shows staging hunks (parts of a file), the three-way merge editor for conflicts, and the GitLens extension for blame and history. Reference: VS Code source control. Learn the commands first, then let the editor save you typing - when the UI does something odd, git status in the terminal explains it.


2. Part 2 - Rewriting history

The whole of Part 2 comes with one rule, so here it is up front: rewrite only commits that exist on your machine or your own branch. Once a commit is on main or on a branch somebody else has pulled, you add fixes (revert), you do not rewrite. Section 4 has the reasoning.

Chapter 5 - Reset (soft, mixed, hard)

git reset moves the current branch pointer to another commit and decides what happens to the staging area and working directory -

1git reset --soft HEAD~1    # undo the commit, keep changes STAGED      - "I committed too early"
2git reset --mixed HEAD~1   # undo the commit, keep changes UNSTAGED    - the default
3git reset --hard HEAD~1    # undo the commit AND throw the changes away - dangerous
4git reset --hard origin/main   # make local main identical to GitHub
5git reset HEAD file.txt    # unstage one file (keep the edit)

Remember - --hard deletes uncommitted work; before using it, git stash or make sure you can live without the changes. Committed work is recoverable via reflog. Reference: git-reset.

Chapter 6 - Amend (1:16:48)

1git commit --amend                     # fix the last commit message
2git add forgotten.txt
3git commit --amend --no-edit           # add a file to the last commit, keep the message

Remember - amend creates a new commit replacing the last one; if the old one was already pushed you now need --force-with-lease. Reference: git-commit.



Chapter 7 - Cherry-pick (1:22:42)

Copy one commit from another branch onto the current one - the classic hotfix move -

1git log --oneline hotfix                 # find the commit
2git switch release/2.4
3git cherry-pick a1b2c3d                  # apply it here as a new commit
4git cherry-pick a1b2c3d..f6e5d4c         # a range
5git cherry-pick --no-commit a1b2c3d      # apply, let me edit before committing

Remember - the copy has a new hash; if the two branches later merge, Git usually recognises the duplicate, but not always. Reference: git-cherry-pick.

Chapters 8, 9, 10 - Squash, reorder, drop with interactive rebase (1:30 - 1:47)

One tool does all three - interactive rebase - which replays your last N commits through an editor where you decide the fate of each -

1git rebase -i HEAD~4
1pick 1a2b3c4 Add login form
2squash 2b3c4d5 Fix typo in login form        # (1:30:18) fold into the previous commit
3pick 3c4d5e6 Add logout
4drop 4d5e6f7 Debug prints                     # (1:42:57) delete this commit entirely
5# reorder (1:39:33): move the lines - Git replays them in the new order
6# reword: keep the change, edit the message   # fixup: like squash but discard its message

Save and close; Git replays and asks for the combined message when squashing. Remember - this is how you turn "WIP, WIP, fix, fix, final" into one clean commit before opening the PR. If it goes wrong mid-way, git rebase --abort returns everything to how it was. Reference: git-rebase.

Chapter 11 - Exec (1:47:19)

Run a command after every replayed commit - the way to prove each commit in a series builds and passes tests -

1git rebase -i --exec "npm test" HEAD~4
2git rebase -i --exec "terraform validate" HEAD~3

The rebase stops at the first commit where the command fails, so you fix exactly that one. Remember - clean, individually-passing commits make bisect (next chapter) and code review far easier.

Chapter 12 - Bisect (1:50:48)

Something broke between last week and today and nobody knows which of the 60 commits did it. Bisect finds it by binary search -

 1git bisect start
 2git bisect bad                         # current commit is broken
 3git bisect good v2.3.0                 # this tag was fine
 4# Git checks out the middle commit - test it, then:
 5git bisect good    # or
 6git bisect bad
 7# ... about log2(60) ≈ 6 rounds later:
 8# "a1b2c3d is the first bad commit"
 9git bisect reset
10
11# fully automatic with a script that exits 0 for good, non-zero for bad
12git bisect start HEAD v2.3.0
13git bisect run ./test.sh

Remember - bisect is the single most under-used Git command; with run and a test script it finds a regression in a thousand commits in ten steps. Reference: git-bisect.



Chapter 13 - Stash (2:09:20)

You are mid-change and must switch branches now -

1git stash push -m "half-done login validation"     # save working dir + index, clean the tree
2git stash list
3git switch main && git pull && git switch -        # do the urgent thing, come back
4git stash pop                                      # re-apply and drop (apply keeps it in the list)
5git stash push -u                                  # include untracked files
6git stash show -p stash@{1}                        # peek at an older one
7git stash drop stash@{1}

Remember - stash is a stack; name your stashes or you will have five WIP on main entries and no idea which is which. Reference: git-stash.

Chapter 14 - Diff (2:29:58)

1git diff                          # working dir vs staging (unstaged changes)
2git diff --staged                 # staging vs last commit (what will be committed)
3git diff HEAD                     # working dir vs last commit (everything)
4git diff main..feature/login      # two branches
5git diff main...feature/login     # changes on the branch since it forked
6git diff a1b2c3d f6e5d4c -- src/app.py
7git diff --stat                   # file-level summary
8git diff --word-diff              # for prose and YAML

Remember - .. compares tips, ... compares against the merge base; the second is what a pull request shows. Reference: git-diff.


3. Part 3 - Practices

Chapter 15 - Log (2:46:17)

1git log --oneline --graph --all --decorate      # the picture of your branches
2git log -5 --stat                               # last five with files touched
3git log -p -- path/to/file                      # every change to one file, with diffs
4git log --author="Rahul" --since="2 weeks ago"
5git log -S "db_password"                        # commits that added/removed this string (pickaxe)
6git log --grep="JIRA-123"                       # by message
7git log main..feature/login                     # what the branch adds
8git shortlog -sn                                # commits per author
9git blame -L 10,20 app.py                       # who changed these lines

Set an alias once: git config --global alias.lg "log --oneline --graph --all --decorate". Reference: git-log.

Chapter 16 - .gitignore (3:00:42)

 1# .gitignore - patterns, one per line
 2node_modules/
 3__pycache__/
 4*.log
 5.env
 6.env.*
 7.terraform/
 8*.tfstate
 9*.tfstate.backup
10.vscode/
11.DS_Store
12!keep-this.log       # negation
1git rm --cached .env              # the file was already committed - stop tracking, keep on disk
2git check-ignore -v .env          # which rule ignores this file?

Remember - .gitignore only affects untracked files; anything already committed stays tracked until git rm --cached. And a secret that was committed once is in the history forever - rotate it, then clean history with git filter-repo if you must. The Terraform case is a post of its own: why you should not store tfstate in Git. References: gitignore, GitHub's ignoring files, and the templates at github.com/github/gitignore.

Chapter 17 - Merge conflicts (3:07:00)

Two branches changed the same lines. Git stops and marks the file -

1<<<<<<< HEAD
2    timeout = 30
3=======
4    timeout = 60
5>>>>>>> feature/login
1git status                        # "both modified: config.py"
2# edit config.py - keep one side, the other, or write the combination; delete the markers
3git add config.py
4git commit                        # finishes the merge (or: git rebase --continue during a rebase)
5git merge --abort                 # changed your mind - back to before the merge
6git mergetool                     # or VS Code's three-way merge editor

Remember - a conflict is Git asking a question only a human can answer; it is not an error. Prevent most of them with small branches merged often, and git pull --rebase (or git fetch + git rebase origin/main) before you push. Reference: git-merge, how conflicts are presented.



4. The safety net - reflog, revert, force-with-lease, and when rewriting is allowed

Three commands that are not chapters but make Part 2 safe -

1git reflog                                 # every position HEAD has been in - "lost" commits are here
2git reset --hard HEAD@{3}                  # go back to where you were three moves ago
3git revert a1b2c3d                         # undo a commit by ADDING a new inverse commit - safe on shared branches
4git push --force-with-lease                # push rewritten history only if nobody pushed in between

The rules -

  1. Private branch, not yet pushed - rewrite freely: amend, squash, reorder, reset.
  2. Your own branch, pushed, nobody else works on it - rewrite, then git push --force-with-lease (never plain --force, which can overwrite a colleague's push).
  3. Shared branch (main, develop, a release branch) - never rewrite. Undo with git revert; fix forward.
  4. Did something terrible? - git reflog. Git keeps unreachable commits for at least 30 days; only --hard resets of uncommitted changes are truly gone.

Reference: git-reflog, git-revert.


5. The GitHub errors everybody hits

1. remote: Support for password authentication was removed on August 13, 2021 - Use a personal access token or SSH - fix here.

2. git@github.com: Permission denied (publickey). fatal: Could not read from remote repository - The SSH key is not added to GitHub or the agent - fix here.

3. fatal: unable to update url base from redirection - The remote URL moved (renamed repo/org) - fix here.

4. ! [rejected] main -> main (fetch first) / non-fast-forward - Somebody pushed before you. git pull --rebase, resolve, push.

5. fatal: refusing to merge unrelated histories - Two repositories with no common commit (an init on both sides). git pull origin main --allow-unrelated-histories once.

6. error: Your local changes to the following files would be overwritten by checkout - Commit or stash before switching.

7. detached HEAD - You checked out a commit or tag directly. git switch -c fix-from-here to keep work, or git switch main to leave.

8. Hundreds of merged branches cluttering git branch -a - git fetch --prune and delete merged branches.

9. The .env with a secret is in the repository - git rm --cached .env, add to .gitignore, rotate the secret, and consider git filter-repo to purge history.

10. Pull request shows thousands of changed lines you did not touch - Line endings (CRLF vs LF) - set git config --global core.autocrlf true on Windows (or input on macOS/Linux) and add a .gitattributes with * text=auto.


More videos on this topic - the standalone git cherry-pick lesson from my DevOps Master Course -


6. Conclusion

Git is a small number of ideas - commits, branches, the staging area, and a reflog that forgives almost everything - and a large number of commands that combine them. The course teaches them in the order you will need them: foundations to work on a team repository with branches and pull requests, history rewriting to turn messy work into clean commits and to hunt regressions with bisect, and practices - log, ignore, conflicts - that keep a repository healthy. Keep this page open as the cheat sheet, keep the rule from section 4 in mind, and the official references are the Pro Git book (free) and the Git reference manual. Everything Git-related on this site is under the GitHub category.