Lab 04: Git and GitHub#
Leave with a repository for your homework.
Fork the course repository.
Make changes on branches. Review and merge them.
Bring in course updates. Keep using your fork for homework.
Open beside this page:
A DataHub terminal: File → New → Terminal in JupyterLab.
A local Bash terminal works too; use Git Bash on Windows.
Run commands in the terminal, not Python cells. No Python kernel needed.
Diagrams showing as source? Use the course page.
The merge-conflict exercise at the end is optional.
What is Git for?#
Git is version control. It keeps your code’s history.
In Lab 03, we saved the seed and inputs. We need the code that used them too.
Commit: a snapshot you choose to record, with a message, author, and links to earlier commits.
Compare: see what changed and where a problem started.
Recover: get back to work you’ve committed.
Branch and merge: try changes separately, then combine them.
Work offline: a normal clone includes the files and history. Git is distributed.
Keep one project with a history, instead of simulation_final.py,
simulation_final2.py, and simulation_really_final.py.
For a result, record commit + seed + inputs + environment.
Save, commit, and push are separate steps.
Still check the physics. Git doesn’t tell us whether the calculation is right.
What does GitHub add?#
GitHub hosts Git repositories online. Git works without it.
Git |
GitHub |
|---|---|
Keeps commits and branches |
Hosts the code and history |
Compares and combines changes |
Adds sharing, permissions, and review |
Works locally, including offline |
Lets others access the work online |
Pull requests: propose and review changes.
Issues: track problems and work to do.
Forks: make your own repository from someone else’s; contribute back if you want.
Actions: run automated checks.
Here, local means the machine running Git: DataHub or your laptop. DataHub runs on a server; GitHub holds another copy.
You committed offline. Can your partner see it on GitHub yet?
Where is the change right now?#
Edit. Stage. Commit. Push.
Place |
What’s there? |
|---|---|
Working tree |
The files you’re editing |
Staging area |
Content selected for the next commit |
Local repository |
Committed history, stored in |
Remote |
Another repository, reached through a saved URL |
%%{init: {"theme":"base","themeVariables":{"fontSize":"16px","primaryColor":"#eff6ff","primaryTextColor":"#0f172a","primaryBorderColor":"#2563eb","lineColor":"#718096","textColor":"#0f172a","edgeLabelBackground":"#f1f5f9","clusterBkg":"#f8fafc","clusterBorder":"#64748b","titleColor":"#0f172a"},"flowchart":{"htmlLabels":true,"curve":"linear","nodeSpacing":32,"rankSpacing":48},"fontFamily":"Arial"}}%%
flowchart TB
subgraph local[Local: DataHub or laptop]
W[Working files] -->|git add| S[Staging area]
S -->|git commit| C[Local branch and committed history]
T[Remote-tracking refs: origin/main] -->|git merge origin/main| C
C -->|switch or completed merge updates files| W
end
C -->|git push| R[GitHub repository]
R -->|git fetch| T
class W main
class S feature
class C merged
class R remote
class T main
style local fill:#f8fafc,stroke:#64748b,color:#0f172a
classDef default fill:#f8fafc,stroke:#64748b,color:#0f172a,stroke-width:2px
classDef main fill:#dbeafe,stroke:#2563eb,color:#172554,stroke-width:2px
classDef feature fill:#fef3c7,stroke:#b45309,color:#451a03,stroke-width:2px
classDef merged fill:#ccfbf1,stroke:#0f766e,color:#134e4a,stroke-width:3px
classDef remote fill:#ede9fe,stroke:#7c3aed,color:#2e1065,stroke-width:2px
classDef other fill:#ffe4e6,stroke:#be123c,color:#4c0519,stroke-width:2px
linkStyle default stroke:#718096,stroke-width:2px
add: stage content.commit: record it locally.push: send commits to the remote.fetch: download history; update our record of remote branches. Working files stay put.merge: combine that history with our current branch.pull: fetch and integrate. We’ll usepull --ff-onlywhen no merge commit is needed.
After add, where is the change? After commit? Has either sent it to GitHub?
Forks: your copy of the course repository#
A fork is another repository. A branch lives inside one.
We’ll fork jmduarte/phys142 into your GitHub account.
Your fork starts with the course history. You control it; GitHub keeps the connection.
Your commits don’t change the course repo. Course updates don’t appear in your fork automatically.
Operation |
What it creates or does |
|---|---|
Branch |
A name for a line of commits in one repository |
Fork |
Another GitHub repository, with its own branches and permissions |
Clone |
Local files and repository history |
Pull request |
Proposes a merge within a repo or across forks |
%%{init: {"theme":"base","themeVariables":{"fontSize":"16px","primaryColor":"#eff6ff","primaryTextColor":"#0f172a","primaryBorderColor":"#2563eb","lineColor":"#718096","textColor":"#0f172a","edgeLabelBackground":"#f1f5f9","clusterBkg":"#f8fafc","clusterBorder":"#64748b","titleColor":"#0f172a"},"flowchart":{"htmlLabels":true,"curve":"linear","nodeSpacing":32,"rankSpacing":48},"fontFamily":"Arial"}}%%
flowchart TB
accTitle: The course repository, your fork, and your clone
accDescr: Fork the course repository on GitHub, clone your fork, and push your own commits to it. Fetch and merge upstream updates into your local branch, then push to your fork.
U["Course repository: jmduarte/phys142"]
F["Your GitHub fork: origin"]
L["Your local clone on DataHub"]
U -->|Fork once on GitHub| F
F -->|git clone| L
F -->|git fetch origin| L
L -->|git push origin| F
U -->|git fetch upstream| L
class U main
class F feature
class L merged
classDef default fill:#f8fafc,stroke:#64748b,color:#0f172a,stroke-width:2px
classDef main fill:#dbeafe,stroke:#2563eb,color:#172554,stroke-width:2px
classDef feature fill:#fef3c7,stroke:#b45309,color:#451a03,stroke-width:2px
classDef merged fill:#ccfbf1,stroke:#0f766e,color:#134e4a,stroke-width:3px
classDef remote fill:#ede9fe,stroke:#7c3aed,color:#2e1065,stroke-width:2px
classDef other fill:#ffe4e6,stroke:#be123c,color:#4c0519,stroke-width:2px
linkStyle default stroke:#718096,stroke-width:2px
origin→ your fork. Push your commits here.upstream→ the course. Fetch updates here, then merge them locally.These are remote names. Adding one doesn’t give you push access.
Fork the course repository#
Make your copy. Use it for the rest of the course.
Sign in and open jmduarte/phys142.
Choose Fork. Owner: your account. Name:
phys142. Copy onlymain.Create the fork. Check its URL:
https://github.com/YOUR-USERNAME/phys142.Find forked from jmduarte/phys142 below the name.
Leave Actions disabled. We don’t need the website deployment workflow.
Already have this fork or a
homework/directory? Look at it with me before repeating setup.Your fork is public. You can look at each other’s repositories.
assignments/privateis a separate staff submodule. Don’t initialize it or copy its contents.Your files go under
homework/. Leave course files in place.Submit code and a report on Gradescope. Pushing doesn’t submit homework.
Find the owner, repo name, branch, and latest commit. Check the URL: the README and its links still describe the course, even in your fork.
Make a branch for your homework setup#
Both branches start at the same commit.
In your fork, create
homework-setupfrommainusing the branch selector.On that branch, choose Add file → Create new file.
Name it
homework/README.md. GitHub creates the directory from the path.Add:
# My PHYS 142 homework
My code, reports, and notes for PHYS 142 go here.
Record how to run each calculation, including its seed and inputs.
Choose Commit changes. Message:
Add my homework README.Commit to
homework-setup.
A branch is a name pointing to a commit, not another directory.
This commit moves
homework-setup;mainstays put.Use messages that tell us what changed.
stuffwon’t help later.
Switch to main: is the file there? Switch back and find your commit.
Open a pull request and merge it#
Check the destination. Read the diff.
Open a PR with these settings:
Field |
Choose |
|---|---|
Base repository — receives the change |
|
Base branch |
|
Head repository — supplies the change |
|
Compare branch |
|
GitHub may suggest the course repo as the base. Change it to your fork.
Add a title and a sentence explaining the homework directory.
Read Files changed with a partner. This is the diff.
Choose Create a merge commit and confirm. Use this option to match the diagram.
%%{init: {"theme":"base","themeVariables":{"fontSize":"16px","primaryColor":"#eff6ff","primaryTextColor":"#0f172a","primaryBorderColor":"#2563eb","lineColor":"#718096","textColor":"#0f172a","edgeLabelBackground":"#f1f5f9","clusterBkg":"#f8fafc","clusterBorder":"#64748b","titleColor":"#0f172a"},"flowchart":{"htmlLabels":true,"curve":"linear","nodeSpacing":32,"rankSpacing":48},"fontFamily":"Arial"}}%%
flowchart LR
accTitle: Branching and merging a README change
accDescr: Solid arrows follow development from A to B and M. M joins A and B. Dotted arrows show branch pointers. Git stores parent references backward.
A(("A: Course version")) --> M((("M: Reviewed change")))
A --> B(("B: Homework README"))
B --> M
PM[main] -. points to .-> M
PF[homework-setup] -. points to .-> B
class A,PM main
class B,PF feature
class M merged
classDef default fill:#f8fafc,stroke:#64748b,color:#0f172a,stroke-width:2px
classDef main fill:#dbeafe,stroke:#2563eb,color:#172554,stroke-width:2px
classDef feature fill:#fef3c7,stroke:#b45309,color:#451a03,stroke-width:2px
classDef merged fill:#ccfbf1,stroke:#0f766e,color:#134e4a,stroke-width:3px
classDef remote fill:#ede9fe,stroke:#7c3aed,color:#2e1065,stroke-width:2px
classDef other fill:#ffe4e6,stroke:#be123c,color:#4c0519,stroke-width:2px
linkStyle default stroke:#718096,stroke-width:2px
Each circle is a commit. Time runs left to right; earlier course history is omitted.
Mjoins both histories. Git stores links back to its two parents.Deleting a merged branch name leaves its commits in
main’s history.Opening the PR doesn’t change
main. Merging does.
Check your fork’s main for homework/README.md and find the merged PR.
The course repo hasn’t changed.
Similar names |
Different jobs |
|---|---|
Pull request |
Propose and review a merge on GitHub |
|
Update the local checkout |
Set up SSH before cloning your fork#
Create an SSH key#
Your public key goes on GitHub. Your private key stays here.
Run this on the machine where you run Git: DataHub for this lab.
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ls -la ~/.ssh
Already see
id_ed25519_phys142orid_ed25519_phys142.pub? Don’t overwrite them. Ask me.Otherwise, replace
YOUR-GITHUB-EMAILbelow and create the key:
ssh-keygen -t ed25519 -C "YOUR-GITHUB-EMAIL" -f ~/.ssh/id_ed25519_phys142
Enter a passphrase at the prompts. It protects the private key; it isn’t your GitHub password.
id_ed25519_phys142is private. Don’t share it or put it in a repo.id_ed25519_phys142.pubis public. That’s the one we’ll copy to GitHub.
Load the key into an agent in this terminal:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519_phys142
ssh-add -l
ssh-addasks for the key’s passphrase.ssh-add -lshould list the key.After a new terminal or DataHub restart, rerun the agent block. Don’t generate another key.
Add the public key to GitHub#
cat ~/.ssh/id_ed25519_phys142.pub
Copy the whole line, starting with
ssh-ed25519.Open GitHub Settings → SSH and GPG keys → New SSH key.
Title: PHYS 142 DataHub. Key type: Authentication Key.
Paste the public key and choose Add SSH key.
Test the connection using this key:
ssh -T -i ~/.ssh/id_ed25519_phys142 -o IdentitiesOnly=yes git@github.com
First connection? Compare the displayed fingerprint with GitHub’s published fingerprints. Type
yesonly if it matches.The greeting must name your GitHub account. If it names someone else or says
Permission denied, stop and ask me.Successfully authenticated plus does not provide shell access is success. GitHub accepts Git operations, not an interactive shell; this test normally exits with status
1.git@github.comalways uses the SSH usergit. The key identifies your GitHub account.
Get a local copy of your fork#
Make a separate clone for your homework.
Keep the course copy opened by DataHub as your reference. Leave its remotes alone.
All Git exercises below happen in
~/phys142-lab04/phys142, your own clone.Replace
YOUR-USERNAMEwith your GitHub username.Run this block once. It creates
~/phys142-lab04/phys142.Already have
phys142-lab04? Look inside it with me before continuing.If
git --versionfails on DataHub, ask me.
git --version
cd ~
mkdir phys142-lab04
cd phys142-lab04
git clone --config core.sshCommand="ssh -i ~/.ssh/id_ed25519_phys142 -o IdentitiesOnly=yes" \
git@github.com:YOUR-USERNAME/phys142.git
cd phys142
git remote add upstream https://github.com/jmduarte/phys142.git
pwd
git status
git remote -v
Check the URLs:
Remote |
Repository |
We’ll use it to… |
|---|---|---|
|
|
Fetch and push your work |
|
|
Fetch course updates |
originuses SSH and the key you just registered. Enter its passphrase if prompted.--config core.sshCommand=...selects that key for this new clone only.upstreamuses HTTPS to read the public course repo.clonegives us the files and.githistory. Nogit initneeded.Use the plain clone above: no
--recurse-submodulesor submodule initialization.Leave
assignments/privateuninitialized. Forking doesn’t grant access to it.
Set your name and email#
These identify your commits. They don’t log you in.
Replace both placeholders. For email privacy, copy your exact GitHub noreply address from email settings.
git config user.name "Your Name"
git config user.email "YOUR-EXACT-GITHUB-NOREPLY-ADDRESS"
git log --oneline --graph --all --decorate -6
No
--global: these settings apply only to this repo.They set the commit author. They don’t grant push access.
The short strings are commit IDs. Shared course commits have the same IDs in everyone’s fork.
Your new commits will usually have different IDs from your partner’s.
Scrolling viewer? Space moves down; q returns to the prompt.
Add a small practice calculation to your workspace#
Small text files are easy to compare.
Stay in
~/phys142-lab04/phys142.Practice with die-simulation inputs. We’ll edit them, not run the simulation.
Paste each whole block, including
EOF.cat > filenamewrites that text to a file.Create the files under
homework/. Keep the course’s root README and.gitignorein place.
mkdir homework/practice
cat > homework/practice/settings.txt <<'EOF'
distribution = fair_die
seed = 20261008
samples = 100
EOF
cat > homework/.gitignore <<'EOF'
.ipynb_checkpoints/
__pycache__/
*.pyc
.venv/
.env
results/
EOF
git status
.gitignore: skip untracked checkpoints, caches, environments, and generated results.These rules apply under
homework/, alongside the course’s existing rules.It doesn’t untrack committed files or remove them from earlier commits.
Keep code, small inputs, README instructions, and environment specifications in the repository.
Leave large generated datasets and credentials out. Ignoring a file can’t protect a secret you’ve already shared.
Git’s ignore rules.
Stage the files#
Look at what’s going into the commit.
git diff
git add homework/practice/settings.txt homework/.gitignore
git diff --staged
git status
Command |
What we see |
|---|---|
|
New, untracked files and changes to tracked files |
|
Unstaged edits to tracked files; no contents of untracked files |
|
The content selected for the next commit |
git addstages the content when you run it.Edit the file again? Run
git addagain to include that edit too.
Commit what we staged.
git commit -m "Record dice simulation settings and ignore generated files"
git status
git log --oneline -3
The working tree should be clean: no changes waiting to be committed.
Check GitHub.
homework/practice/settings.txtshouldn’t be there yet; we’ve only committed locally.A clean working tree doesn’t tell us whether we’ve pushed our commits.
Make a branch from the terminal#
Change the sample count on a new branch.
git switch -c more-samples
Open
homework/practice/settings.txtin JupyterLab’s file browser or your editor.Change only
samples = 100tosamples = 1000and save.Return to the terminal:
git diff
git add homework/practice/settings.txt
git diff --staged
git commit -m "Increase dice sample count to 1000"
git branch
switch -ccreates the branch and switches to it.The star in
git branchmarks our current branch.HEAD usually points to that branch. This commit moved
more-samplesforward.
Switch back to main#
Same directory. Different version of the file.
Save and close
homework/practice/settings.txtbefore switching. An old editor tab could overwrite the new version.
git switch main
cat homework/practice/settings.txt
On
main,samplesshould be100again. Git updated the working file.The version with 1000 samples is still on
more-samples.Let’s make a different change on
main:
cat > homework/practice/NOTES.md <<'EOF'
Record the seed and sample count when comparing simulation runs.
EOF
git add homework/practice/NOTES.md
git commit -m "Add a reminder about reproducible comparisons"
Branch |
New change |
|---|---|
|
The note |
|
The larger sample count |
Neither branch has both changes yet.
Merge the changes#
Merge into the branch you’re on.
We’re on
main. Bring inmore-samples:
git status
git merge --no-ff more-samples -m "Merge the larger-sample experiment"
cat homework/practice/settings.txt
cat homework/practice/NOTES.md
git log --oneline --graph --all --decorate -8
%%{init: {"theme":"base","themeVariables":{"fontSize":"16px","primaryColor":"#eff6ff","primaryTextColor":"#0f172a","primaryBorderColor":"#2563eb","lineColor":"#718096","textColor":"#0f172a","edgeLabelBackground":"#f1f5f9","clusterBkg":"#f8fafc","clusterBorder":"#64748b","titleColor":"#0f172a"},"flowchart":{"htmlLabels":true,"curve":"linear","nodeSpacing":32,"rankSpacing":48},"fontFamily":"Arial"}}%%
flowchart LR
accTitle: Merge two lines of development
accDescr: Solid arrows follow development from A to B and C, then M. M combines B and C. Dotted arrows show branch pointers.
A(("A: 100 samples")) --> C(("C: Add notes"))
C --> M((("M: Merge")))
A --> B(("B: 1000 samples"))
B --> M
PM[main] -. points to .-> M
PF[more-samples] -. points to .-> B
class A,C,PM main
class B,PF feature
class M merged
classDef default fill:#f8fafc,stroke:#64748b,color:#0f172a,stroke-width:2px
classDef main fill:#dbeafe,stroke:#2563eb,color:#172554,stroke-width:2px
classDef feature fill:#fef3c7,stroke:#b45309,color:#451a03,stroke-width:2px
classDef merged fill:#ccfbf1,stroke:#0f766e,color:#134e4a,stroke-width:3px
classDef remote fill:#ede9fe,stroke:#7c3aed,color:#2e1065,stroke-width:2px
classDef other fill:#ffe4e6,stroke:#be123c,color:#4c0519,stroke-width:2px
linkStyle default stroke:#718096,stroke-width:2px
The diagram starts at the settings commit. Earlier README history is omitted.
Different files changed, so Git could combine the edits.
Check
main: do we have both the note and 1000 samples?--no-ffrequests a merge commit joining both histories. We need one anyway: both branches advanced.A merge doesn’t check the code. Inspect it and rerun the calculation or tests.
When Git can fast-forward#
Move the branch name to a commit that already exists.
Without the
homework/practice/NOTES.mdchange,mainwould be an ancestor ofmore-samples.Move
maintoBwithout a new commit: that’s a fast-forward.
%%{init: {"theme":"base","themeVariables":{"fontSize":"16px","primaryColor":"#eff6ff","primaryTextColor":"#0f172a","primaryBorderColor":"#2563eb","lineColor":"#718096","textColor":"#0f172a","edgeLabelBackground":"#f1f5f9","clusterBkg":"#f8fafc","clusterBorder":"#64748b","titleColor":"#0f172a"},"flowchart":{"htmlLabels":true,"curve":"linear","nodeSpacing":32,"rankSpacing":48},"fontFamily":"Arial"}}%%
flowchart LR
subgraph before[Before fast-forward]
A1[A] --> B1[B]
M1[main] -. points to .-> A1
F1[more-samples] -. points to .-> B1
end
subgraph after[After fast-forward]
A2[A] --> B2[B]
M2[main] -. points to .-> B2
F2[more-samples] -. points to .-> B2
end
before ~~~ after
class A1,B1,A2,B2 main
class M1,M2 main
class F1,F2 feature
style before fill:#f8fafc,stroke:#64748b,color:#0f172a
style after fill:#f8fafc,stroke:#64748b,color:#0f172a
classDef default fill:#f8fafc,stroke:#64748b,color:#0f172a,stroke-width:2px
classDef main fill:#dbeafe,stroke:#2563eb,color:#172554,stroke-width:2px
classDef feature fill:#fef3c7,stroke:#b45309,color:#451a03,stroke-width:2px
classDef merged fill:#ccfbf1,stroke:#0f766e,color:#134e4a,stroke-width:3px
classDef remote fill:#ede9fe,stroke:#7c3aed,color:#2e1065,stroke-width:2px
classDef other fill:#ffe4e6,stroke:#be123c,color:#4c0519,stroke-width:2px
linkStyle default stroke:#718096,stroke-width:2px
linkStyle 6 stroke:transparent,stroke-width:0px
Solid arrows: order of commits.
Dotted arrows: which commit each branch points to.
Our actual example had two lines of development. It needed a two-parent merge.
Push your work and bring updates back#
Upload the committed history#
Push. Then check GitHub.
Run the first two commands. Check your fork’s URL and
mainbefore pushing.
git remote -v
git branch --show-current
git push origin main
git rev-parse --short HEAD
git status
We’ve pushed
mainand its history, including the merged work.This doesn’t push every local branch name.
Refresh main on GitHub and check:
homework/practice/settings.txthas 1000 samples.homework/practice/NOTES.mdis there.The latest commit ID matches the local
HEADprinted above.
Make a remote change, then update the clone#
Change it on GitHub. Check your local copy.
On GitHub, open
homework/README.mdin your fork, onmain.Add
Current practice sample count: 1000.and commit directly tomain.Our local copy is still on the earlier commit. Fetch and compare:
git status
git fetch origin
git log --oneline main..origin/main
git diff main origin/main -- homework/README.md
cat homework/README.md
origin/mainis our local record of the fork’s branch after fetching. It doesn’t watch GitHub for updates.Log and diff show the new commit;
cat homework/README.mdstill shows the old file.Check that the working tree is clean, then bring the commit into our
main:
git merge --ff-only origin/main
cat homework/README.md
git status
Next time:
git pull --ff-only origin maincombines fetch and fast-forward.No second commit needed. We brought in the existing one.
--ff-onlystops if the local and remote histories have diverged.If it stops, run
git log --oneline --graph --all --decorateand show me. We’ll look at the histories before combining them.Don’t force-push or discard local work to get past the error.
Bring in updates from the course#
Fetch from the course. Merge locally. Push to your fork.
New material appears in jmduarte/phys142. Your fork doesn’t update itself.
Work in
~/phys142-lab04/phys142.Save your files. Check for a clean working tree; commit work you want to keep before switching or merging.
Update from your fork, then check the course:
git status
git switch main
git pull --ff-only origin main
git fetch upstream
git log --oneline main..upstream/main
Command |
What it does |
|---|---|
|
Brings in changes from your GitHub fork |
|
Downloads course history; leaves working files alone |
|
Lists course commits your |
upstream/main is our local record after the fetch. An empty log means no new course commits.
Merge the course history into
main, then push to your fork:
git merge --no-edit upstream/main
git log --oneline --graph --all --decorate -10
git push origin main
git status
Already up to date? Nothing new to merge. Repeat when new material is posted.
Both sides have new commits? Git may make a merge commit keeping both histories.
No
--ff-onlyon this merge: your homework can make the histories diverge.--no-editaccepts Git’s generated merge message.Conflict? Look at the files with me; the optional exercise below covers this. Don’t force-push or discard work.
origin is your fork. Pulling from it alone won’t fetch course updates.
After fetching upstream, you still need to merge, then push.
Follow the two histories#
Your homework stays. The course update comes in.
%%{init: {"theme":"base","themeVariables":{"fontSize":"16px","primaryColor":"#eff6ff","primaryTextColor":"#0f172a","primaryBorderColor":"#2563eb","lineColor":"#718096","textColor":"#0f172a","edgeLabelBackground":"#f1f5f9","clusterBkg":"#f8fafc","clusterBorder":"#64748b","titleColor":"#0f172a"},"flowchart":{"htmlLabels":true,"curve":"linear","nodeSpacing":32,"rankSpacing":48},"fontFamily":"Arial"}}%%
flowchart LR
accTitle: Merge a course update with your homework history
accDescr: The course and your work share A. The course adds C and you add B. M in your local main merges both histories; pushing sends M to your fork. Upstream main stays at C.
A(("A: Shared start")) --> C(("C: Course update"))
A --> B(("B: Your homework"))
C --> M((("M: Keep both")))
B --> M
PU[upstream/main] -. points to .-> C
PM[main after merge] -. points to .-> M
class A,C,PU main
class B feature
class M,PM merged
classDef default fill:#f8fafc,stroke:#64748b,color:#0f172a,stroke-width:2px
classDef main fill:#dbeafe,stroke:#2563eb,color:#172554,stroke-width:2px
classDef feature fill:#fef3c7,stroke:#b45309,color:#451a03,stroke-width:2px
classDef merged fill:#ccfbf1,stroke:#0f766e,color:#134e4a,stroke-width:3px
classDef remote fill:#ede9fe,stroke:#7c3aed,color:#2e1065,stroke-width:2px
classDef other fill:#ffe4e6,stroke:#be123c,color:#4c0519,stroke-width:2px
linkStyle default stroke:#718096,stroke-width:2px
A: shared starting point.B: your homework commit.C: new course commit.M: your local merge of both histories. Push it to your fork.The course stays at
C. Your homework hasn’t been sent there.
Solid arrows follow development; dotted arrows show branch pointers.
No new course commit? No C or M yet.
Saving homework in your fork needs no PR to the course.
A course PR proposes a change to the shared materials. Check its base repository.
Which remote gets your push? Which has course updates? How do fork, clone, and branch differ?
Start your Assignment 1 directory#
Set up the files you’ll keep using.
Directory |
Contents |
|---|---|
|
Course handouts |
|
Your code, report, and README |
Start with a clean working tree. Make a branch and add the README:
git status
git switch main
git switch -c assignment1-setup
mkdir homework/assignment1
cat > homework/assignment1/README.md <<'EOF'
# Assignment 1
## Run my code
TODO: Add the filenames, required packages, and exact command to run the calculation.
## Reproduce a result
TODO: Record the inputs, random seed, result, and uncertainty.
## Check the calculation
TODO: Describe a comparison or test and what it tells me.
## Report
TODO: Include the figures, explanations, and required AI-use appendix.
EOF
git add homework/assignment1/README.md
git diff --staged
git commit -m "Start my Assignment 1 workspace"
git push -u origin assignment1-setup
On GitHub:
Open a PR. Base and head repositories: your fork.
Base:
main. Compare:assignment1-setup.Read the diff. Choose Create a merge commit.
Bring it back locally:
git switch main
git pull --ff-only origin main
git log --oneline -4
git status
For your next homework session:
Check for course updates.
Branch for the change you’re trying.
Add your source files and report. Replace the README’s TODOs as you work.
Commit at useful stopping points; push what you want on GitHub.
For reported results, record commit + inputs + seed + environment.
Submit code and report on Gradescope. Saving and pushing don’t submit them.
Optional: make and resolve a merge conflict#
A conflict can occur when two branches change the same line incompatibly.
Use two local branches. Leave
mainunchanged; don’t push these branches.Stay in
~/phys142-lab04/phys142. Check thatgit statusis clean.
Create the first branch:
git switch main
git switch -c seed-a
In
homework/practice/settings.txt, replaceseed = 20261008withseed = 11. Save, then:
git add homework/practice/settings.txt
git commit -m "Try seed 11"
git switch main
git switch -c seed-b
seed-bstarts frommain, where the seed is still20261008. In the same file, replace it withseed = 22, save, then:
git add homework/practice/settings.txt
git commit -m "Try seed 22"
git merge seed-a
The merge should stop with a conflict in homework/practice/settings.txt: both branches changed the same seed. We must choose what to keep.
Read the conflict before editing#
Current branch:
seed-b, seed22.Incoming branch:
seed-a, seed11.No merge commit exists yet.
%%{init: {"theme":"base","themeVariables":{"fontSize":"16px","primaryColor":"#eff6ff","primaryTextColor":"#0f172a","primaryBorderColor":"#2563eb","lineColor":"#718096","textColor":"#0f172a","edgeLabelBackground":"#f1f5f9","clusterBkg":"#f8fafc","clusterBorder":"#64748b","titleColor":"#0f172a"},"flowchart":{"htmlLabels":true,"curve":"linear","nodeSpacing":32,"rankSpacing":48},"fontFamily":"Arial"}}%%
flowchart LR
accTitle: Conflicting seed changes before the merge
accDescr: Main stays at A. Seed-a points to B and seed-b to C. No merge commit exists yet. Solid arrows follow development; dotted arrows show branch pointers.
A(("A: Seed 20261008")) --> B(("B: Seed 11"))
A --> C(("C: Seed 22"))
PM[main] -. points to .-> A
PA[seed-a] -. points to .-> B
PB["seed-b: Current branch"] -. points to .-> C
class A,PM main
class B,PA feature
class C,PB other
classDef default fill:#f8fafc,stroke:#64748b,color:#0f172a,stroke-width:2px
classDef main fill:#dbeafe,stroke:#2563eb,color:#172554,stroke-width:2px
classDef feature fill:#fef3c7,stroke:#b45309,color:#451a03,stroke-width:2px
classDef merged fill:#ccfbf1,stroke:#0f766e,color:#134e4a,stroke-width:3px
classDef remote fill:#ede9fe,stroke:#7c3aed,color:#2e1065,stroke-width:2px
classDef other fill:#ffe4e6,stroke:#be123c,color:#4c0519,stroke-width:2px
linkStyle default stroke:#718096,stroke-width:2px
Run git status and open homework/practice/settings.txt. HEAD marks our side; seed-a marks the incoming side:
<<<<<<< HEAD
seed = 22
=======
seed = 11
>>>>>>> seed-a
Some configurations also show the original value in a
|||||||block.Choose one seed. Remove the conflict markers and the version you aren’t keeping.
Resolve, inspect, then commit#
Keep seed 11. The complete file should be:
distribution = fair_die
seed = 11
samples = 1000
Save, then inspect and commit:
git diff
git add homework/practice/settings.txt
git diff --staged
git commit -m "Resolve the seed conflict using seed 11"
git status
git log --oneline --graph --all --decorate -10
git switch main
cat homework/practice/settings.txt
Back on
main, the seed should still be20261008. The merge commit is onseed-b.In a real simulation, changing the seed can change the result. Rerun the calculation and record the seed.
To cancel a conflicted merge, run
git merge --abortbefore resolving and committing. Because we started clean, this restores the pre-merge state. It doesn’t undo a committed merge.
Reference: Git merge and conflict handling.
Keep this beside your homework#
A small command reference#
Question or action |
Command |
|---|---|
Where am I? |
|
What changed, and what is staged? |
|
What changed in tracked files since staging? |
|
What will the next commit contain? |
|
Stage a particular file |
|
Record the staged changes |
|
Read the history and branch labels |
|
Create and switch to a branch |
|
Switch to an existing branch |
|
Merge into the current branch |
|
Check remote URLs |
|
Download history from my fork |
|
Download new course history |
|
Merge course updates into my current branch |
|
Update from my own fork when |
|
Publish |
|
Publish a new feature branch and track it |
|
Run
git statusbefore and after a change.Read the diff. Stage the files you want, then inspect the staged diff.
Commit. Push when you’re ready to share the commits.
If Git stops with an error, read it before trying another command.
When something stops you#
What you see |
What to check |
|---|---|
|
Run |
|
Set |
|
Save your file, then check |
|
Check your fork’s SSH URL, |
No connection to the authentication agent |
Rerun the |
Push rejected as non-fast-forward |
The remote has history your branch doesn’t contain. Fetch, look at the graph, and show me before combining the changes. |
Switching or merging would overwrite local changes |
Look at the changes and commit the work you want to keep before switching. Don’t discard it just to get past the error. |
Conflict markers in a file |
Resolve the content, remove markers, stage, inspect, and complete the merge. |
Save notebooks before staging. Outputs and metadata can make diffs large; clear outputs you don’t need.
Agree on who edits each notebook. Move frequently shared code into small text modules to make changes easier to compare and merge.
GitHub’s notebook preview displays the file; it doesn’t run the Python code.
Final check: ready for the next homework session#
Show your partner:
Your fork of
jmduarte/phys142andhomework/assignment1/README.md.A commit and its diff. Explain the change.
A PR merged into your own fork, with the same change in local
main.git remote -v: identifyoriginandupstream.A clean working tree, with local
HEADmatching your GitHubmain.
Explain:
How will you bring in a new course handout without losing your homework?
Why isn’t
git pull origin mainenough when the update is only in the course repository?What comes after
git fetch upstream?How do Git and GitHub differ? What do save, commit, and push do?
What does each of branch, fork, and clone create?
Why is a pull request different from pull?
Optional independent challenge#
Create
add-run-notes. Add a section tohomework/README.mdexplaining the seed and sample count inhomework/practice/settings.txt.Stage the change, read the diff, and commit.
Push with
git push -u origin add-run-notes.Open a PR to your fork’s
main. Read the diff and merge.Switch your local checkout to
main, then rungit pull --ff-only origin main.
References and more practice#
Learn Git Branching: an optional interactive sandbox for more branching practice.
Diagrams use Mermaid. A and B are teaching labels for commits, not actual hashes to use in Git commands.