LSE ME204 · Data Engineering Principles for the Social Sciences
🖥️ Week 02 Day 03 Lecture
10:00 – 10:25
How to keep track of how your scripts evolve over time
How to keep more than the latest copy of a file
A straight line of commits. Newest is usually at the top of git log.
The message is the label you give that version. Without it, the pile is just a stack of anonymous copies.
Branches are like limbs on a tree: people can edit in parallel without overwriting each other.
Later you merge a branch back into main. This afternoon’s lab forces that join on purpose.
On GitHub: New repository. Git runs on your machine later. The remote copy and the Pages settings are on GitHub.
Suggested settings:
me204-git-practice (or your own).gitignore: Python
After Create repository: README is on main.
On GitHub: edit README.md in the browser, or wait and edit after clone.
If git clone over SSH fails with a permission error, authenticate once with the GitHub CLI.
In the terminal:
Choose GitHub.com, then SSH, and follow the prompts. Nuvolos already has gh installed.
On GitHub: green Code button → copy the SSH URL.
In the terminal:
10:25 – 11:20
How to commit more than once so the history says what you did
You need a real file in the repo before the first commit. Write a tiny Open Library search that prints raw JSON.
In your cloned repo, create 01-search.py.
Call Open Library search (no API key). Pick one title or author. Print the raw JSON response. Nothing fancy yet.
Docs: Open Library Search API
Build this shape together. Stop once the JSON prints.
In the editor:
In the terminal:
Example of a successful run (truncated):
{
"numFound": 184,
"start": 0,
"docs": [
{
"title": "Ada Lovelace",
"author_name": ["Isabel Sanchez Vegara"],
"first_publish_year": 2018,
...
},
...
]
}
The -m string is for a future you. Say what changed.
In the terminal the shape is:
update or fixCheck, then commit the JSON-printing script. Suggested message: Add Open Library search that prints raw JSON.
git status→
On branch main
Your branch is up to date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
01-search.py
nothing added to commit but untracked files present
Untracked: Git sees 01-search.py on disk in your working folder, but is not recording it yet.
git diffDiff: the line-by-line change list between your working folder and the last commit. Untracked files have nothing to compare yet, so git diff stays empty until you stage.
git add→
(no output)
No text is normal. Run git status again if you want to see it staged in green.
Staged: you marked this version of 01-search.py for the next commit. Unstaged means the opposite: changes still only in the working folder, not on that list.
git commit -m→
[main 3f8a2c1] Add Open Library search that prints raw JSON
1 file changed, 12 insertions(+)
create mode 100644 01-search.py
Committed locally: a new box on top of your local pile (newest on top). Remote unchanged: origin/main still points at the earlier tip.
git log and git statusSame story in the terminal. Newest line first in git log. Status says you are ahead of the remote.
Now change the script. Print a few fields instead of the whole JSON.
In the editor, replace the print(json.dumps(...)) line with:
Each doc is a dictionary for one book.
doc["title"] is ordinary dictionary lookup.
Some books omit author_name or first_publish_year. Ask with "author_name" in doc before you read that key. If it is missing, use a placeholder string in the else branch.
In the terminal:
Example of a successful run:
Ada Lovelace | Isabel Sanchez Vegara | 2018
Ada Lovelace | Christopher Hollings | 2018
Enchantress of numbers | Jennifer Chiaverini | 2017
Commit the print change as its own snapshot. Suggested message: Print title, author, and year from search results.
git status (again)→
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
modified: 01-search.py
no changes added to commit
Modified (unstaged): 01-search.py is tracked, but your edits sit only in the working folder. They are not staged for the next commit yet.
git diff (again)→
diff --git a/01-search.py b/01-search.py --- a/01-search.py +++ b/01-search.py @@ -8,4 +8,18 @@ payload = response.json() -print(json.dumps(payload, indent=2)) +for doc in payload["docs"]: + title = doc["title"] + + if "author_name" in doc: + author = doc["author_name"][0] + else: + author = "(no author)" + + if "first_publish_year" in doc: + year = doc["first_publish_year"] + else: + year = "?" + + print(f"{title} | {author} | {year}")
git diff now lists those unstaged edits: red lines left the last commit, green lines are in your working folder.
git add (again)git add copies the current working version into the staging area. The file is now staged for the next commit.
git addStaging is a snapshot. Edit again before you commit and the new edits stay only in the working folder.
git status (staged and unstaged)→
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: 01-search.py
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
modified: 01-search.py
Same filename, two places: green = staged snapshot, red = newer working edits not staged yet. git diff shows the unstaged part. git diff --staged shows what the next commit would include.
git add once more, then commitIf you want the newer edit in this commit too, stage again. Then commit.
In the terminal:
After the second git add, working and staging match again.
Local pile grows with each commit. Remote still on the old tip until you push.
Here is a shorter version of the same loop. Next slides step through each new idea.
.get with a defaultLooks up the key. Uses the second argument if the key is missing.
Same as:
or []If the key is missing, .get returns None. or [] turns that into an empty list.
Same as:
if / else on one lineTake the first author when the list is non-empty, otherwise the placeholder.
Same as:
Yes, commit messages are UTF-8 and accept emojis. Check out gitmoji (♻️ means refactor code).
The local pile grows again. origin/main still has not moved.
Your local machine is ahead. The remote on GitHub still points at the old tip.
Local pile grew. origin/main has not moved.
git push→
Enumerating objects: 8, done.
Writing objects: 100% (6/6), done.
To github.com:YOU/me204-git-practice.git
a1b2c3d..e7d4a12 main -> main
git push sends the commits GitHub does not have yet.
origin/main now matches main. Both piles share the same top box.
What if you edit the README on github.com? Or push from your laptop? Or a classmate pushes first?
Your Nuvolos copy is behind. git push will refuse until you catch up.
git pull may stop and askThe first time Git has to join histories, it asks how: merge or rebase. For this course, choose merge.
hint: You have divergent branches and need to specify how to reconcile them. hint: git config pull.rebase false # merge hint: git config pull.rebase true # rebase hint: git config pull.ff only # fast-forward only
In the terminal (once per machine is enough):
That sets merge as the default for every repo on this machine. Do not pick rebase today.
git pull→
Updating e7d4a12..b8c9d0e
Fast-forward
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
git pull downloads the commits you are missing and updates your local main. This afternoon’s lab uses pull when someone else pushed first.
These leave your files alone. They only print history or diffs.
In the terminal:
git diff --staged compares what you staged to the last commit.
Same three buckets. Before vs After. restore --staged is safe. Bare restore and reset --hard discard work.
git restore --stagedSafe. Resets the index for that file back to HEAD. The working folder is not rewritten.
In the terminal:
git restore without --stagedDestructive: copies the index into the working folder. Unstaged edits on disk are discarded. They do not move into the index as a staged snapshot. When nothing is staged, the index already matches HEAD, so the file ends up matching the last commit.
In the terminal:
git reset --hardAlso destructive. Forces both the working folder and the index to HEAD. Staged and unstaged edits are discarded.
In the terminal:
If you only meant to unstage, use git restore --staged. Do not run reset --hard today.
11:20 – 11:35

After the break:
docs/index.md and GitHub Pages11:35 – 12:15
How to try an edit without changing main yet
In the terminal:
git branch lists names. git switch -c creates improve-readme and moves you onto it.
Edit README.md while you are on improve-readme. Commit there. Stay on this branch until the next slide.
In the terminal:
In the terminal:
After the merge, main includes the README commit. Then push so GitHub matches.
12:15 – 12:30
How to do all of this the lazy (but still valid) way
Find these in the panel:

12:30 – 12:55
How to publish a Markdown page from this repo on the web
docs/index.mdIn the terminal:
In the terminal:
On GitHub:
main/docsWait a minute, then open https://<user>.github.io/<repo>/

If the URL 404s, check folder /docs, branch main, and wait for the Pages build. Public repos work on the free plan. Private Pages needs a paid GitHub plan.
♻️ = refactor code)13:00
LSE Summer School 2026 | ME204 Week 02 Day 03
LSE ME204 (2026)