Ultimate GitLab Commands Cheat Sheet: CI/CD, Repository, and DevOps Workflow Reference

Ultimate Git Lab Commands Cheat Sheet

I’ve been living inside GitLab for most of my DevOps work — pushing code, wiring up pipelines, chasing down why a runner won’t pick up a job at 11 PM. Over time I built my own mental shortcut list, and this is that list, cleaned up and organized so you can actually use it as a reference instead of scrolling through old terminal history like I used to.

This covers everything from basic Git operations through GitLab, to CI/CD pipeline syntax, to the glab CLI, to security and troubleshooting. I’ve kept it practical — real commands, real examples, real gotchas.

Table of Contents

  1. Git & Repository Basics on GitLab
  2. Branching & Merge Requests
  3. GitLab CI/CD Fundamentals
  4. .gitlab-ci.yml Syntax Reference
  5. Runners
  6. Variables & Secrets
  7. Container Registry & Docker
  8. GitLab CLI (glab) Commands
  9. Issues & Project Management
  10. Tags & Releases
  11. Security Features
  12. Best Practices
  13. Troubleshooting Common Issues
  14. Real-World Workflows
  15. FAQs
  16. Interview Questions
  17. Common Mistakes
  18. Printable Quick-Reference Summary
  19. Official Documentation Links

1. Git & Repository Basics on GitLab

Since GitLab is built on Git, the foundation is standard Git commands pointed at a GitLab remote.

CommandDescriptionExample
git cloneClone a GitLab repogit clone git@gitlab.com:group/project.git
git remote -vShow configured remotesgit remote -v
git addStage changesgit add .
git commitCommit staged changesgit commit -m "Fix login bug"
git pushPush to remotegit push origin main
git pullFetch and mergegit pull origin main
git fetchFetch without merginggit fetch origin
git statusShow working tree statusgit status
git logShow commit historygit log --oneline --graph

I always clone with SSH rather than HTTPS when I can — it saves me from typing credentials on every push, assuming I’ve already got my SSH key added to my GitLab profile.

git clone git@gitlab.com:mygroup/myproject.git

Checking commit history the way I actually read it:

git log --oneline --graph --decorate --all

That gives me a compact, visual view of branches and merges instead of a huge wall of text.


2. Branching & Merge Requests

GitLab’s equivalent of GitHub’s “pull request” is the merge request (MR). Here’s how I typically work with branches.

CommandDescriptionExample
git branchList branchesgit branch -a
git checkout -bCreate and switch to new branchgit checkout -b feature/login-fix
git switch -cModern alternative to checkout -bgit switch -c feature/login-fix
git mergeMerge a branchgit merge feature/login-fix
git rebaseReapply commits on top of another basegit rebase main
git push -u origin <branch>Push new branch and set upstreamgit push -u origin feature/login-fix

My typical merge request flow:

git checkout -b feature/add-search
# make changes
git add .
git commit -m "Add search functionality"
git push -u origin feature/add-search

After that push, GitLab gives me a direct link in the terminal output to open a merge request — I click it, fill in the description, assign a reviewer, and let CI run.

Naming conventions I stick to:

  • feature/short-description
  • bugfix/short-description
  • hotfix/short-description
  • chore/short-description

Consistent naming makes it much easier to scan a busy repo’s branch list.


3. GitLab CI/CD Fundamentals

This is where GitLab really shines compared to plain Git hosting. Every pipeline is defined in a .gitlab-ci.yml file at your repo root.

Core concepts:

  • Pipeline — the full automated process triggered by a commit or MR.
  • Stage — a phase in the pipeline (e.g., build, test, deploy).
  • Job — an individual task within a stage.
  • Runner — the agent that actually executes jobs.
  • Artifact — files produced by a job, passed to later stages or downloadable.

A minimal pipeline looks like this:

stages:
  - build
  - test
  - deploy

build_job:
  stage: build
  script:
    - echo "Building the application..."
    - npm install

test_job:
  stage: test
  script:
    - npm test

deploy_job:
  stage: deploy
  script:
    - echo "Deploying to production..."
  only:
    - main

Jobs in the same stage run in parallel; stages run sequentially. So test_job won’t start until every job in build succeeds.


4. .gitlab-ci.yml Syntax Reference

KeywordPurposeExample
stagesDefine pipeline stages in orderstages: [build, test, deploy]
scriptCommands to run in a jobscript: - npm run build
imageDocker image for the jobimage: node:20
only / exceptLegacy job filteringonly: [main]
rulesModern conditional job logicrules: - if: '$CI_COMMIT_BRANCH == "main"'
artifactsFiles to keep after job runsartifacts: paths: [dist/]
cacheCache dependencies between runscache: paths: [node_modules/]
before_scriptCommands run before the main scriptbefore_script: - npm ci
after_scriptCommands run after the main scriptafter_script: - echo "done"
needsDefine job dependencies for DAG pipelinesneeds: ["build_job"]
environmentTrack deployment environmentsenvironment: production
whenControl job execution conditionwhen: manual
retryAuto-retry failed jobsretry: 2
timeoutMax job runtimetimeout: 30 minutes

Using rules instead of only/except (the modern approach):

deploy_prod:
  stage: deploy
  script:
    - ./deploy.sh production
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: manual
    - when: never

I moved almost all my pipelines from only/except to rules a while back — rules gives far more control, especially when combining branch conditions with variables.

Caching dependencies to speed up pipelines:

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/
    - .npm/

That alone cut several of my Node.js pipelines from minutes down to seconds on repeat runs.


5. Runners

Runners are the machines (or containers) that actually execute your pipeline jobs.

CommandDescriptionExample
gitlab-runner registerRegister a new runnergitlab-runner register
gitlab-runner listList registered runnersgitlab-runner list
gitlab-runner runStart the runner processgitlab-runner run
gitlab-runner verifyVerify runner connectivitygitlab-runner verify
gitlab-runner unregisterRemove a runnergitlab-runner unregister --name my-runner

Registering a runner (interactive prompt walkthrough):

sudo gitlab-runner register
# Enter GitLab instance URL
# Enter registration token (from Project > Settings > CI/CD > Runners)
# Enter a description
# Enter tags (e.g., docker,linux)
# Enter executor (docker, shell, kubernetes, etc.)

I tag my runners deliberately (docker, linux, gpu, etc.) so I can target specific runners from within a job:

test_job:
  tags:
    - docker
  script:
    - npm test

Without matching tags, a job can sit “pending” forever because no runner picked it up — one of the most common pipeline issues I’ve had to debug for other people.


6. Variables & Secrets

TypeWhere DefinedUse Case
CI/CD variablesProject Settings > CI/CD > VariablesAPI keys, tokens, credentials
Predefined variablesAutomatically set by GitLab$CI_COMMIT_BRANCH, $CI_PROJECT_NAME
File-type variablesSettings, marked as “File”Config files, certs
Protected variablesOnly exposed on protected branchesProduction secrets

Common predefined variables I reference constantly:

$CI_COMMIT_BRANCH       # current branch
$CI_COMMIT_SHA          # full commit hash
$CI_PROJECT_NAME        # project name
$CI_PIPELINE_ID         # pipeline ID
$CI_JOB_NAME            # current job name
$CI_ENVIRONMENT_NAME    # deployment environment

Using a secret variable in a job:

deploy_job:
  script:
    - curl -H "Authorization: Bearer $DEPLOY_TOKEN" https://api.example.com/deploy

I always mark sensitive values as both “Protected” and “Masked” in the UI — protected so they only apply on protected branches, masked so they never show up in job logs.


7. Container Registry & Docker

GitLab ships with a built-in Container Registry per project.

CommandDescriptionExample
docker loginAuthenticate to registrydocker login registry.gitlab.com
docker buildBuild an imagedocker build -t registry.gitlab.com/group/project .
docker pushPush image to registrydocker push registry.gitlab.com/group/project
docker pullPull image from registrydocker pull registry.gitlab.com/group/project

A typical build-and-push job inside .gitlab-ci.yml:

build_image:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA

$CI_REGISTRY, $CI_REGISTRY_USER, and $CI_REGISTRY_PASSWORD are all predefined for you automatically — I don’t need to manually configure Docker credentials in most pipelines.


8. GitLab CLI (glab) Commands

glab is GitLab’s official command-line tool, similar in spirit to GitHub’s gh. I use it constantly to avoid tab-switching to the browser.

CommandDescriptionExample
glab auth loginAuthenticate the CLIglab auth login
glab repo cloneClone a repoglab repo clone group/project
glab mr createCreate a merge requestglab mr create --title "Fix bug" --description "..."
glab mr listList open MRsglab mr list
glab mr viewView MR detailsglab mr view 42
glab mr mergeMerge an MRglab mr merge 42
glab issue createCreate an issueglab issue create --title "Bug: login fails"
glab issue listList issuesglab issue list
glab pipeline listList pipelinesglab pipeline list
glab pipeline ci viewView pipeline in terminalglab pipeline ci view
glab ci traceStream job log liveglab ci trace

Creating and merging an MR entirely from the terminal:

glab mr create --title "Add search filters" --description "Adds category and date filters"
glab mr view
glab mr merge --squash

I use glab ci trace a lot when I want to watch a currently running job’s log stream without opening a browser tab.


9. Issues & Project Management

GitLab’s issue tracker is tightly integrated with merge requests and boards.

FeatureDescription
Issue boardsKanban-style visual tracking
LabelsCategorize and filter issues
MilestonesGroup issues/MRs into a timeboxed goal
WeightAssign relative effort/complexity to issues
Epics (Premium+)Group related issues across projects

Linking a commit to an issue automatically:

git commit -m "Fix login redirect, closes #45"

Using closes #45 (or fixes, resolves) in a commit message automatically closes issue #45 when that commit lands on the default branch.


10. Tags & Releases

CommandDescriptionExample
git tagCreate a lightweight taggit tag v1.2.0
git tag -aCreate an annotated taggit tag -a v1.2.0 -m "Release 1.2.0"
git push --tagsPush all tags to remotegit push origin --tags
glab release createCreate a GitLab releaseglab release create v1.2.0

Tagging and pushing a release:

git tag -a v1.2.0 -m "Add search and performance fixes"
git push origin v1.2.0

I pair this with a release stage in CI that triggers only when a tag matching v* is pushed:

release_job:
  stage: release
  script:
    - echo "Publishing release $CI_COMMIT_TAG"
  rules:
    - if: '$CI_COMMIT_TAG =~ /^v/'

11. Security Features

GitLab has strong built-in security tooling, especially from Ultimate/Premium tiers, but several are available even in lower tiers.

FeatureDescription
SASTStatic Application Security Testing on source code
Dependency ScanningFlags vulnerable dependencies
Secret DetectionScans for accidentally committed credentials
Container ScanningScans Docker images for known CVEs
Protected branchesRestrict who can push/merge to critical branches
Protected variablesRestrict secret exposure to protected branches/tags

Enabling SAST with GitLab’s included template:

include:
  - template: Security/SAST.gitlab-ci.yml

That one line pulls in a full static analysis job without me having to hand-write scanning logic myself.


12. Best Practices

  • Keep .gitlab-ci.yml DRY using extends and include for shared job configs.
  • Use rules over only/except for anything beyond the simplest branch filter.
  • Cache dependencies (node_modules, .m2, vendor/) to cut pipeline time significantly.
  • Protect your main/production branches and require MR approvals.
  • Use needs to build a DAG pipeline instead of strictly sequential stages when jobs don’t actually depend on each other — it can meaningfully cut total pipeline time.
  • Mask and protect all sensitive CI/CD variables.
  • Pin Docker image versions (node:20.11 rather than node:latest) so pipelines don’t randomly break on upstream image updates.
  • Use merge request templates so every MR has consistent context (what changed, why, how it was tested).

13. Troubleshooting Common Issues

Pipeline stuck “pending” forever Usually means no runner matches the job’s tags, or all runners are busy/offline. Check Settings > CI/CD > Runners.

“This job could not start because it could not retrieve the job specification” Usually a runner-to-GitLab connectivity issue — check the runner’s network access and token validity.

Merge request shows conflicts Pull the target branch locally and rebase or merge:

git checkout feature/my-branch
git fetch origin
git merge origin/main
# resolve conflicts, then
git add .
git commit
git push

Docker-in-Docker (dind) job fails to connect to the daemon Make sure DOCKER_HOST, DOCKER_TLS_CERTDIR, and the docker:dind service are all correctly configured together — mismatches here are a very common source of failures.

Variable not being picked up in a job Check whether it’s marked “Protected” and whether the pipeline is actually running on a protected branch.


14. Real-World Workflows

Feature branch to production, start to finish:

git checkout -b feature/checkout-flow
# work, commit
git push -u origin feature/checkout-flow
glab mr create --title "New checkout flow"
# CI runs automatically; review comments addressed
glab mr merge --squash
git checkout main
git pull origin main
git tag -a v2.1.0 -m "Checkout flow release"
git push origin v2.1.0

Debugging a failing pipeline live:

glab pipeline list
glab pipeline ci view
glab ci trace

Rolling back a bad deploy using a manual job:

rollback:
  stage: deploy
  script:
    - ./deploy.sh $LAST_STABLE_TAG
  when: manual

15. FAQs

What’s the difference between GitLab CI/CD and Jenkins? GitLab CI/CD is built directly into the repository host and configured with a single YAML file per repo, while Jenkins is a separate, more general-purpose automation server that typically needs plugins and more manual wiring to connect to your source control.

Do I need a separate server to run GitLab CI/CD? You need at least one runner, but GitLab.com provides shared runners for free (with usage limits), so for many projects you don’t need to host your own.

What’s the difference between only/except and rules? rules is the newer, more flexible syntax that supports conditional logic (if, changes, exists), while only/except is simpler but more limited and considered legacy.

Can I run GitLab CI/CD pipelines locally before pushing? Yes — gitlab-runner exec docker <job-name> lets you simulate a job locally, though it doesn’t perfectly replicate the full remote environment.

How is glab different from using the GitLab web UI? glab lets you create, view, and merge MRs, manage issues, and watch pipelines entirely from the terminal, which is faster for people who live in a shell most of the day.


16. Interview Questions

  1. Explain the relationship between pipelines, stages, and jobs in GitLab CI/CD.
  2. What’s the difference between artifacts and cache in a .gitlab-ci.yml file?
  3. How would you set up a pipeline that only deploys to production on a manual trigger?
  4. What are protected branches and protected variables, and why do they matter together?
  5. How does needs change the execution model of a pipeline compared to standard stages?
  6. Walk through how you’d debug a job stuck in “pending” status.
  7. What is Docker-in-Docker (dind), and why is it needed for building images in CI?
  8. How do merge trains work, and what problem do they solve?
  9. What’s the difference between a lightweight tag and an annotated tag in Git?
  10. How would you structure a monorepo pipeline so unrelated services don’t trigger each other’s jobs?

17. Common Mistakes

  • Forgetting to tag runners and jobs consistently, leaving jobs stuck pending.
  • Using only: [main] when rules would give far more precise control.
  • Committing secrets directly into .gitlab-ci.yml instead of using masked CI/CD variables.
  • Not caching dependencies, leading to unnecessarily long pipeline times.
  • Using latest tags for Docker images in CI, causing unpredictable, hard-to-reproduce failures.
  • Forgetting git push --tags after creating a tag locally, so the tag never reaches GitLab.
  • Merging without squashing on projects that expect a clean, linear history.
  • Not setting when: manual on production deploy jobs, letting a normal push accidentally trigger a live deployment.

18. Printable Quick-Reference Summary

CLONE/PUSH        git clone git@gitlab.com:group/project.git
BRANCH            git checkout -b feature/x, git push -u origin feature/x
MR (glab)         glab mr create, glab mr view, glab mr merge --squash
PIPELINE BASICS   stages, script, image, rules, artifacts, cache
RUNNERS           gitlab-runner register / list / verify
VARIABLES         $CI_COMMIT_BRANCH, $CI_PROJECT_NAME, masked/protected vars
DOCKER            docker login $CI_REGISTRY, docker push $CI_REGISTRY_IMAGE
GLAB CLI          glab auth login, glab pipeline list, glab ci trace
TAGS/RELEASES     git tag -a v1.0.0 -m "msg", git push origin v1.0.0
SECURITY          include: template: Security/SAST.gitlab-ci.yml

19. Official Documentation Links


This is the exact reference I keep pinned when I’m setting up new projects or fixing a broken pipeline under pressure. GitLab has a lot of surface area, but once these commands and concepts are second nature, the whole CI/CD workflow stops feeling like a black box and starts feeling like just another tool in the kit.

Total
1
Shares

Leave a Reply

Previous Post
Ultimate Git Hub Commands Cheat Sheet

Ultimate GitHub Commands Cheat Sheet: Git Workflow, Collaboration, and Repository Management

Next Post
Ultimate Linux Commands Cheat Sheet

Ultimate Linux Commands Cheat Sheet: Essential Terminal Commands for Power Users

Related Posts