Chapter 07Lesson 02~215 minutes

Merge Requests, Drafts, Review Threads, Suggestions, and Change Collaboration: Guided Hands-On Workflow and Core Operations

Run a disposable change through branch creation, draft merge request, state inspection, review thread and suggestion, ready-for-review transition, and verified merge or close using Git, glab, UI, and REST evidence.

Disposable labglabREST APIDiff evidenceReview workflowVerification

Learning objectives

  • Create a disposable feature branch and draft merge request without requiring paid features or a second account.
  • Capture source/target SHAs, diff refs, commits, pipeline state, issue links, and discussion state before review actions.
  • Add a synthetic diff review/suggestion and prove the resulting source-branch change instead of trusting UI status alone.
  • Mark an MR draft/ready and request review only from an already-authorized test identity, never by granting extra project access for the lab.
  • Predict and verify the target-branch, source-branch, and linked-issue state after merge or close.
Availability baseline (verified 2026-08-21). Core merge requests, draft/ready state, reviewers, comments/review threads, suggestions, basic approvals, branch/fork workflows, merge-request pipelines, the Merge Requests/Discussions REST APIs, and the glab mr command family are documented for Free/Premium/Ultimate on GitLab.com, Self-Managed, and Dedicated. On GitLab Free, eligible users can approve an MR, but approvals are optional and do not enforce a merge gate; required approval rules are Premium/Ultimate. Draft MRs cannot merge until marked ready, but by default they run the same MR pipelines as ready MRs. Current fork-pipeline behavior and protected-resource rules are version-sensitive, so production policy must be checked against the deployed GitLab version.

1. Scenario, assumptions, and safety boundary

Use one disposable GitLab project you own for training. The change is intentionally tiny: add a synthetic health endpoint note to README.md. The chapter does not need a real secret, production repository, deployment, custom runner, or paid approval rule.

  • Offering/tier: GitLab.com Free or equivalent current Free project.
  • Role: enough access to push a feature branch and create/merge an MR in your disposable project. If the default branch is protected so only Maintainers can merge, use the account that owns the training project.
  • Authentication: reuse Chapter 02 glab/Git authentication; do not print or create a new PAT for this lesson.
  • Review identity: an existing controlled collaborator is optional. If none exists, inspect reviewer state and use the review-request fixture rather than inviting a real person or widening permissions.
  • CI: no CI configuration is required. A missing pipeline is a valid observed state, not a reason to spend compute.

2. Capture the pre-change state

Start from a clean worktree and record the current default branch identity. This is the reference point for every later claim.

REPO="GROUP/mr-sandbox"
PROJECT_ID="123456"   # replace with your disposable project ID
DEFAULT="main"         # verify; do not assume
BRANCH="ch07-mr-lab"
mkdir -p ch07-evidence

glab auth status
glab repo view -R "$REPO" --output json   --jq '{path_with_namespace,visibility,default_branch}'   | tee ch07-evidence/project.json

git status --short
git fetch origin --prune
BASE_SHA="$(git rev-parse "origin/$DEFAULT")"
printf 'base_sha=%s
' "$BASE_SHA" | tee ch07-evidence/base-sha.txt
Prediction 1: creating a branch and opening an MR will not change origin/main. The target branch changes only if a merge/push actually updates it.

3. Create synthetic work and a feature branch

Create one synthetic issue first if you want to exercise traceability. Record its IID; do not rely on human memory to reconstruct which issue the MR was meant to address.

ISSUE_URL="$(glab issue create -R "$REPO"   --title "CH07: document synthetic health check"   --description "Disposable Chapter 07 training issue. No production data."   --yes)"
printf '%s
' "$ISSUE_URL"

# Obtain the issue IID from the UI/output and record it.
ISSUE_IID="12"  # synthetic example; replace with actual IID

git switch -c "$BRANCH" "origin/$DEFAULT"
printf '
## CH07 synthetic health check

This text exists only for the merge-request lab.
' >> README.md
git add README.md
git commit -m "docs: add CH07 synthetic health note"
git push -u origin "$BRANCH"
SOURCE_SHA="$(git rev-parse HEAD)"
printf 'source_sha=%s
' "$SOURCE_SHA" | tee ch07-evidence/source-before-mr.txt

4. Open a draft MR and prove its identity before review

Create the MR as draft so the hosted object exists early while explicitly blocking merge. The description connects intent to the synthetic issue. A closing keyword is included only if you intend to test issue-closing during the final merge.

glab mr create -R "$REPO"   --source-branch "$BRANCH"   --target-branch "$DEFAULT"   --title "CH07: synthetic health-check documentation"   --description "Closes #$ISSUE_IID

Disposable Chapter 07 lab. Verify source/target SHAs before merge."   --draft --yes

# Discover the MR by source branch, then record its IID.
glab mr list -R "$REPO" --source-branch "$BRANCH" --output json
MR_IID="7"  # replace with the actual IID

glab api "projects/$PROJECT_ID/merge_requests/$MR_IID"   --jq '{iid,title,state,draft,source_branch,target_branch,sha,diff_refs,detailed_merge_status,head_pipeline}'   | tee ch07-evidence/mr-draft.json

Expected observations: draft is true, source_branch is the training branch, target_branch is the verified default branch, and the MR sha should match the current feature-branch head. head_pipeline may be null if the project has no applicable CI.

5. Inspect commits, diff, and discussions before commenting

Do not start review from the green/red summary alone. Confirm the actual changed file and commit identity.

glab mr view "$MR_IID" -R "$REPO" --comments
glab mr diff "$MR_IID" -R "$REPO" | tee ch07-evidence/mr-diff-before.txt

glab api "projects/$PROJECT_ID/merge_requests/$MR_IID/commits" --paginate   --jq '.[] | {id,short_id,title,author_name,created_at}'   | tee ch07-evidence/mr-commits-before.jsonl

glab api "projects/$PROJECT_ID/merge_requests/$MR_IID/discussions" --paginate   | tee ch07-evidence/discussions-before.json
Prediction 2: adding or resolving a review comment alone does not change the MR source SHA. Applying a code suggestion does.

6. Add a review thread and suggestion with synthetic code

Open the MR Changes view, select the line you added, and start a review thread. First leave a concern such as “Make the heading explicitly say this is training-only.” Before resolving it, capture the current source SHA and discussion state.

Then add a suggestion that replaces the heading with ## CH07 training-only synthetic health check. Use Apply suggestion only after verifying the suggestion is scoped to this disposable branch. GitLab should create a new source-branch commit and mark the suggestion applied.

PRE_SUGGEST_SHA="$(git ls-remote origin "refs/heads/$BRANCH" | awk '{print $1}')"
printf 'pre_suggestion_sha=%s
' "$PRE_SUGGEST_SHA"

glab api "projects/$PROJECT_ID/merge_requests/$MR_IID/discussions" --paginate   --jq '.[] | {id,notes:[.notes[] | {id,type,resolvable,resolved,body,author:.author.username}]}'   | tee ch07-evidence/discussions-with-suggestion.json

# After applying the suggestion in the UI:
git fetch origin "$BRANCH"
POST_SUGGEST_SHA="$(git rev-parse "origin/$BRANCH")"
printf 'post_suggestion_sha=%s
' "$POST_SUGGEST_SHA"
test "$PRE_SUGGEST_SHA" != "$POST_SUGGEST_SHA" && echo "source branch changed as expected"

git show --stat --oneline "$POST_SUGGEST_SHA"

Inspect the new commit author/committer and the now-resolved suggestion thread. The important causal chain is apply suggestion → source branch commit → new MR head SHA, not “thread became green.”

7. Move draft → ready and request review without widening access

Mark the MR ready after the synthetic change is coherent. The CLI currently supports --ready and --draft.

glab mr update "$MR_IID" -R "$REPO" --ready --yes

glab api "projects/$PROJECT_ID/merge_requests/$MR_IID"   --jq '{iid,draft,reviewers,assignees,detailed_merge_status,sha}'   | tee ch07-evidence/mr-ready.json

If you already have a controlled training collaborator who is a member of this disposable project, request review without changing membership:

REVIEWER="training-user"  # existing authorized identity only
glab mr update "$MR_IID" -R "$REPO" --reviewer "$REVIEWER" --yes
No second account? Skip the live reviewer assignment and save a fixture that says “reviewer would be selected from existing authorized members.” Do not invite a real coworker or grant Developer access merely to satisfy the lab.

8. Predict merge versus close before acting

Write down the expected state. If you close the MR, the target branch remains at its current SHA and the feature branch remains separate. If you merge into the default branch, the target branch changes according to the project merge method, and the issue-closing behavior can fire when the closing reference reaches the default branch and automatic closing is enabled.

TARGET_BEFORE="$(git ls-remote origin "refs/heads/$DEFAULT" | awk '{print $1}')"
SOURCE_BEFORE_FINAL="$(git ls-remote origin "refs/heads/$BRANCH" | awk '{print $1}')"
printf 'target_before=%s
source_before_final=%s
' "$TARGET_BEFORE" "$SOURCE_BEFORE_FINAL"   | tee ch07-evidence/final-prediction-inputs.txt

9. Merge safely—or close—and verify the exact result

Preferred checkpoint path: merge in the disposable project so you can verify branch and issue causality. Use --sha to refuse a merge if the source head changed after review. This prevents accidentally merging an unreviewed later push.

REVIEWED_SHA="$(glab api "projects/$PROJECT_ID/merge_requests/$MR_IID" --jq '.sha')"

glab mr merge "$MR_IID" -R "$REPO"   --sha "$REVIEWED_SHA"   --remove-source-branch   --auto-merge=false   --yes

git fetch origin --prune
TARGET_AFTER="$(git rev-parse "origin/$DEFAULT")"
printf 'target_after=%s
' "$TARGET_AFTER" | tee ch07-evidence/target-after.txt

glab api "projects/$PROJECT_ID/merge_requests/$MR_IID"   --jq '{iid,state,merged_at,merge_commit_sha,squash_commit_sha,sha,source_branch,target_branch}'   | tee ch07-evidence/mr-final.json

glab issue view "$ISSUE_IID" -R "$REPO"

If your project policy, role, or test intent makes merge undesirable, close the MR instead and verify that origin/$DEFAULT did not move. Do not force-push or bypass protections to make the lab succeed.

10. Challenge: choose the control, not the click path

You discover that the MR is ready, discussions are resolved, but the source SHA changed after the last review. Which control should you use before merging?

Answer by naming the state you must re-verify. A strong solution re-inspects the new diff/commits and uses the merge command’s expected --sha guard (or equivalent UI evidence) instead of trusting the old review state.

11. Cleanup and evidence

  • Keep the merged MR and closed synthetic issue as training history, or close the MR if you chose the no-merge path.
  • Delete only the synthetic source branch if it still exists and you are certain it is not reused.
  • Remove local training branches after returning to the default branch.
  • Do not delete the project, rewrite history, or weaken branch protection.
git switch "$DEFAULT"
git branch -D "$BRANCH" 2>/dev/null || true
git remote prune origin

glab api "projects/$PROJECT_ID/merge_requests/$MR_IID"   --jq '{iid,state,draft,sha,merge_commit_sha,target_branch,web_url}'   > ch07-evidence/mr-cleanup-proof.json
sha256sum ch07-evidence/* > ch07-evidence/SHA256SUMS.txt

Knowledge check

The MR is ready but sha changed after review. Should you merge using the old approval/review evidence?

Why can a missing pipeline be a valid result in this lesson?

What should happen to origin/main when you only create a draft MR?

After applying a suggestion, which independent evidence proves code changed?

Why use glab mr merge --sha in a controlled lab?

Summary

You created a tiny source branch, opened a draft MR, captured diff/commit/discussion evidence, applied a suggestion and proved the new source SHA, moved the MR to ready, handled reviewer assignment without widening permissions, predicted merge/close outcomes, and verified the target branch and linked issue independently. Lesson 3 turns these mechanics into design choices.

Official references

Next lesson

Design the merge-request workflow deliberately

Lesson 3 compares change size, branch/fork topology, draft timing, reviewer strategy, and web suggestions versus local commits through security, audit, reliability, and maintainability tradeoffs.

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
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.