GitLab
01 / 09

GitLab Workflow

GitLab Workflow

GitLab organizes work in Groups and Projects. Merge Requests (the GitLab equivalent of Pull Requests) are the primary unit of code review. Understanding protected branches, approval rules, and CODEOWNERS is essential for team workflows.

Groups, Projects & Repository Structure

# Groups: namespace for projects (like GitHub organizations)
# Subgroups: nested groups (e.g. company/backend/payments)
# Projects: individual repositories

# Clone a project
git clone git@gitlab.com:mygroup/myproject.git
git clone https://gitlab.com/mygroup/myproject.git

# GitLab uses "main" as default branch (older projects use "master")
# Rename local default branch to match
git branch -m master main
git push -u origin main
# Then update default branch in Settings → Repository → Default branch

# Repository mirroring — keep a GitLab repo in sync with GitHub
# Settings → Repository → Mirroring repositories
# Pull mirroring: GitLab pulls from GitHub on schedule or via trigger
# Push mirroring: GitLab pushes to another remote on each push

# Set up push mirror via API
curl --request POST --header "PRIVATE-TOKEN: <token>"   "https://gitlab.com/api/v4/projects/:id/remote_mirrors"   --data "url=https://github.com/user/repo.git&enabled=true&keep_divergent_refs=true"

Merge Requests

# Create an MR from the CLI (glab tool — see CLI page)
glab mr create --title "feat: add payment gateway"   --description "Closes #123"   --assignee @me   --label "feature,backend"   --target-branch main

# Draft MR — not ready for review (prefixes title with "Draft:")
glab mr create --draft --title "WIP: refactor auth"

# MR merge strategies (set in project Settings → Merge Requests):
# Merge commit:     always creates merge commit (full history)
# Squash and merge: squashes all MR commits into one
# Fast-forward:     linear history, no merge commit (fails if not rebased)
# Allow squash on merge: let author choose per MR

# Approval rules (Settings → Merge Requests → Approval rules)
# Require N approvals before merge
# Set "Code owner approval" to require CODEOWNERS to approve

# CODEOWNERS file — auto-assigns reviewers based on changed paths
# Place at: CODEOWNERS, docs/CODEOWNERS, or .gitlab/CODEOWNERS
# Syntax matches .gitignore patterns

# .gitlab/CODEOWNERS
[Backend]
src/api/        @backend-team @alice
src/db/         @alice @bob

[Frontend]
src/components/ @frontend-team

[DevOps]
*.yml           @devops-team
Dockerfile      @devops-team
terraform/      @devops-team

# Protected branches (Settings → Repository → Protected branches)
# Restrict who can push/merge to main/release/* branches
# "Allowed to merge": Maintainers
# "Allowed to push":  No one (force merge requests)
# "Allowed to force push": disabled

Issues & Milestones

# Create issue from CLI
glab issue create --title "Bug: login fails on Safari"   --description "Steps to reproduce: ..."   --label "bug,high-priority"   --milestone "v2.0"

# List open issues
glab issue list
glab issue list --label "bug" --milestone "v2.0"

# Close issue via commit message or MR description
# Supported keywords: Closes, Fixes, Resolves
git commit -m "fix: handle null session token

Closes #42"

# Cross-project reference
# Closes mygroup/other-project#15

# Issue boards — Kanban-style board linked to labels
# Epics (GitLab Premium) — group issues across milestones

# Milestones — track progress toward a goal
# Project milestones: per-project
# Group milestones: span multiple projects in a group

# Quick actions in issue/MR descriptions (no UI needed):
# /assign @alice        — assign to user
# /label ~bug           — add label
# /milestone %v2.0      — set milestone
# /close                — close issue
# /spend 2h             — log time (if time tracking enabled)
# /due 2024-06-30       — set due date

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free