Checkpoint Lab — Pull Requests, Drafts, Linked Issues, Change Sets, and Collaboration Patterns
Run a full pull-request checkpoint from issue to draft PR, additional commits, linked work, readiness, controlled base change, independent commit-range proof, handoff criteria, and cleanup without merging or mutating production resources.
Learning objectives
- Create a fresh Issue and topic branch, open a draft PR, add commits, link the Issue, inspect all major PR evidence surfaces, and mark it ready.
- Predict at least two important ref/relationship changes before acting and verify them independently with Git plus GitHub structured output.
- Change the PR base in a controlled way, understand the default-branch closing-keyword consequence, and prove the resulting commit range.
- Write explicit handoff criteria that separate review readiness, check state, merge policy, and deployment ownership.
- Clean up a disposable PR/repository without merging or rewriting shared history.
- Bridge from PR creation/collaboration into Chapter 08 code-review discipline.
\, 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. Checkpoint mission and evidence package
Build c07-pr-checkpoint and produce evidence for:
repository/default branch, Issue URL/state, topic branch OIDs, PR
number/state, base/head refs and OIDs, commit list, three-dot diff
summary, closing-Issue relationship, check rollup, draft→ready
transition, controlled base change, relationship change caused by
non-default base, restored base, and a written handoff policy.
2. Preflight and collision gate
gh auth status --active --hostname github.com
OWNER=$(gh api user --jq .login)
REPO="c07-pr-checkpoint"
gh repo view "$OWNER/$REPO" >/dev/null 2>&1 && {
echo "STOP: repository already exists" >&2
exit 2
}
3. Create source Issue and a release-base 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: publish retry handoff criteria" --body "Synthetic Chapter 07 checkpoint issue.")
ISSUE_NUMBER=${ISSUE_URL##*/}
# Create a non-default candidate base with one harmless independent commit.
git switch -c release/c07
printf '
Release branch marker for Chapter 07 checkpoint.
' >> README.md
git add README.md
git commit -m "chore: add release branch marker"
git push -u origin release/c07
RELEASE_OID=$(git rev-parse HEAD)
# Return to default before creating the topic so the topic does NOT inherit release/c07.
git switch "$DEFAULT_BRANCH"
The release branch exists only to make the base-change exercise observable. The topic will start from the default branch, so changing the PR base later changes the comparison target but does not rewrite the topic branch.
4. Create the topic branch and first commit
git switch -c docs/retry-handoff
cat >> README.md <<'EOF'
## Retry handoff
A retry change is ready for review when scope, validation, and rollback notes are documented.
EOF
git add README.md
git commit -m "docs: add retry handoff criteria"
git push -u origin docs/retry-handoff
TOPIC1=$(git rev-parse HEAD)
5. Prediction 1: opening a draft PR changes hosted review state, not branch OIDs
Write this prediction in your evidence notes before executing:
the PR will become a new GitHub resource, its head will point at
TOPIC1, its base will point at the default branch,
and Closes #N will establish a closing relationship
because the target is the default branch; neither branch OID
should move merely because the PR was opened.
PR_BODY=.c07-checkpoint-pr-body.md
cat > "$PR_BODY" <<EOF
Closes #$ISSUE_NUMBER
Checkpoint PR: review scope, validation, and rollback notes.
EOF
PR_URL=$(gh pr create --base "$DEFAULT_BRANCH" --head docs/retry-handoff --draft --title "docs: define retry handoff" --body-file "$PR_BODY")
PR_NUMBER=${PR_URL##*/}
gh pr view "$PR_NUMBER" --json number,state,isDraft,baseRefName,baseRefOid,headRefName,headRefOid,closingIssuesReferences,url
git rev-parse HEAD
git ls-remote origin "refs/heads/$DEFAULT_BRANCH" "refs/heads/docs/retry-handoff" "refs/pull/$PR_NUMBER/*"
6. Prove the initial change set and evidence planes
git fetch origin "$DEFAULT_BRANCH" docs/retry-handoff
git log --oneline "origin/$DEFAULT_BRANCH..origin/docs/retry-handoff"
git diff --stat "origin/$DEFAULT_BRANCH...origin/docs/retry-handoff"
gh pr diff "$PR_NUMBER" --name-only
gh pr view "$PR_NUMBER" --json commits,files,statusCheckRollup,reviewDecision,reviewRequests
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,head:.head.ref,head_sha:.head.sha}'
7. Add a review-preparation commit and verify same-PR evolution
cat >> README.md <<'EOF'
Rollback note: revert the documentation commit if the guidance proves incorrect.
EOF
git add README.md
git commit -m "docs: add rollback note"
git push
git fetch origin "$DEFAULT_BRANCH" docs/retry-handoff
TOPIC2=$(git rev-parse HEAD)
gh pr view "$PR_NUMBER" --json number,headRefOid,commits,files,updatedAt
git log --oneline "origin/$DEFAULT_BRANCH..origin/docs/retry-handoff"
The second commit should appear in the existing PR. If GitHub shows a new PR number, you opened another PR rather than updating the head branch.
8. Mark ready and capture handoff state
gh pr ready "$PR_NUMBER"
gh pr view "$PR_NUMBER" --json number,isDraft,state,reviewRequests,reviewDecision,statusCheckRollup,closingIssuesReferences,headRefOid
gh pr checks "$PR_NUMBER" || true
Record whether checks exist. “No checks reported” is acceptable in this disposable repository. Readiness is a collaboration signal, not proof that checks or reviews are complete.
9. Prediction 2: changing to a non-default base changes PR comparison/relationship, not topic history
Before acting, write:
changing the PR base from the default branch to
release/c07 will mutate PR base metadata and
comparison context. The topic branch OID TOPIC2 must
not change. Because the PR no longer targets the default branch,
the closing keyword is no longer eligible to auto-close the Issue
on merge; GitHub may also stop presenting it as a closing
relationship. The Issue itself should remain open either way
because we never merge.
10. Change the base and independently prove the result
BEFORE_HEAD=$(gh pr view "$PR_NUMBER" --json headRefOid --jq .headRefOid)
gh pr edit "$PR_NUMBER" --base release/c07
gh pr view "$PR_NUMBER" --json number,baseRefName,baseRefOid,headRefName,headRefOid,commits,files,closingIssuesReferences
git fetch origin release/c07 docs/retry-handoff
printf 'local_topic='; git rev-parse origin/docs/retry-handoff
printf 'before_head='; printf '%s
' "$BEFORE_HEAD"
printf 'merge_base='; git merge-base origin/release/c07 origin/docs/retry-handoff
git log --oneline "origin/release/c07..origin/docs/retry-handoff"
git diff --stat "origin/release/c07...origin/docs/retry-handoff"
gh issue view "$ISSUE_NUMBER" --json number,state,url
Because release/c07 has an independent commit that the
topic does not contain, the two branches diverge. The head OID still
should equal TOPIC2. The exact three-dot file diff
remains focused on what the topic introduced from the merge base;
the PR’s base coordinate and closing-keyword semantics are the
important hosted changes. Inspect
closingIssuesReferences as evidence, but treat the
documented non-default-base rule—not a particular UI rendering—as
the authoritative reason auto-close is inactive.
11. Restore the intended default-branch target and verify relationship recovery
gh pr edit "$PR_NUMBER" --base "$DEFAULT_BRANCH"
gh pr view "$PR_NUMBER" --json baseRefName,baseRefOid,headRefName,headRefOid,closingIssuesReferences
git fetch origin "$DEFAULT_BRANCH" docs/retry-handoff
git log --oneline "origin/$DEFAULT_BRANCH..origin/docs/retry-handoff"
git diff --stat "origin/$DEFAULT_BRANCH...origin/docs/retry-handoff"
The PR should again target the default branch; verify the closing relationship through structured PR output. The Issue remains open because the PR remains unmerged.
12. Write the PR handoff criteria before merge
| Gate | Checkpoint policy |
|---|---|
| Scope | PR title/body explain one coherent change; no unrelated commits/files |
| Base/head | Base is intentional; head repository/branch/OID recorded |
| Issue relationship | Closing keyword used only if default-branch merge should close the Issue |
| Review readiness | PR is ready, not draft; requested reviewers/owners are known where applicable |
| Automated evidence | Configured checks are passing or absence is explicitly documented |
| Review evidence | Required approvals/conversations resolved according to repository policy |
| History changes | Any rebase/force update communicated and old/new OIDs preserved |
| Merge | Merge method and permissions handled under Chapter 09 policy |
| Deployment | Success proven by deployment/release evidence, not inferred from PR merge |
13. Final verification checklist
- Issue is still open and its URL/number is preserved.
- PR is open and ready, with base restored to the default branch.
- Head OID equals the last pushed topic commit.
-
Local
git log base..headshows only the intended topic commits. - Local three-dot diff and hosted Files changed agree on the intended file scope.
- Closing-Issue relationship exists only after restoring the default-branch target.
- Check/review state is recorded without being mistaken for deployment evidence.
- No force push, merge, repository transfer, secret change, or policy bypass was needed.
14. Cleanup and rollback
Close the PR without merging, then archive the disposable repository only after verifying its exact identity. Closing preserves the not-merged outcome and archiving makes the repository read-only while retaining the evidence. Permanent deletion is optional and should be performed separately only after a second identity check.
gh pr close "$PR_NUMBER" --comment "Chapter 07 checkpoint complete; intentionally not merged."
cd ..
printf 'archive-check=%s/%s
' "$OWNER" "$REPO"
gh repo archive "$OWNER/$REPO"
rm -rf "$REPO"
gh repo archive is
reversible and does not require broadening the CLI token for
repository deletion. If you later choose permanent deletion, use the
repository danger zone only after independently re-checking
owner/name.
15. What Chapter 07 adds to the production GitHub operating model
Chapter 07 adds the primary change-control object: a PR that names intended integration coordinates, keeps reviewable change scope observable, links work deliberately, records human/automated evidence, and evolves as its head ref moves. The operating model can now distinguish “code proposed,” “review requested,” “checks reported,” “merged,” and “deployed” as separate facts.
16. Bridge to Chapter 08: Code Review discipline
This checkpoint deliberately stopped before substantive review. Chapter 08 takes the PR’s Files changed and conversation surfaces and turns them into a disciplined review system: suggested changes, CODEOWNERS, review requests, review states, reviewer responsibility, and how to avoid rubber-stamp approvals.
Knowledge check
What did changing the PR base prove without rewriting Git history?
PR comparison/target metadata can change while the head branch OID stays identical.
Why did the closing-Issue relationship depend on restoring the default branch?
GitHub currently interprets closing keywords only for PRs targeting the repository default branch.
Why was the Issue still open after every base change?
The PR was never merged, so no closing-keyword merge event occurred.
What proves the topic branch did not change during base retargeting?
Compare the before/after headRefOid and local
remote-tracking topic OID; they should match
TOPIC2.
What is the most important handoff distinction before Chapter 08?
Ready-for-review is only a stage signal; actual review quality and approval discipline are separate controls taught next.
Does closing the PR delete its head commits?
No. Closing the PR changes hosted PR state; the branch/commits remain until refs/repository cleanup changes them.
Authoritative references
About pull requests
Changing a pull request base branch
Changing the stage of a pull request
Linking a pull request to an issue
Branches and pull-request comparisons
Comparing commits
gh pr create
gh pr ready
gh pr edit
gh pr view
gh pr diff
gh pr checks
REST API endpoints for pull requests
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.