Welcome to our collaborative Git exercise! In this activity, you will first work independently, then in pairs and teams, to practice branching, committing, resolving merge conflicts, and making pull requests.
- Creating and pushing branches.
- Making pull requests to a protected main branch.
- Working with shared files in a team.
- Encountering and resolving merge conflicts.
- Organizing contributions from many people into one shared project.
Setup remotes (run once per local clone):
# already set automatically when you clone YOUR fork
git remote -v
# add the class repo as 'upstream'
git remote add upstream https://github.com/<class-org-or-user>/<class-repo>.git
git fetch upstreamKeep your fork up to date (before new work):
git checkout main
git fetch upstream
git merge --ff-only upstream/main
git push origin main- Make a fork of this repository on your local GitHub account and clone it to your computer.
- You will see folders for the morning section and the afternoon section. Choose the appropriate folder to work in.
- Create a new branch named
solo/<onyen>. - Now navigate to the
solo/folder (unrelated to branch name). Inside it, create a new text file named<onyen>.txt. - Add your full name inside the file.
- Stage, commit, and push your branch to your fork on GitHub.
- Open a pull request from your fork’s branch to the upstream repository’s
mainwith the titlesolo: <onyen>.
Each student will have their own file, so there should be no conflicts in this step.
-
Your group of 4–6 students is a team. Choose a unique team identifier (for example,
UNC-Alpha,Sharks,Team42). -
One person in the team acts as Integrator. The Integrator’s fork will be the team’s working fork. The Integrator:
- Adds teammates as collaborators on their fork (Repo → Settings → Collaborators).
- Creates the base branch
team/<team-id>/baseon their fork. - Creates
teams/<team-id>/roster.mdwith:# Team <team-id> Roster (alphabetical by last name) Members:
-
All teammates add the team remote (the Integrator’s fork) to their local clones:
git remote add team https://github.com/<integrator-username>/<class-repo>.git git fetch team
-
Each pair branches from the team base branch and pushes to the team remote:
git checkout -b team/<team-id>/pair-<lastname1>-<lastname2> team/<team-id>/base # edit teams/<team-id>/roster.md (add exactly one line under 'Members:') git add teams/<team-id>/roster.md git commit -m "Add <Name1> + <Name2> — Team name: <team name>" git push -u team team/<team-id>/pair-<lastname1>-<lastname2>
OR (no collaborator access): push to your own fork and open a PR into the Integrator’s fork base branch.
-
The Integrator opens PRs (or reviews incoming PRs) from each pair branch into
team/<team-id>/integration(created fromteam/<team-id>/base). Resolve conflicts as specified.
- The Integrator should create a new branch
team/<team-id>/integrationfrom the base on their fork. - Then, merge each pair branch into the integration branch, one by one.
- This will cause conflicts in the
roster.mdfile. - Resolve the conflicts by keeping only one
Members:header, then making sure all lines are included. - The final list of pairs must be in alphabetical order by last name.
- Each line must show both names and the team name.
- This will cause conflicts in the
- After all conflicts are resolved and merged, push the integration branch.
- The Integrator should append the team’s final roster to the file
class-roster.md.- Add a section starting with
## <team-id>followed by the list of pairs.
- Add a section starting with
- Commit and push the update to the integration branch on their fork.
- Open a pull request from the Integrator’s fork
team/<team-id>/integrationto the upstream repository’smainwith the title<team-id> → class-roster.
git add <file>— stage changes to be committed.git branch -vv— show local branches and their remote tracking.git checkout -b <new-branch>— create and switch to a new branch.git checkout <branch>— switch to an existing branch.git clean -fd— remove untracked files and folders (use with caution).git clone <repo-url>— clone the repository to your computer.git commit -m "<message>"— commit staged changes with a message.git diff— show unstaged changes.git diff --staged— show staged but uncommitted changes.git fetch --all— fetch all updates from remote branches.git log --oneline --graph --decorate --all— visualize branch history.git merge <branch>— merge another branch into your current branch.git merge --abort— cancel a merge attempt.git pull --ff-only— update your branch with the latest changes from remote.git push -u origin <branch>— push your branch to GitHub and set upstream.git reflog— view recent HEAD movements to recover from mistakes.git remote add upstream <url>— add the class repo as upstream.git remote add team <url>— add the Integrator’s fork as team.git reset --hard origin/main— reset your branch to match your fork’s main branch.git restore <file>— discard changes to a file before staging.
Update local main from upstream:
git checkout main
git fetch upstream
git merge --ff-only upstream/main
git push origin main-
Confusing branch names with folder names.
Remember:solo/{{ONYEN}}is the branch name;solo/is the folder. Both are required. -
Forgetting to pull the latest changes before branching or merging.
Always rungit pull --ff-onlyonmainor your base branch to avoid diverging histories. -
Leaving merge conflict markers in files.
Always remove<<<<<<<,=======, and>>>>>>>. Ensure the finalroster.mdis clean and alphabetized.
git status— check current branch and file state.git log— view commit history.