Eric Manning
September 1, 2026
paper.docx
paper_v2.docx
paper_v2_advisor_comments.docx
Or a file or folder on Dropbox or Google Drive.
What changed?
Who changed it?
Why did they change it?
Every time you commit, git records:
a1b2c3dYou can return to any commit as needed or compare any two commits.
| Dropbox / OneDrive / Drive | git + GitHub | |
|---|---|---|
| Tracks | a file | a change across files |
| Versions are | automatic, timed, unnamed | deliberate, named, explained |
| History kept | ~30 days, per file | forever, whole project |
| Both of you edit | “conflicted copy (Eric’s Mac)” | a merge you can resolve line-by-line |
| Try something risky | copy the whole folder | a branch |
| Share it publicly | a link | a repo, fork, or website |
| Big binary data | good at this | bad at this |
| Restricted data | Princeton-managed, has a DUA | your problem |
Code and text -> git. Medium-to-large data -> somewhere else. Fetch as needed.
In a terminal — RStudio’s Terminal tab (next to Console), or Positron’s Terminal panel:
git version 2.55.0
If not:
xcode-select --install, or install from git-scm.comsudo apt install git or your distribution’s equivalentGit stamps every commit with a name and an email. Set them once, globally:
Or, without leaving R:
github.com/join — but think for ten seconds about the username first.
Happy Git’s advice:
Email. Add your Princeton address as a second, verified email so GitHub links your university identity.
Vice versa is also okay.
Two-factor authentication is required. Set it up now. Use your phone. Use a biometric passkey (your face) if you can.
This opens GitHub’s token page with the form already filled in:
repo, user, workflowpositron-laptop-2026Copy it. This is the only time you will see it, but you can always make a new one.
Back in R:
? Enter password or token: ghp_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8
-> Adding new credentials...
-> Removing credentials from cache...
-> Done.
This saves the token to your operating system’s credential store.
Treat the token exactly like a password. Never write it or commit it.
── Git global (user) ─────────────────────
• Name: 'Jane Doe'
• Email: 'jdoe@gmail.com'
• Default initial branch name: 'main'
── GitHub user ───────────────────────────
• Default GitHub host: 'https://github.com'
• Personal access token for 'https://github.com': '<discovered>'
• GitHub user: 'janedoe'
• Token scopes: 'gist, repo, user, workflow'
| Term | What it means |
|---|---|
| repository | a folder git is tracking (a “repo”). The history lives in .git/ |
| commit | a saved snapshot, with a message (also verb) |
| stage | choose which changes go into the next commit |
| diff | a line-by-line difference between two versions |
| remote | a copy of the repo somewhere else, usually GitHub |
| origin | the default name for your remote |
| clone | download a repo, with all of its history |
| push / pull | send commits to the remote / get commits from it |
| branch | a named line of development. The default one is main (or master) |
The names are bad.
git add
git commit
.git/A commit should be one idea instead of “everything I happened to have saved.”
Staging lets you make two commits instead of one commit called stuff:
a1b2c3 Handle counties missing from the ACS extract
z0y9x8 Fix typo in README
Future you or somebody else will read this. Be brief, but clear.
GitHub first — make the repo on github.com, then clone it locally.
Better. The remote is wired up correctly when you start.
Local first — you already have a folder of work. Put it under git, then create the GitHub repo and connect them.
Slides for this at the end of the section.
github.com → the + menu → New repository
first-repoThen Create repository.
~/DownloadsRStudio clones the repo, makes an .Rproj file, and opens the project. The Git pane appears in the top-right.
Cmd/Ctrl + Shift + P — and type Git: Clone (or use Clone Repository on the Welcome page)Positron clones the repo and opens the folder as your workspace. No .Rproj file is created, and none is needed.
Both IDEs are running this for you:
New R script, analysis.R:
Save it. Saving is not committing. Git has no idea you did anything yet.
git statusOn branch main
Your branch is up to date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
analysis.R
nothing added to commit but untracked files present
RStudio — Git pane → tick the Staged box next to analysis.R → Commit → type a message → Commit
Positron — Source Control → hover analysis.R → + (Stage Changes) → type a message in the box → ✓ Commit
Terminal
[main 9f8e7d6] Add first look at county income
1 file changed, 6 insertions(+)
create mode 100644 analysis.R
| Command | Stages |
|---|---|
git add . |
everything at or below where you’re standing |
git add -A |
everything in the whole repo, wherever you are |
git add -u |
only files git already tracks — no new ones |
RStudio — tick the box in the Git pane’s header row.
Positron — the + on the Changes heading, not on a file.
git add . is only as safe as your .gitignore. It also coalesces all changes.
Edit analysis.R — replace the summary() line:
Save. Then look at the Git pane / Source Control — the file is now Modified rather than untracked.
git diff[main a1b2c3d] Use mean rather than summary for county income
1 file changed, 1 insertion(+), 1 deletion(-)
git add . is safe here — you just looked at the diff, and it’s one file.
THE LOOP: Edit → look at the diff → commit.
a1b2c3d Use mean rather than summary for county income
9f8e7d6 Add first look at county income
0011223 Initial commit
RStudio — the green ↑ Push arrow in the Git pane
Positron — Sync Changes in Source Control, or the ↻ in the status bar
Terminal
Enumerating objects: 8, done.
To https://github.com/janedoe/first-repo.git
0011223..a1b2c3d main -> main
Go look at your repo URL.
Commit often. Write short, but clear commit messages. (Looking at you, Claude.)
| I want to… | Do this |
|---|---|
| Throw away uncommitted edits to a file | git restore analysis.R |
| Unstage something I staged | git restore --staged analysis.R |
| Fix the message on my last commit | git commit --amend |
| Undo a commit I already pushed | git revert a1b2c3d — makes a new commit that reverses it |
| See an old version of a file | git log -p analysis.R |
If it’s really broken, move your new edits, delete the folder, clone it again, and put your new files back.
You have a folder of work and want it on GitHub. From inside that folder:
Initialises the repo, offers to commit everything currently there, and restarts the session so the IDE notices.
usethis::)You won’t remember the inputs and outputs.
# Setup --------------------------------------------------------
library(dplyr)
# Load data ----------------------------------------------------
county <- read.csv("data/county_data.csv")
# Clean --------------------------------------------------------
county <- county |> filter(...) |> mutate(...) |> ...
# Model --------------------------------------------------------
first_model <- lm(y_var ~ x_var, data = county, ...)
# Figures ------------------------------------------------------
ggplot(...)RStudio: Cmd + Shift + R
Delete it. Git remembers.
Change one thing here and the diff says this line changed. Useless.
Now the diff points at the step/line(s) you changed.
Deleting a file in a later commit does not remove it.
GitHub:
A 40 MB CSV, committed ten times as you clean it, is 400 MB of history.
.gitignore# R
.Rhistory
.RData
.Renviron
.Rproj.user/
# Data — too big and/or restricted; see data/README.md
data/*.csv
!data/README.md
# Quarto build output
/.quarto/
/_site/
*_files/
# OS junk
.DS_Store
When you ticked the R template while creating the repo, GitHub gave you the first block: .Rhistory, .RData, .Renviron, .Rproj.user/.
Set up .gitignore before the first commit.
API keys, tokens, passwords, database credentials. Never in a script.
.Renviron is already in the R .gitignore template.
Bots scan public GitHub for credentials within seconds of a push.
In order:
First, the thing that does not work:
Git records the deletion, but does not forget the file in previous commits.
You have to rewrite every commit that ever touched the file.
To scrub a string rather than a whole file, put the string in a file and use --replace-text ../passwords.txt instead.
filter-repo deliberately deletes your origin remote when it finishes, so you can’t push the rewrite by accident.
Every commit hash after the removed file has changed. Collaborators must delete their copy and clone fresh.
Early in a project, just start fresh:
.gitignore firstRewriting history with git-filter-repo works too.
A branch is a label pointing at a commit.
Once main is stable and large:
main in a state you’d be willing to show someone elseNew commits land in try-state-fe, not main.
We used to use checkout for this (and other things).
Commit before you switch.
The files on disk change. Your analysis.R reverts to whatever main says it is.
You’re happy with the branch. Bring it into main:
Updating a1b2c3d..d4e5f6a
Fast-forward
analysis.R | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
Now you can delete the branch: git branch -d try-state-fe
When the same lines changed in two places. Git will not guess.
Commit both. Then, from main:
Auto-merging analysis.R
CONFLICT (content): Merge conflict in analysis.R
Automatic merge failed; fix conflicts and then commit the result.
Both IDEs highlight this block and offer buttons: Accept Current, Accept Incoming, Accept Both, Compare.
Edit the file so it says what you actually want. Then delete all three marker lines.
Then stage and commit as normal:
Resolving a conflict: edit, delete markers, save, commit.
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://github.com/...'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository
hint: pushing to the same ref.
Start every work session with git pull.
Clone — Your copy to read, run, and edit locally. You cannot push it back without write access.
Fork — A copy in your GitHub account. You can push to it freely (and easily offer changes to original authors).
If you can’t push to that repo, this will:
origin to your fork and upstream to the originalupstream at the original:origin https://github.com/janedoe/replication-2024.git (fetch)
origin https://github.com/janedoe/replication-2024.git (push)
upstream https://github.com/someuser/replication-2024.git (fetch)
upstream https://github.com/someuser/replication-2024.git (push)
Your fork does not update itself.
Method packages. Found a bug in someone’s estimator? Fork, fix, open a PR. GitHub will credit your contributions.
No license means all rights reserved. Nobody can use your code.
Free static hosting attached to any GitHub repository.
<username>.github.io/<repo>
Static means HTML, CSS, and JavaScript. You render locally and publish the result.
Which is exactly what Quarto already does.
Project site — any repo:
janedoe.github.io/first-repo
User site — a repo named janedoe.github.io gets the bare address:
janedoe.github.io
The second one is your academic website.
Broadly,
<yourusername>.github.iomain (or master) branchusethis::, wire to a new GitHub respositoryIn a fresh RStudio session, File > New Project > New Directory > Quarto Website
Before publishing anything, add to .gitignore if not already there:
.quarto/
_site/
main (or master) branchCommit everything as an initial commit as we’ve done previously. This will create a main (or master) branch.
usethis::, wire to a new GitHub respositoryIt will look something like:
It will open the GitHub repo in the browser. If this shows a 404 error, refresh the page.
You can call quarto preview at any time to render a local version of the website in your browser.
Alternatively, you can pull it up in the RStudio viewer by opening one of the .qmd files and clicking “Render” at the top. (In the adjoining gear box, make sure “Preview in Viewer Pane” is selected.)
Now is a good time to make, save, stage, and commit some edits before first publication, if desired. After making and saving, you can call quarto preview or click “Render” again at any time to view your changes.
Once you’ve pushed any changes, in the terminal type quarto publish gh-pages. If prompted, type yes when asked if you want to publish using gh-pages. The printed output will end with something like the following:
Follow those directions. Click the link or go to “Settings” > “Pages” in the GitHub repo and change the “Branch” dropdown from None to gh-pages, then click Save. Wait a minute and your site will publish. (To view the status of the publication run, you can click on the “Actions” tab of the GitHub repo.)
You now have two branches doing two different jobs:
| Branch | Holds | You touch it |
|---|---|---|
main |
your source: .qmd, .R, _quarto.yml |
constantly |
gh-pages |
rendered HTML, managed by Quarto | never |
To update the site later: edit, preview (if you want), commit, push, then run quarto publish gh-pages again.
The Quarto documentation is truly excellent. See https://quarto.org/docs/websites/ and its subcontent. You can easily swap between website templates, just as you can swap between document templates.
Claude is also quite good at helping with this.
See here for another way to publish – and how to wire your website to a custom domain.
So you know the words when you meet them:
git stash · git rebase · tags and releases · submodules · GitHub Issues · Projects and boards · Actions and CI · Codespaces · renv for package versions · pre-commit hooks · signed commits
Learn each of these the first time you actually need them.
Nobody knows all of git. Look it up or ask Claude/Codex to help you.
| What | Terminal | RStudio | Positron |
|---|---|---|---|
| See what changed | git status |
Git pane | Source Control (Ctrl/Cmd+Shift+G) |
| See the diff | git diff |
Diff button | click the file |
| Stage a file | git add <file> |
tick Staged | + on the file |
| Stage everything | git add . |
header checkbox | + on Changes |
| Commit | git commit -m "..." |
Commit | message box, then ✓ |
| Send | git push |
↑ Push | Sync Changes |
| Get | git pull |
↓ Pull | Sync Changes |
| History | git log --oneline |
History (clock) | Graph |
| New branch | git switch -c name |
branch dropdown | branch in status bar |
| Switch branch | git switch name |
branch dropdown | branch in status bar |
| Undo a file | git restore <file> |
Revert | discard changes (↩︎) |
Comment your code properly.