CSCD 211 › lessons

The professional git workflow: branch, commit, push, pull request, merge

Week 0 onboarding, the lesson the intro-to-GitHub page promised. About 20 minutes to read, then about 15 minutes to run the loop once yourself. You already know the four-command loop (add, commit, push, pull). This adds the two moves a software team uses on top of it, the branch and the pull request, and walks the whole loop end to end with the exact commands and the exact output you will see. Every command below was run on a real machine and the output is copied in, so nothing here is a guess. Every mistake in this loop is recoverable, so it is safe to fumble while you learn it.

The one promise of this lesson. By the end you can take one lab from start to finish the way a team does: branch off main, commit your work, push the branch, open a pull request, merge it, and pull main back down for the next task. This is the loop you run for every lab, so learning it once pays off nineteen times.


Before you start

You should be able to tick each of these. If one is shaky, do the matching Week 0 onboarding lesson first, then come back.


Why a branch and a pull request, when add-commit-push already works

It would be faster this week to edit main directly and skip the rest. It is not faster over a quarter, and it is not how any team you will join actually works. Two problems show up the moment more than one change is in flight, and the branch and the pull request each solve one of them.

The board ties it together: anyone helping you can see what is done, what is in flight, and what is next. That is the difference between writing code and building software, and it is the habit this course exists to build.


Atom 1: a branch is a safe place to work

Never build a lab directly on main. Make a branch named for the lab, and move onto it in one command:

git switch -c lab01-comparable-comparator

The -c means create, and the name says which lab and what it is. Here is the real output:

Switched to a new branch 'lab01-comparable-comparator'

You are now on the branch. The files look the same, because a fresh branch starts as an exact copy of main; the difference is that every commit you make now lands on the branch, and main stays untouched until you choose to merge.

Check yourself. You just ran git switch -c lab03-stack. You edit a file and commit. Is main changed?


Atom 2: commit on the branch, starting with the stub

The commit loop on a branch is the same add then commit you already know. The first commit on any lab is the stub: a skeleton that compiles, with every required method present and returning a placeholder. Put the word stub in the message, and push it within 24 hours of the lab opening:

git add .
git commit -m "stub: Course compiles with compareTo placeholder"

The real output of that commit:

[lab01-comparable-comparator 88f29f1] stub: Course compiles with compareTo placeholder
 1 file changed, 2 insertions(+), 1 deletion(-)

Git tells you the branch, a short id for the snapshot (88f29f1), your message, and what changed. After the work itself, commit each time a piece works, not once at the end, so each commit is a save point you can return to. The stub commit is the running example below, and the same loop carries the rest.

What you should see now. Run git status -sb. A clean tree on your branch looks like this, with nothing listed as changed:

## lab01-comparable-comparator

Check yourself. You ran git add . then git commit, and have changed nothing since. Predict what git status -sb will show, and why.


Atom 3: push the branch to GitHub

A commit is on your machine only until you push. The first time you push a new branch, name where it goes with -u origin and the branch name, which also sets it to track that branch so later pushes are just git push:

git push -u origin lab01-comparable-comparator

The real output of a first push, captured on a practice repository:

To github.com:EWU-CSCD211-Su26/your-repo.git
 * [new branch]      lab01-comparable-comparator -> lab01-comparable-comparator
branch 'lab01-comparable-comparator' set up to track 'origin/lab01-comparable-comparator'.

The [new branch] line is GitHub confirming your branch now exists there too. After this first push, every later push on the same branch is just git push, because the branch already knows where it belongs. One small change to watch for: now that the branch is pushed and tracking, git status -sb adds an ...origin/lab01-comparable-comparator suffix to the branch line, which just means it knows its match on GitHub. That is expected, not an error.

Check yourself. You committed three times on your branch but have not pushed. Your laptop dies. How many of those commits are on GitHub?


Atom 4: open a pull request

When the work meets the lab's acceptance criteria, open a pull request: a request to merge your branch into main, and the place your work gets checked. You can open it from the green "Compare and pull request" button that GitHub shows after a push, or from the command line:

gh pr create

It prompts you for a title and a description. In the description, link the issue so it closes automatically when the PR merges, using your lab's issue number from the issue page:

Closes #5

Opening the PR moves the task to In Review. This is the step that makes the work a team thing instead of a private one: the tests run on the PR, and any feedback lands there as comments you can answer.

Check yourself. Your PR is open and a test fails on it. You fix the bug locally. What do you do to update the same pull request, and do you open a new one?


Atom 5: review, merge, and move to the next task

Once the PR is approved and the checks pass, click the green Merge button on the pull request page. GitHub merges your branch into main for you, the pull request shows as merged, and the linked issue closes, so the task moves to Done on the board. The merge happens on GitHub, not on your machine, so there is nothing to run in your terminal for this step.

Back on your machine, bring that merge down so your local copy is current, then start the next lab:

git switch main
git pull

The pull brings the merge you just made on GitHub down to your local main. The real output:

From github.com:EWU-CSCD211-Su26/your-repo
   3ef559f..1510050  main -> origin/main
Updating 3ef559f..1510050
Fast-forward
 Course.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Delete the finished branch; it has done its job. Then run the whole loop again for the next task. By the end of the quarter it will feel like breathing.

One more step makes a real lab truly done: Done on GitHub is not the same as turned in. You also submit a zip of your project that matches your merged commit to the Canvas lab assignment, which is your official record. Merging completes the GitHub half, and the Canvas zip is the other half, so a lab is not done until both are true. The intro-to-GitHub lesson covers the zip step.

Check yourself. You merged your PR on GitHub, then kept working on your machine without running git pull on main. What is now true about your local main?


If it goes wrong

Three real failures happen to almost everyone the first few times. Each one is recoverable, and each message below is the actual text git prints, so you can recognize it on sight.

Your push is rejected with "fetch first"

You run git push and see this:

 ! [rejected]        lab01-comparable-comparator -> lab01-comparable-comparator (fetch first)
error: failed to push some refs to 'github.com:EWU-CSCD211-Su26/your-repo.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

It means GitHub has a commit you do not have yet, often because you pushed from another machine or merged a PR on the website. The fix is in the hint: run git pull to bring those commits down, then git push again. This is exactly why the next-task step ends with git pull.

A merge conflict

When two changes touch the same lines, a merge stops and asks you to choose:

Auto-merging Course.java
CONFLICT (content): Merge conflict in Course.java
Automatic merge failed; fix conflicts and then commit the result.

Run git status and the file shows as UU, meaning unmerged on both sides. Open it, and git has written both versions in, marked like this:

<<<<<<< HEAD
    String title = "main version";
=======
    String title = "branch version";
>>>>>>> lab02-feature

Edit the file so it holds the one correct version, delete all three marker lines (<<<<<<<, =======, >>>>>>>), then git add the file and git commit to finish the merge. A conflict is git asking a question it cannot answer for you, not a sign you broke something.

You forgot to branch and committed on main

You did the work, then noticed git status says ## main. Nothing is lost. Make the branch now, which carries your new commits onto it, and your work moves to where it belongs:

git switch -c lab01-comparable-comparator

Your commits are now on the branch. If you also want main clean again, ask for help in office hours before rewinding it, so you do not lose anything by accident.


The same loop in IntelliJ (coming with screenshots)

IntelliJ has a button for each step in this loop. The verified, click-by-click version, with a real screenshot of every panel, is being captured from the installed IntelliJ and will be added to this lesson. Until then, the terminal commands above are the source of truth, and they do the identical thing the buttons do, so you can run the whole loop today without waiting.


Show what you can do

Make this small artifact, then write the reflection.


Where this goes next

Lab 1 has you run this exact loop for real: branch, stub commit within 24 hours, build Course.compareTo and a Comparator, push, open a pull request, and merge. The in-class standups use the same vocabulary, where you report what you committed, what is in flight, and what is blocking you. The IntelliJ visual walkthrough adds the buttons on top of the commands you now understand.