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.
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.
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
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
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
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?
No. Re-inspect the new commits/diff and re-establish review/CI evidence for the current source SHA. An expected-SHA merge guard helps prevent accidental merge of a later push.
Why can a missing pipeline be a valid result in this lesson?
The lab does not require CI configuration. Pipeline state is evidence to inspect; the absence of an applicable pipeline should be reported honestly rather than triggering unnecessary compute.
What should happen to origin/main when you only
create a draft MR?
Nothing. Creating the hosted MR does not update the target branch.
After applying a suggestion, which independent evidence proves code changed?
The source branch/MR head SHA changes and a new commit appears. Thread resolution alone would not prove that.
Why use glab mr merge --sha in a controlled
lab?
It binds the merge action to the exact reviewed source HEAD and refuses the merge if someone pushed a different commit afterward.
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
- GitLab Docs — Merge requests
- GitLab Docs — Create merge requests
- GitLab Docs — Draft merge requests
- GitLab Docs — Merge request reviews
- GitLab Docs — Suggest changes
- GitLab Docs — Merge request workflows
- GitLab Docs — Merge request pipelines
- GitLab Docs — Changes in merge requests
- GitLab Docs — Troubleshooting merge requests
- GitLab Docs — Merge request approvals
- GitLab Docs — Default branch
- GitLab Docs — Merge requests API
- GitLab Docs — Discussions API
- GitLab Docs — Suggest Changes API
- GitLab Docs — glab mr
- GitLab Docs — glab mr create
- GitLab Docs — glab mr update
- GitLab Docs — glab mr view
- GitLab Docs — glab mr checkout
- GitLab Docs — glab mr merge
- GitLab Docs — REST API pagination
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.