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.
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 prand versioned REST evidence.
\, 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.
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"
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"
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?
The PR points at the same head branch/ref; when that ref moved to a new commit, the PR recalculated around the new head OID.
What should change when you edit only the PR title?
Hosted PR metadata; base/head branch OIDs and Git commits should remain unchanged.
Why is a missing check rollup not necessarily a failure?
A disposable repository may have no configured checks at all. Absence of checks is different from a failing check.
Why is the live reviewer request optional in a solo lab?
A real request requires an eligible person and sends a notification; the course must not require spamming a stranger or buying another account.
What independent evidence proves the PR change set locally?
Fetch the base/head refs, inspect
git log base..head, and compare
git diff base...head with hosted PR data.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.