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.
- [ ] I can name the three places my code lives: the working folder, the staging area, the repository.
- [ ] I can run the loop
git add, thengit commit -m "message", thengit push. - [ ] I know a commit is saved only on my machine until I push it to GitHub.
- [ ] I have accepted a lab on Canvas and have my repository cloned to my machine.
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.
- A branch keeps
mainworking while you build. You experiment on a copy, and if the work goes sideways,mainis still safe and still compiles, so you never break the one version everything else depends on. - A pull request is where the work gets checked before it joins
main. The automated tests run on it and you get feedback, and only then does it merge, so this is where code gets better instead of just getting written.
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.
- Artifact. In your own lab repository, run the whole loop once on a throwaway branch:
git switch -c practice-loop, make a one-line change to the README, commit it with a real message, push the branch, open a pull request, merge it, thengit switch mainandgit pull. You have now done one full professional loop. - Reflection ("I can ..."). Write one line for each, in your own words: I can make a branch and say why I do not build on
main; I can push a branch the first time and explain what-u origindoes; I can open a pull request and say what it is for; I can read a rejected push and a merge conflict and know the fix. Then name one thing you could recover from now that would have stopped you this morning.
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.