Chapter 07Lesson 02~165 minutes

Pull Requests, Drafts, Linked Issues, Change Sets, and Collaboration Patterns: Guided Hands-On Workflow and Core Operations

Create a disposable issue, topic branch, and draft pull request; inspect its base/head refs, commits, diff, checks, and conversation; move between draft and ready state; update metadata; add commits; and verify every change through Git plus GitHub evidence.

gh prDraft PRLinked issueVerification

Learning objectives

  • Create a disposable public repository, Issue, topic branch, and draft pull request with explicit base/head coordinates.
  • Inspect Conversation, Commits, Files changed, checks, base/head OIDs, and linked Issue state before and after each mutation.
  • Move the PR between draft and ready states and edit title/body without changing the Git commit graph.
  • Request a reviewer when a safe collaborator exists, while preserving a no-second-account mandatory path.
  • Push an additional commit and prove that the existing PR updates rather than requiring a new PR.
  • Compare local three-dot Git evidence with structured gh pr and versioned REST evidence.
Availability: GitHub.com + GitHub Free + one disposable public personal repository is sufficient. Requesting a specific human review requires an eligible collaborator/reviewer; that step has an optional live path and a mandatory read-only/simulation path so the lesson remains completable by one account. No merge is required.
Shell portability: multi-line examples with trailing \, command substitution such as $(...), and printf are labeled Git Bash/Bash/zsh. In PowerShell, use the same Git/gh arguments on one line or use the backtick for line continuation; PowerShell-native alternatives are shown for the key file-writing steps. The GitHub resource semantics are identical.

1. Scenario: a retry-note change controlled through a draft PR

You will create c07-pr-workflow-lab, open Issue “Document retry policy,” create topic branch docs/retry-policy, and open a draft PR to main. The PR body will use Closes #N, but the lab will not merge, so the Issue remains open. You will then add another commit, mark the PR ready, inspect checks, and optionally request a real collaborator review.

Disposable-only: do not reuse a production repository, protected release branch, or employer review queue. The lab intentionally creates review notifications and hosted metadata.

2. Preflight: identity, repository collision, and current GitHub state

gh auth status --active --hostname github.com
OWNER=$(gh api user --jq .login)
REPO="c07-pr-workflow-lab"

gh repo view "$OWNER/$REPO" >/dev/null 2>&1 && {
  echo "STOP: $OWNER/$REPO already exists" >&2
  exit 2
}

git --version
gh --version

PowerShell equivalent for the variables is $OWNER = gh api user --jq .login and $REPO = "c07-pr-workflow-lab". The collision check is a safety gate: never delete or overwrite a repository merely because its name matches a tutorial.

3. Create the repository and Issue; capture the default branch

gh repo create "$OWNER/$REPO" --public --add-readme --clone
cd "$REPO"
DEFAULT_BRANCH=$(git branch --show-current)

ISSUE_URL=$(gh issue create   --title "Docs: document retry policy"   --body "Synthetic Chapter 07 issue for PR linkage practice.")
ISSUE_NUMBER=${ISSUE_URL##*/}

printf 'owner=%s repo=%s default=%s issue=%s
'   "$OWNER" "$REPO" "$DEFAULT_BRANCH" "$ISSUE_NUMBER"

PowerShell: $DEFAULT_BRANCH = git branch --show-current; $ISSUE_URL = gh issue create ...; $ISSUE_NUMBER = ($ISSUE_URL -split "/")[-1]. The Issue is a GitHub record. No Git ref changed when you created it.

4. Create a topic branch and push one commit

git switch -c docs/retry-policy

cat >> README.md <<'EOF'

## Retry policy
Retry transient operations only when the operation is safe to repeat.
EOF

git add README.md
git commit -m "docs: add retry policy note"
git push -u origin docs/retry-policy

HEAD1=$(git rev-parse HEAD)
printf 'first_head=%s
' "$HEAD1"

PowerShell file-writing alternative: Add-Content README.md "`n## Retry policy`nRetry transient operations only when the operation is safe to repeat.". The push creates/updates refs/heads/docs/retry-policy in the hosted repository. No PR exists yet.

5. Predict, then open the draft pull request

Prediction A: opening the PR will create hosted PR metadata and GitHub PR refs, but the topic branch OID should stay HEAD1 and main should not move.

PR_BODY=.c07-pr-body.md
cat > "$PR_BODY" <<EOF
Closes #$ISSUE_NUMBER

Adds the retry guidance required by the synthetic issue.
EOF

PR_URL=$(gh pr create   --base "$DEFAULT_BRANCH"   --head docs/retry-policy   --draft   --title "docs: document retry policy"   --body-file "$PR_BODY")
PR_NUMBER=${PR_URL##*/}

printf 'pr=%s
' "$PR_URL"

The PR author controls the head branch in this same-repository lab. Opening the PR creates notifications/timeline state, so treat rapid automated PR creation as a real platform mutation rather than a free read operation.

6. Inspect the PR from three independent perspectives

gh pr view "$PR_NUMBER" --json   number,title,state,isDraft,baseRefName,baseRefOid,headRefName,headRefOid,   commits,files,closingIssuesReferences,reviewRequests,statusCheckRollup,url

gh pr diff "$PR_NUMBER" --name-only

git fetch origin "$DEFAULT_BRANCH" docs/retry-policy

git log --oneline --decorate "origin/$DEFAULT_BRANCH..origin/docs/retry-policy"
git diff --stat "origin/$DEFAULT_BRANCH...origin/docs/retry-policy"

git ls-remote origin "refs/pull/$PR_NUMBER/*"

Expected evidence: one topic commit, README.md in the diff, the PR is draft, base is the default branch, and the closing-Issue relationship is visible because the PR targets the default branch. If the repository has no CI workflow, an empty check rollup is valid evidence—not an error to “fix.”

7. Verify the hosted PR through the versioned REST API

gh api   -H "Accept: application/vnd.github+json"   -H "X-GitHub-Api-Version: 2026-03-10"   "repos/$OWNER/$REPO/pulls/$PR_NUMBER"   --jq '{number,state,draft,mergeable,base:.base.ref,base_sha:.base.sha,head:.head.ref,head_sha:.head.sha,changed_files,commits}'

If mergeable is null, GitHub is still computing the test merge. Re-run the read later; do not mutate the PR to force a value.

8. Edit title/body: GitHub metadata changes, Git OIDs do not

Prediction B: changing PR title/body should change the PR resource but not HEAD1, the hosted topic branch OID, or the base branch OID.

cat > "$PR_BODY" <<EOF
Closes #$ISSUE_NUMBER

Adds retry safety guidance and an operator example.
EOF

gh pr edit "$PR_NUMBER"   --title "docs: clarify retry policy"   --body-file "$PR_BODY"

gh pr view "$PR_NUMBER" --json title,body,headRefOid,baseRefOid,closingIssuesReferences

git rev-parse HEAD

9. Exercise draft and ready-for-review state

gh pr view "$PR_NUMBER" --json number,isDraft,state

gh pr ready "$PR_NUMBER"
gh pr view "$PR_NUMBER" --json number,isDraft,state,reviewRequests

# Demonstrate the inverse transition, then return to ready.
gh pr ready "$PR_NUMBER" --undo
gh pr view "$PR_NUMBER" --json number,isDraft,state

gh pr ready "$PR_NUMBER"

No Git commit changes in this sequence. The PR stays the same number and same base/head branches. The operation changes collaboration stage.

10. Request review—live only when an eligible collaborator exists

Requesting a review is a notification and permission-sensitive action. Current GitHub documentation requires write access to request a review and an eligible repository reader/reviewer. A solo learner should not invent a username or spam a stranger.

# Read-only: inspect current requests.
gh pr view "$PR_NUMBER" --json reviewRequests,reviews

# OPTIONAL live path only with a consenting eligible collaborator:
# REVIEWER="collaborator-login"
# gh pr edit "$PR_NUMBER" --add-reviewer "$REVIEWER"
# gh api -H "Accept: application/vnd.github+json" #   -H "X-GitHub-Api-Version: 2026-03-10" #   "repos/$OWNER/$REPO/pulls/$PR_NUMBER/requested_reviewers"
Mandatory no-second-account completion: explain which permission boundary the request crosses, show the documented command shape, and verify the existing empty/non-empty review request list. Do not send a review request to an unrelated user.

11. Push a second commit and watch the same PR evolve

cat >> README.md <<'EOF'

Operator example: retry a read-only health probe after a transient network error.
EOF

git add README.md
git commit -m "docs: add retry operator example"
git push
git fetch origin "$DEFAULT_BRANCH" docs/retry-policy

HEAD2=$(git rev-parse HEAD)
printf 'second_head=%s
' "$HEAD2"

gh pr view "$PR_NUMBER" --json number,headRefOid,commits,files,updatedAt

git log --oneline "origin/$DEFAULT_BRANCH..origin/docs/retry-policy"
git diff --stat "origin/$DEFAULT_BRANCH...origin/docs/retry-policy"

The PR number stays constant because its head ref is the same. The head ref now points to a new OID, so GitHub recalculates the commit list, file diff, merge test, and any configured checks. This is the key operational reason you update a PR by pushing to its head branch rather than opening a replacement PR for every review fix.

12. Inspect checks without pretending a check exists

gh pr view "$PR_NUMBER" --json statusCheckRollup,headRefOid

# If the repository reports checks, inspect them in detail:
gh pr checks "$PR_NUMBER" || true

On a repository with no Actions workflow or external check integration, “no checks reported” is expected. The || true is used only so an instructional shell session can continue when the CLI reports a non-success status for the absence/pending state; automation should handle exit codes intentionally. gh pr checks also has a documented exit code for pending checks.

13. Challenge: choose the correct surface

For each scenario, choose Git, PR metadata, Issue metadata, or checks before you act:

  • The title says the wrong subsystem, but the commits are correct → edit PR metadata, not Git history.
  • The PR includes an accidental generated file → change the branch content/commit, then push; do not hide it with a title edit.
  • The work should no longer auto-close the Issue → remove/change the closing relationship in the PR body or development link.
  • A required CI job failed → inspect the check/job evidence; changing the PR from draft to ready does not repair code.

14. Cleanup and rollback

Do not merge the lab PR. Close it, leave a final synthetic-lab note, and archive only the disposable repository after verifying its owner/name. Archiving is reversible and avoids requiring the broader repository-delete credential scope. Permanent deletion is optional and can be performed later from the repository danger-zone UI after a second identity check.

gh pr close "$PR_NUMBER" --comment "Chapter 07 disposable lab complete."
cd ..
printf 'archive-check=%s/%s
' "$OWNER" "$REPO"
gh repo archive "$OWNER/$REPO"
rm -rf "$REPO"
Cleanup boundary: archiving makes the lab repository read-only but preserves evidence and is reversible. Permanent deletion is destructive; if you choose it later, verify the exact disposable owner/name in the repository danger zone immediately before confirming.

15. Lesson summary

You created a PR without treating it as a branch copy: the head branch carried commits, while the PR carried review/integration metadata. Metadata edits and draft/ready transitions left Git OIDs alone. Pushing a new commit moved the head ref and updated the same PR. Git, gh, PR refs, and REST each provided independent evidence.

Knowledge check

Why did the second push update the same pull request?

What should change when you edit only the PR title?

Why is a missing check rollup not necessarily a failure?

Why is the live reviewer request optional in a solo lab?

What independent evidence proves the PR change set locally?

Next lesson

Design the collaboration policy, not just the command sequence

Lesson 03 compares draft timing, PR size, Issue lifecycle linking, same-repository versus fork PRs, and stacked/dependent changes.

Authoritative references

 Creating a pull request
 Changing the stage of a pull request
 Linking a pull request to an issue
 Requesting a pull request review
 gh pr create
 gh pr ready
 gh pr view
 gh pr diff
 gh pr checks
 REST API endpoints for pull requests
 REST API review-request endpoints
 REST API versions

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.