Git Branching & Collaboration
Work a change through a branch, a rebase and a conflict, and recover from the three mistakes everyone makes.
- Time
- 45 min
- Level
- Beginner
- Objectives
- 4 objectives
- Cost
- Free
Where this fits in the platform
Already built
—
This lab adds
- A repository you can branch and merge without fear
Before you start
You will need
- git 2.30+
- a GitHub account
You do not need these already — the lab environment below provides them.
You will be able to
- Take a change from branch to merged pull request
- Rebase onto a moved main and resolve a conflict deliberately
- Recover a commit you thought you destroyed
- Remove a secret from history, and know why that is not enough
Cost — Free
— a GitHub account is enough
Nothing to pay in the browser. Open the terminal runs this against a simulated cloud — the same API calls and the same commands, with no account and no bill. The figure above applies only if you build it in your own.
The scenario#
You are contributing to a repository other people are also changing. Main has moved since you branched, your history has a conflict in it, and at some point you will reset something you did not mean to.
All three are normal. None of them should cost you work.
Hands-on environment
Run this lab in a real terminal, free and in your browser. The environment is temporary and yours alone — break it as much as you like.
Open the terminalOpens in Killercoda, in a new tab — keep this page open for the steps.
Run it on your own machine
Run this lab on your own machine. One command starts the environment, with everything the lab needs already installed:
You will need:
- git
git clone https://github.com/EgyKode/EgyKode-lab.git
cd EgyKode-lab
./egykode start
./egykode shellYou need Docker and Git installed. Everything else runs inside the environment. The first start downloads it and takes a few minutes; later starts are seconds.
Not sure what you already have? Run: npm run doctor — it checks and changes nothing.
Anything you tick here is your own record. EgyKode cannot see inside that terminal, so the success criteria stay self-assessed even when the environment checks your work for you.
The daily loop
Step 1 of 4
What you are proving: You can take a change from branch to merged pull request with a history that stays linear
Marking this settles success criterion 1.
git switch -c feat/add-healthcheck # branch from main
# ... edit, then ...
git add -p # stage hunks, not whole files
git commit -m "Add /healthz endpoint"
git fetch origin
git rebase origin/main # replay your work on current main
git push -u origin feat/add-healthcheckgit add -p walks you through each hunk. It is slower than git add . and it
is the reason your commits end up saying one thing each — which is what makes
them reviewable and revertible.
Rebase daily, not at the end. Replaying two commits onto a main that moved this morning is a small conflict you still remember the context for. Replaying three weeks of work is every conflict at once, in a hurry.
What you are proving: You can resolve a conflict by reading both sides, rather than taking one wholesale
Marking this settles success criterion 2.
git rebase origin/main
# CONFLICT (content): Merge conflict in src/app.pyOpen the file. You will see both sides:
<<<<<<< HEAD (what is on main)
timeout = 30
======= (what you wrote)
timeout = 60
>>>>>>> feat/add-healthcheckThe mistake is picking a side because it is quicker. Read both — someone raised that timeout on main for a reason, and your change may need to accommodate it rather than replace it.
# after editing to the correct combined result
git add src/app.py
git rebase --continuegit rebase --abort puts everything back exactly as it was. Nothing is lost by
trying.
What you are proving: You can recover a commit after a hard reset, using the reflog
Marking this settles success criterion 3.
git reset --hard HEAD~3 # three commits, apparently gone
git reflog # every position HEAD has held
# a1b2c3d HEAD@{1}: commit: Add /healthz endpoint
git reset --hard HEAD@{1} # back, intactgit reflog is the undo history for the repository itself. A commit is
reachable for ~90 days even after every branch pointing at it is gone. Almost
nothing done locally in git is actually destructive, and knowing that changes
how confidently you work.
What you are proving: You can remove a secret from history, and explain why that does not make it safe
Marking this settles success criterion 4.
git rm --cached .env
echo ".env" >> .gitignore
git commit -m "Remove .env from tracking"That stops tracking it going forward, and the value is still in history and in every clone. The order that matters:
- Rotate the credential. Assume it is compromised — this is the only step that actually protects anything.
- Then rewrite history (
git filter-repo, or the GitHub secret-scanning flow). - Then force-push, and tell anyone with a clone.
Doing step 2 without step 1 is theatre.
The failure is where the learning is. These are the ones that actually happen:
git push is rejected as non-fast-forward
Main moved. git fetch origin && git rebase origin/main, then push. Do not --force onto a shared branch.
The rebase conflicts in files you never touched
You branched from an old main. Abort, fetch, and rebase onto the current one.
You reset and lost commits
git reflog, find the hash, git reset --hard <hash>. It is almost certainly still there.
A force-push erased a colleague's commits
Use --force-with-lease instead — it refuses when the remote has moved since you last fetched.
Success criteria
0 of 4
The concept behind it
Next up
Lab 6 of 59 on the project path