Skip to content

Pull-request sequence

  • Lesson 7
  • 45 min
  • Module 3: Collaborate through reviews
Lesson 7 of 15 · Git and Team Development EssentialsPull-request sequence

What you will be able to do

Get a change into main the way that teams do it: on its own branch, with a check and a review before the merge. After this lesson, you can take one change through every step of a pull request.

Before you startWhat to know and to have readyAbout 45 minutes

What you need to know

What you need on your computer

  • A terminal in your ~/projects folder. On Windows, use Git Bash, from Terminal bridge: Get a terminal.
  • Git, with your name and email address, from Set up Git: Step 2: tell Git who you are. The commits that you make in the lab show this name.
  • An internet connection, one time, to clone the practice files in Set up the practice lab. That section makes the lab, and shows how to make it again with --reset.
  • You do not need an account on a website. This lesson is a local simulation: the remote is a folder on your computer, and you play both people.
  • The setup script makes its commits with fixed names and dates. So their hashes are the same as in this lesson, for example e058b3f. The commits that you make yourself have different hashes. Use the ones from your own output.

Tested with Git 2.54 on macOS, Windows (Git Bash) and Linux. Git 2.40 or later is required. The setup script for the labs is not yet tested in Git Bash on Windows.

From this module on, you practise in a lab that a script makes for you. The lab has a known start state: the same files, branches and commits as the lessons. If something goes wrong, you can make it again in a few seconds.

Your ~/projects/ticket-notes repository from Modules 1 and 2 does not change. The lab is in a new folder.

  1. Go to your projects folder:

    Terminal window
    cd ~/projects
  2. Get the practice files. Do this step only once. If you already have the nextia-learning-labs folder, run git -C nextia-learning-labs pull to get the newest version instead.

    Terminal window
    git clone https://github.com/Nextia-Intelligence/nextia-learning-labs.git

    The output starts with Cloning into 'nextia-learning-labs'....

  3. Make the lab for this module:

    Terminal window
    sh nextia-learning-labs/C14/setup.sh m03
    Output
    Ready: /Users/amira/projects/c14-lab
    ticket-notes your clone
    sam-notes Sam's clone
    team-remote.git the shared remote
    Next: cd c14-lab/ticket-notes
    To start this scenario again: sh nextia-learning-labs/C14/setup.sh m03 --reset
  4. Go into your clone, and look at the history:

    Terminal window
    cd c14-lab/ticket-notes
    git log --oneline --graph --all
    Output
    * 2e9e37c (HEAD -> main, origin/main, origin/HEAD) Add the on-call number
    | * 6c3828f (origin/add-faq, add-faq) Add a network question to the FAQ
    | * 6b53600 Add FAQ
    |/
    | * 5a15d07 (origin/add-ticket-104) Improve README wording
    | * e34484f Add ticket 104
    |/
    * e058b3f Add ticket 103
    * bae8898 Add a format check for ticket notes
    * eec3e5b Ignore secrets, exports and logs
    * 55b7943 Add contacts
    * 6a0bdd9 Add ticket 102
    * e01bd9f Add first ticket note
    * ec0aceb Add README

    If your hashes are the same, the lab is ready.

The c14-lab folder contains three repositories:

Folder What it is
team-remote.git The shared remote: a bare repository, as in Module 2.
ticket-notes Your clone. You work here as Amira. Your own commits show the name from your global settings (Module 1).
sam-notes The clone of your teammate, Sam Okafor. Its identity is already set to Sam, so commits that you make there show his name.

The other branches, add-ticket-104 and add-faq, are for the next two lessons.

To start again at any time, go to ~/projects and add --reset to the setup command. It deletes only the c14-lab folder, then makes it again:

Terminal window
sh nextia-learning-labs/C14/setup.sh m03 --reset

Without --reset, the script does not delete anything. It stops with The folder c14-lab already exists.

On a team, nobody commits directly to main. Each change goes onto its own branch first. Then the author asks the team to merge it. This request is a pull request (PR): a request to merge a source branch into a target branch after review. GitLab calls the same thing a merge request.

Every PR has two branches. You must always know which is which:

  • The source branch has the new commits. In this lesson, it is add-ticket-template.
  • The target branch is where the commits go. Usually it is main.

This lesson writes the pair as add-ticket-template → main.

Before the merge, two things happen:

  • A check is a command that tests the change automatically, for example a format check or the tests of a program. On a hosted service such as GitHub, a continuous integration (CI) service runs the checks each time that you push to the branch.
  • A review is when a teammate reads the change and decides. The reviewer either approves it, or requests changes: asks the author to fix something first.

At the end, someone merges the PR. You met merging in Module 2: Git joins two lines of history with a new commit that has both as parents.

A sequence diagram with four participants: Author, Remote, Checks and Reviewer. The author makes a branch and commits. The author pushes add-ticket-template to the remote. The author opens the PR, add-ticket-template to main, for the reviewer. The remote runs the check, and the check reports pass or fail to the reviewer. The reviewer fetches and reads the log and diff, then requests changes. The author makes a new commit and pushes. The check runs again. The reviewer approves. The author merges into main, pushes and deletes the branch.
The pull-request sequence. The PR follows the branch, so a new push updates the same PR.

A hosted service shows the PR on a web page. You do not need one to learn the sequence. This lesson does each step with Git commands and text files:

Step In this lesson (simulation) On GitHub (optional, not required)
Make a branch and commit git switch -c, git commit The same.
Push the branch git push -u origin add-ticket-template The same. GitHub then shows a Compare & pull request button.
Open the PR Write the PR description in a text file next to the repository. Select Compare & pull request. Set base to main (the target) and compare to add-ticket-template (the source). Write the description, then select Create pull request.
Run the checks Run sh check.sh yourself. CI runs the checks. You see the result on the Checks tab.
Review In sam-notes, fetch, then read git log and git diff. Write the review in the PR file. The reviewer reads the Files changed tab, then selects Review changes, and then Request changes or Approve.
Respond to the review Make a new commit on the same branch, and push. The same. The PR shows the new commit.
Merge Switch to main, merge with --no-ff, and push. Select Merge pull request, then Confirm merge.
Delete the branch git branch -d and git push origin --delete Select Delete branch. Then run git branch -d on your computer.

Worked example: a template for ticket lines

Section titled “Worked example: a template for ticket lines”

The ticket-notes repository has a check, check.sh. It fails when a line in tickets.txt does not start with Ticket <number>: . New help desk staff do not know this format. Amira wants to add a template that shows it.

Current branch: main. Amira makes sure that main is up to date, because the new branch starts from it:

Terminal (Amira, ticket-notes)
git pull
Output
Already up to date.

She makes the source branch:

Terminal (Amira, ticket-notes)
git switch -c add-ticket-template
Output
Switched to a new branch 'add-ticket-template'

Current branch: add-ticket-template. She makes template.txt with one line:

template.txt
Ticket <number>: <the problem>. <what you did>.

She stages and commits it:

Terminal (Amira, ticket-notes)
git add template.txt
git commit -m "Add a template for ticket lines"
Output
[add-ticket-template d08926d] Add a template for ticket lines
1 file changed, 1 insertion(+)
create mode 100644 template.txt

Before she asks for a review, Amira makes sure of two things. First, the branch contains only her change. main..add-ticket-template means “the commits on add-ticket-template that are not on main”:

Terminal (Amira, ticket-notes)
git log --oneline main..add-ticket-template
Output
d08926d Add a template for ticket lines

One commit, and it is hers. Second, the check passes:

Terminal (Amira, ticket-notes)
sh check.sh
Output
PASS: 3 ticket lines checked

sh check.sh runs the script in the file check.sh. On GitHub, CI runs this same command for each push. Here, you run it yourself.

Terminal (Amira, ticket-notes)
git push -u origin add-ticket-template
Output
To /Users/amira/projects/c14-lab/team-remote.git
* [new branch] add-ticket-template -> add-ticket-template
branch 'add-ticket-template' set up to track 'origin/add-ticket-template'.

PR: add-ticket-template → main. A good PR description answers three questions for the reviewer: what is the problem, what did you change, and how did you check it. Amira writes it in a new file, ~/projects/c14-lab/pr-add-ticket-template.md. The file is next to the repository, not in it, so it does not go into a commit.

c14-lab/pr-add-ticket-template.md
# Add a template for ticket lines
Source: add-ticket-template. Target: main.
## Problem
New help desk staff write ticket lines in different formats.
Then check.sh fails, and they do not know why.
## Change
Add template.txt. It shows the format that check.sh expects.
## How I checked
- `git log --oneline main..add-ticket-template` shows only my commit.
- `sh check.sh` on the branch: PASS: 3 ticket lines checked.

Sam reviews in his own clone. He fetches, so that his record of the remote has the new branch:

Terminal (Sam, sam-notes)
cd ../sam-notes
git fetch
Output
From /Users/amira/projects/c14-lab/team-remote
* [new branch] add-ticket-template -> origin/add-ticket-template

He reads the commits and the change. The diff uses three dots: main...origin/add-ticket-template shows only the changes that the branch made. The next lesson explains why three dots matter.

Terminal (Sam, sam-notes)
git log --oneline main..origin/add-ticket-template
git diff main...origin/add-ticket-template
Output
d08926d Add a template for ticket lines
diff --git a/template.txt b/template.txt
new file mode 100644
index 0000000..9333f70
--- /dev/null
+++ b/template.txt
@@ -0,0 +1 @@
Ticket <number>: <the problem>. <what you did>.

The change is correct, but the placeholders alone are hard to follow. Sam requests changes. He adds his review to the end of the PR file:

c14-lab/pr-add-ticket-template.md (end)
## Review (Sam): request changes
- Blocking: please add one real example line under the template.
New staff learn the format faster from an example.

Current branch: add-ticket-template in Amira’s clone. She does not open a new PR. She adds a commit to the same branch:

template.txt
Ticket <number>: <the problem>. <what you did>.
Example: Ticket 101: printer offline. Restarted the spooler.
Terminal (Amira, ticket-notes)
cd ../ticket-notes
git commit -am "Add an example to the ticket template"
sh check.sh
git push
Output
[add-ticket-template 48f03a7] Add an example to the ticket template
1 file changed, 1 insertion(+)
PASS: 3 ticket lines checked
To /Users/amira/projects/c14-lab/team-remote.git
d08926d..48f03a7 add-ticket-template -> add-ticket-template

A PR follows its source branch, not one fixed commit. So the push updates the PR: on GitHub, the new commit appears in the same PR, and the checks run again.

Sam fetches and reads again. Now the branch has two commits:

Terminal (Sam, sam-notes)
git fetch
git log --oneline main..origin/add-ticket-template
Output
From /Users/amira/projects/c14-lab/team-remote
d08926d..48f03a7 add-ticket-template -> origin/add-ticket-template
48f03a7 Add an example to the ticket template
d08926d Add a template for ticket lines

He reads the new commit with git show 48f03a7, and approves. He adds one line to the PR file: ## Review (Sam): approved.

Current branch: main in Amira’s clone. PR: add-ticket-template → main. She switches to the target branch, and pulls, because a teammate can push to main during the review:

Terminal (Amira, ticket-notes)
git switch main
git pull
Output
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
Already up to date.

She merges the source branch into main:

Terminal (Amira, ticket-notes)
git merge --no-ff --no-edit add-ticket-template
Output
Merge made by the 'ort' strategy.
template.txt | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 template.txt
  • --no-ff means “no fast-forward”. Here, main did not move after the branch started, so Git could only move the main label forward. --no-ff makes a merge commit anyway. The merge commit records that the PR was merged at this point. GitHub’s Create a merge commit option does the same. The third lesson of this module compares it with the other options.
  • --no-edit keeps the message that Git suggests, so no editor opens.

The merge result is new: it combines the branch with the newest main. So she runs the check again, then looks at the history:

Terminal (Amira, ticket-notes)
sh check.sh
git log --oneline --graph -5
Output
PASS: 3 ticket lines checked
* dbdc0c1 (HEAD -> main) Merge branch 'add-ticket-template'
|\
| * 48f03a7 (origin/add-ticket-template, add-ticket-template) Add an example to the ticket template
| * d08926d Add a template for ticket lines
|/
* 2e9e37c (origin/main, origin/HEAD) Add the on-call number
* e058b3f Add ticket 103

The merge commit dbdc0c1 has two parents: 2e9e37c from main and 48f03a7 from the branch. She pushes main:

Terminal (Amira, ticket-notes)
git push
Output
To /Users/amira/projects/c14-lab/team-remote.git
2e9e37c..dbdc0c1 main -> main

The work is in main now, so the branch label is not needed. She deletes it on her computer, then on the remote:

Terminal (Amira, ticket-notes)
git branch -d add-ticket-template
git push origin --delete add-ticket-template
Output
Deleted branch add-ticket-template (was 48f03a7).
To /Users/amira/projects/c14-lab/team-remote.git
- [deleted] add-ticket-template

-d deletes a branch only when its commits are merged. The commits are not deleted: they are part of main.

Do the worked example in your lab. You play Amira in ticket-notes and Sam in sam-notes. At each step, say the current branch and the PR (add-ticket-template → main) aloud or in a note.

  1. In ~/projects/c14-lab/ticket-notes, run git status. The output must show On branch main and working tree clean.

  2. Run git pull. The output is Already up to date.

  3. Make the source branch:

    Terminal window
    git switch -c add-ticket-template
  4. In your editor, make template.txt with the template line from the worked example. Save it.

  5. Stage and commit the file:

    Terminal window
    git add template.txt
    git commit -m "Add a template for ticket lines"
  6. Run git log --oneline main..add-ticket-template. The output shows one commit: yours.

  7. Run sh check.sh. The output is PASS: 3 ticket lines checked.

  8. Push the branch:

    Terminal window
    git push -u origin add-ticket-template

    The output includes * [new branch].

  9. In your editor, make ~/projects/c14-lab/pr-add-ticket-template.md. Write the source, the target, and the three sections: Problem, Change and How I checked.

  10. Simulation: review as Sam. Go to Sam’s clone and fetch:

    Terminal window
    cd ../sam-notes
    git fetch

    The output includes [new branch] add-ticket-template -> origin/add-ticket-template.

  11. Read the change:

    Terminal window
    git log --oneline main..origin/add-ticket-template
    git diff main...origin/add-ticket-template

    The diff shows one new file, template.txt.

  12. Add Sam’s review to the end of the PR file: request changes, and ask for an example line.

  13. Go back to your clone. Make sure that you are on the source branch:

    Terminal window
    cd ../ticket-notes
    git status

    The output starts with On branch add-ticket-template.

  14. Add the example line to template.txt. Save it. Then commit, check and push:

    Terminal window
    git commit -am "Add an example to the ticket template"
    sh check.sh
    git push
  15. Run cd ../sam-notes, then git fetch, then git log --oneline main..origin/add-ticket-template. The output shows two commits. Add ## Review (Sam): approved to the PR file.

  16. In ticket-notes, switch to the target branch and update it:

    Terminal window
    git switch main
    git pull
  17. Merge the source branch:

    Terminal window
    git merge --no-ff --no-edit add-ticket-template

    The output starts with Merge made by the 'ort' strategy.

  18. Run sh check.sh. The output is PASS: 3 ticket lines checked.

  19. Run git log --oneline --graph -5. The newest commit is Merge branch 'add-ticket-template', and it has two lines under it.

  20. Push main:

    Terminal window
    git push
  21. Delete the branch on your computer and on the remote:

    Terminal window
    git branch -d add-ticket-template
    git push origin --delete add-ticket-template
  22. Run git branch -a. add-ticket-template and remotes/origin/add-ticket-template are not in the list.

Prepare a simulated PR for a new change. Use a branch name of your choice, for example add-ticket-105. The change can be a new line in tickets.txt, or a new contact in contacts.txt.

  1. Start from an up-to-date main, and make the source branch.
  2. Make one commit. Check that the branch contains only your commit, and that sh check.sh passes.
  3. Push the branch.
  4. Write ~/projects/c14-lab/pr-<your branch>.md with the source, the target, and the sections Problem, Change and How I checked. In How I checked, write the commands that you ran and their results.

Do not merge yet. A reviewer must be able to understand and check the PR from the file and the branch alone.

Show a model answer
Terminal (Amira, ticket-notes)
git switch main
git pull
git switch -c add-ticket-105

Add one line to the end of tickets.txt, and save it:

tickets.txt (new line)
Ticket 105: new starter has no email account. Created the account.
Terminal (Amira, ticket-notes)
git commit -am "Add ticket 105"
git log --oneline main..add-ticket-105
sh check.sh
git push -u origin add-ticket-105
Output (end)
11525d0 Add ticket 105
PASS: 4 ticket lines checked
To /Users/amira/projects/c14-lab/team-remote.git
* [new branch] add-ticket-105 -> add-ticket-105
branch 'add-ticket-105' set up to track 'origin/add-ticket-105'.
c14-lab/pr-add-ticket-105.md
# Add ticket 105
Source: add-ticket-105. Target: main.
## Problem
Ticket 105 (a new starter with no email account) is closed,
but it is not in the ticket notes.
## Change
Add one line for ticket 105 to tickets.txt.
## How I checked
- `git log --oneline main..add-ticket-105` shows one commit, "Add ticket 105".
- `git diff --stat main...add-ticket-105` shows only tickets.txt, 1 line added.
- `sh check.sh` on the branch: PASS: 4 ticket lines checked.

A good problem statement says what is wrong without the change. Good validation notes give the exact commands and results, so the reviewer can repeat them. “I tested it” is not enough.

Common mistake

I committed on main, not on a branch

Symptom: you forgot git switch -c, and committed on main. git status shows:

Output
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean

Do not follow the hint and push. A push sends the commit straight to the team’s main, with no check and no review.

Cause: the commit went onto the branch that HEAD pointed to, which was main.

Fix: put a new branch label on your commit, then move main back to where the remote has it.

  1. Make the source branch from where you are now. It contains your commit:

    Terminal window
    git switch -c add-ticket-template
  2. Move the main label back to origin/main. You are not on main now, so this is allowed:

    Terminal window
    git branch -f main origin/main
    Output
    branch 'main' set up to track 'origin/main'.
  3. Check the result with git log --oneline -3:

    Output
    d08926d (HEAD -> add-ticket-template) Add a template for ticket lines
    2e9e37c (origin/main, origin/HEAD, main) Add the on-call number
    e058b3f Add ticket 103

Your commit is on add-ticket-template, and main is the same as origin/main again. Continue with the push and the PR. Use this fix only for a commit that you did not push.

Common mistake

The PR shows commits that are not mine

Symptom: the reviewer sees more commits and files than you changed:

Terminal window
git log --oneline main..origin/add-ticket-template
git diff --stat main...origin/add-ticket-template
Output
43b832b Add a template for ticket lines
6c3828f Add a network question to the FAQ
6b53600 Add FAQ
faq.txt | 5 +++++
template.txt | 1 +
2 files changed, 6 insertions(+)

Cause: you made the branch while you were on add-faq, not on main. git switch -c starts the new branch from the branch that you are on, so the new branch contains the FAQ commits too. If you merge it, they go into main without their own review.

Fix: make a correct branch from main, and copy only your file to it. git show add-ticket-template:template.txt prints the file as it is on the wrong branch, and > writes it into the folder.

  1. git switch main
  2. git switch -c add-template
  3. git show add-ticket-template:template.txt > template.txt
  4. git add template.txt, then git commit -m "Add a template for ticket lines"
  5. Run git log --oneline main..add-template. It shows only your commit.
  6. Push the new branch with git push -u origin add-template, and use it for the PR.
  7. Delete the wrong branch on the remote and on your computer: git push origin --delete add-ticket-template, then git branch -D add-ticket-template.

-D deletes a branch even when its commits are not merged. Use it only after you copied your work. To prevent this mistake, run git status before git switch -c, and make sure that it says On branch main.

Check your understanding

Predict: Sam requests changes on add-ticket-template → main. Amira adds a commit to add-ticket-template and pushes. Does she need to open a new PR? What does Sam see when he fetches?

Show the answer

No new PR. A PR follows its source branch, not one fixed commit. After the push, the same PR contains both commits. When Sam fetches, origin/add-ticket-template moves forward, and git log --oneline main..origin/add-ticket-template shows two commits. On GitHub, the checks also run again for the new commit.

Check your understanding

Practical check: before you ask for a review, show that your branch contains only your commits, which files it changes, and that the check passes.

Show the answer

On your source branch, run:

  • git log --oneline main..HEAD: only your commits are in the list.
  • git diff --stat main...HEAD: only the files that you meant to change are in the list.
  • sh check.sh: the output starts with PASS.

Write these commands and their results in the How I checked section of your PR description.

Recap

  • A pull request asks to merge a source branch into a target branch after a check and a review. Always know both branches.
  • The sequence is: branch, commit, check, push, open the PR, review, respond, merge, delete the branch.
  • To respond to a review, push a new commit to the same branch. The PR updates itself.
  • git merge --no-ff always makes a merge commit, which records where the PR was merged.
  • Run the check again after the merge, because the merge result is new.
  • In this lab, sh nextia-learning-labs/C14/setup.sh m03 --reset from ~/projects gives you a fresh start.

Next: Read and review diffs