GitLab Workflow Skill
GitLab-Workflow-Management mit dem glab CLI für Merge Requests, Issues und Git-Best Practices.
Mehrere GitLab-Instanzen
glab erkennt den GitLab-Host automatisch aus Ihrem Git-Remote. GITLAB_HOST wird nicht benötigt, wenn Sie in einem Repository arbeiten. Für Nicht-origin-Remotes (z. B. eine lokale GDK-Instanz, die als sekundärer Remote hinzugefügt wurde) verwenden Sie glab config set remote_alias <remote>. Setzen Sie GITLAB_HOST nur, wenn Sie außerhalb eines Git-Repositorys arbeiten oder einen einmaligen Befehl für eine bestimmte Instanz ausführen. Siehe references/multi-host.md für die Einrichtung von Nicht-Origin-Remotes und die Ableitung des Hostnamens aus Remote-URLs.
⚠️ Nachrichten-Escaping – Häufige Falle
Wenn Ihre Nachricht Backticks (`), $ oder andere Shell-Sonderzeichen enthält, setzen Sie diese NIEMALS direkt in -m "..." ein. Die Shell interpretiert Backticks als Befehlsersetzung, was Ihre Nachricht stillschweigend verstümmelt und Fehler wie /bin/bash: line 1: client_name: command not found erzeugt.
Dies hat bereits zu Produktionsausfällen geführt: Agenten, die fehlerhafte Kommentare an GitLab-MRs/Issues posteten, gefolgt von entschuldigenden Korrekturnotizen.
❌ NICHT – Backticks in doppelt-anführende -m einbetten
# KAPUTT: Die Shell versucht, `client_name` als Befehl auszuführen
glab mr note 100 -m "Use `client_name` and `wor/` here." -R org/repo
# Fehler: /bin/bash: line 1: client_name: command not found
# Der Kommentar wird gepostet als: "Use and here." (Bezeichner stillschweigend entfernt)
# Auch KAPUTT: Backslash-escaped Backticks funktionieren in verschachtelten/gescripteten Kontexten nicht
glab mr note 100 -m "Use \`client_name\`" -R org/repo
# Funktioniert in einfachen Fällen, schlägt jedoch fehl, wenn der Befehl von einem Aufrufer doppelt angeführt wird:
# bash -c "glab mr note 100 -m \"Use \`client_name\`\"" → führt weiterhin client_name aus
✅ RICHTIG – Zuerst in eine Datei schreiben, dann via $(cat ...) übergeben
Wählen Sie einen Pfad, der für Ihre Umgebung geeignet ist (ein mktemp-Ergebnis, eine temporäre Datei im Workspace, was auch immer passt – das Skill schreibt keinen bestimmten Pfad vor; Agenten wählen einen, der für ihren Aufruf eindeutig ist, um Kollisionen bei parallelen Läufen zu vermeiden):
# MSG = von Ihnen gewählter Pfad (z. B. mktemp, ~/workspace/tmp/note-$$.md, etc.)
MSG=<Agent wählt>
cat > "$MSG" << 'EOF'
Use `client_name` and `wor/` here. The `glab` tool handles this.
EOF
glab mr note 100 -m "$(cat "$MSG")" -R org/repo
Das einfach angeführtte 'EOF'-Heredoc-Trennzeichen verhindert die gesamte Variablen-/Backtick-Expansion beim Schreiben der Datei. Die $(cat "$MSG")-Ersetzung ist sicher, da der Dateiinhalt bereits wörtlich geschrieben wurde. Dreifach-Backtick-Codeblöcke (```) sind in <<'EOF'-Heredocs ebenfalls sicher – kein Escaping nötig; nur einfache Backticks und $ lösen die Befehlsersetzung aus.
✅ Ebenfalls sicher – glab api mit -f Flag
glab api --method POST "projects/org%2Frepo/merge_requests/100/notes" \
-f "body=$(cat "$MSG")"
⚠️ Unangeführtes Heredoc interpretiert Backticks immer noch
# KAPUTT: unangeführtes EOF-Trennzeichen – Backticks im Text werden immer noch interpretiert
cat > "$MSG" << EOF
Use `client_name` here. # ← Shell führt client_name beim Schreiben der Datei aus
EOF
⚠️ Heredoc-in-Heredoc bricht die Shell-Parsing
Wenn Ihr Inhalt selbst ein Heredoc-Beispiel mit einem nicht eingerückten EOF-Terminator enthält, schließt das innere EOF in Spalte 0 das äußere Heredoc vorzeitig:
# KAPUTT: Das innere EOF ist in Spalte 0 – es schließt das ÄUSSERE Heredoc vorzeitig
cat > "$OUTER" << 'EOF'
Here is the safe pattern:
cat > "$MSG" << 'EOF'
Use `client_name` here.
EOF
# ↑ Dieses EOF terminiert das ÄUSSERE Heredoc – die Zeilen darunter werden als Shell-Befehle ausgeführt!
echo "more content..."
EOF
# ↑ Dieses verwaiste EOF wird zu einem Befehl: "EOF: command not found"
Behebung – Verwenden Sie ein anderes Trennzeichen für das äußere Heredoc:
cat > "$OUTER" << 'OUTEREOF'
Here is the safe pattern:
cat > "$MSG" << 'EOF'
Use `client_name` here.
EOF
OUTEREOF
Oder schreiben Sie die Datei in Teilen – der erste Teil verwendet >, die folgenden Teile >>, jedes mit seinem eigenen Trennzeichen.
Faustregel: Wenn die Nachricht `, $, ! oder \ enthält – schreiben Sie sie zuerst mit << 'EOF' in eine Datei, immer. Wenn der Inhalt selbst Heredoc-Syntax enthält, verwenden Sie ein eindeutiges äußeres Trennzeichen (z. B. OUTEREOF, MSGEOF), das nicht im Textkörper vorkommt.
Merge Requests erstellen
Übergeben Sie immer --push und -H <owner/repo>. Ohne --push existiert der Branch möglicherweise noch auf keinem Remote. Ohne -H wählt glab möglicherweise den falschen Remote (z. B. einen Sicherheitsspiegel) als Quellprojekt aus und erstellt den MR vom falschen Fork.
Zweiter Remote derselben Familie? In einem Checkout mit sowohl
origin(gitlab-org/gitlab) als auch einemsecurity-Spiegel (gitlab-org/security/gitlab) wähltglab mr create, wenn es nicht-interaktiv ausgeführt wird (kein TTY, wie Agenten arbeiten), stillschweigend densecurity-Fork als Head aus und schlägt mit400 {source_branch: [does not exist]}fehl. Dauerhafte Lösung, einmal pro Checkout setzen:git config remote.origin.glab-resolved-head head. Fallback pro Befehl für frische Checkouts: Übergeben Sie-H <owner/repo>(z. B.-H gitlab-org/gitlab).-Rbehebt dies nicht – es setzt nur das Basis-Repo fest, nicht den Head.
# Einfacher MR
glab mr create --push -H <owner/repo> --title "Add feature" --description "Kurzbeschreibung" --assignee <username>
# Komplexer MR – Beschreibung zuerst in Datei schreiben (eigenen Pfad wählen)
glab mr create --push -H <owner/repo> --title "Add feature" --description "$(cat "$DESC")" --assignee <username>
Vorlagen: Überprüfen Sie .gitlab/merge_request_templates/ auf projektspezifische Vorlagen.
Vollständige Flag-Liste (Claude Code fügt dies automatisch ein; andere Agenten sollten es ausführen):
!glab mr create --help
Merge Requests aktualisieren
glab mr update <nummer> --description "$(cat "$DESC")"
glab mr view <nummer> -R <owner>/<repo>
Issue-Verwaltung
Die vollständige, immer aktuelle Flag-Liste (Claude Code fügt dies automatisch ein; andere Agenten sollten es ausführen):
!glab issue --help
view, note, list, create, update funktionieren wie erwartet. Die nicht offensichtlichen Fallen, vor denen --help Sie nicht warnt:
# Liste ist standardmäßig offen und hat KEIN --state-Flag – stattdessen --closed / --all verwenden
glab issue list --closed -R <owner>/<repo>
glab issue list --all -R <owner>/<repo>
# Labels – --label / --unlabel verwenden, NIEMALS +label oder -label Syntax
glab issue update 123 --label "neues-label"
glab issue update 123 --unlabel "altes-label"
# Bereichsbezogene Labels ersetzen automatisch innerhalb ihres Bereichs – kein --unlabel nötig:
glab issue update 123 --label "status::doing" # entfernt jedes vorhandene status::-Label
# Nachrichten mit Backticks/$ – zuerst in Datei schreiben (siehe Nachrichten-Escaping oben)
glab issue note <nummer> -m "$(cat "$MSG")" -R <owner>/<repo>
Für Issue-Zustandsübergänge (schließen/wiederöffnen via API) und das Posten von Notizen via glab api: references/issue-api.md
Work Items
GitLab migriert Issues zu Work Items. Die URL zeigt /work_items/<iid>, aber die REST-API ist dieselbe.
# ✅ Die Issues-API verwenden – gleiche IID, gleiche Endpunkte
glab api "projects/org%2Fproject/issues/<iid>"
# ❌ /work_items/-REST-Endpunkt existiert nicht
glab api "projects/org%2Fproject/work_items/<iid>" # → 404
URL-Parsing: https://gitlab.com/org/project/-/work_items/539076
→ glab api "projects/org%2Fproject/issues/539076"
Vollständige Details, GraphQL-Alternative, Gruppen-Work Items und das Agentenplan (Workplan)-Widget: references/work-items.md
MR-Review
Seit glab v1.94.0 behandelt glab mr note jede gängige MR-Kommentarform (Liste, allgemein, Diff-Zeile, Antwort, auflösen/wiedereröffnen) ohne rohe glab api-Aufrufe oder selbstgebaute position-Objekte. Bevorzugen Sie es für jeden Workflow mit einem einzigen Kommentar. Die MR-IID ist ein positionsabhängiges Argument (nicht --mr); lassen Sie es weg, um die automatische Erkennung aus dem aktuellen Branch zu nutzen.
# ✅ glab mr note für Lesen/Schreiben/Antworten/Auflösen verwenden – ein Befehl pro Operation
glab mr note list 123 -F json # Diskussionen lesen
glab mr note create 123 -m "Kommentar" # allgemein
glab mr note create 123 --file main.go --line 42 -m "..." # Diff-Kommentar
glab mr note create 123 --reply abc12345 -m "..." # Antwort
glab mr note resolve 123 abc12345 # Thread auflösen
# ❌ NICHT glab api .../discussions für diese Operationen verwenden
glab api "projects/<id>/merge_requests/123/discussions" # mr note list verwenden
glab api --method PUT ".../discussions/<id>" -f resolved=true # mr note resolve verwenden
Vollständige Flag-Liste für die obigen Unterbefehle (Claude Code fügt dies automatisch ein; andere Agenten sollten es ausführen):
!glab mr note --help
Für gestapelte Draft-Reviews (mehrere Inline-Kommentare, die zusammen über bulk_publish veröffentlicht werden) nur auf rohe glab api .../draft_notes zurückgreifen – glab mr note hat keinen Draft-Modus.
Vollständige Referenz (alle Flags, Code-Vorschläge, Drafts/Batch-Fallback, Objektpositionen): references/mr-review.md
Issue-Links, Epics und verschachtelte Gruppen
- Issue-Links (
blocked_by,relates_to): references/issue-links.md - Epics CRUD (erstellen, auflisten, aktualisieren, schließen): references/epics.md
- Epic-Kommentare (GraphQL lesen/schreiben, Paginierung – REST gibt 404 zurück): references/epic-comments.md
- Verschachtelte Gruppen (
%2F-Kodierung): references/nested-groups.md
MR-Listing und -Filterung
Vollständige Flag-Liste (Claude Code fügt dies automatisch ein; andere Agenten sollten es ausführen):
!glab mr list --help
Hinweis: glab mr list listet standardmäßig offene MRs und hat kein --state- oder --status-Flag – verwenden Sie --all, --merged oder --closed, um den Statusfilter zu ändern.
Suche
Für vollständige Suchbeispiele (Instanz / Gruppe / Projekt, Bereichstabelle, Paginierung): references/search.md
Kurzreferenz:
glab api "search?scope=issues&search=<abfrage>" | jq '.[] | {iid, title}'
glab api "groups/<gruppe>/search?scope=merge_requests&search=<abfrage>" | jq '.[]'
glab api "projects/<org>%2F<repo>/search?scope=issues&search=<abfrage>" | jq '.[]'
Git und Commit-Konventionen
Folgen Sie den eigenen Git-Konventionen des Repos, falls vorhanden (ein Projekt kann diese dokumentieren und mit einem Commit-Linter durchsetzen). GitLab-Standards:
git checkout -b feature/description # Feature-Branches
git checkout -b fix/description # Bugfixes
- Großgeschriebene, imperative Commit-Betreffe ("Add feature", nicht "Added feature" oder "feat: add feature"); GitLab verwendet keine Conventional-Commit-Betreffe.
- Referenzieren Sie Issues/MRs mit vollständigen URLs:
Closes https://gitlab.com/org/project/-/issues/123. - Setzen Sie Commit-Nachrichten mit Sonderzeichen in einfache Anführungszeichen:
git commit -m 'Add note from https://gitlab.com/org/project/-/merge_requests/123'.
Agenten-Richtlinien
Die obigen Abschnitte decken die allgemeinen Workflows ab. Dies sind die nicht offensichtlichen Fallen und API-Eigenheiten, die leicht falsch gemacht werden und nicht aus glab <cmd> --help ersichtlich sind:
- Kontext zuerst lesen –
glab issue view/glab mr viewvor der Implementierung;.gitlab/issue_templates/und.gitlab/merge_request_templates/auf Vorlagen prüfen --jqfunktioniert bei Unterbefehlen, nicht beiglab api–glab issue list/glab mr list/glab ci listakzeptieren ein globales--jq-Flag (filtert JSON-Ausgabe);glab apitut dies nicht – leiten Sie seine Ausgabe stattdessen durch| jq '...'- Kein
--body-Flag – glab verwendet--description, nicht--body(was eingh-Flag ist); sie sind nicht austauschbar - Work Items verwenden die Issues-API –
/work_items/<iid>-URLs →projects/.../issues/<iid>; der/work_items/-REST-Endpunkt ist eine 404 - Epic-Kommentare benötigen GraphQL – REST
/notesGET+POST beide → 404 (trifft immer noch auf GitLab 19.1 zu); übergeben Siebody/noteableIdals GraphQL-Variablen, niemals String-Interpolation. Siehe references/epic-comments.md - Kein
-Rfür die Gruppen-API –-RerwartetOWNER/REPO; Gruppenendpunkte verwenden direktglab api "groups/..." - Verschachtelte Gruppen REST:
%2F–groups/org%2Fsubgroup/epics; unkodierte Schrägstriche → 404 - GraphQL iid ist ein String –
workItem(iid: "16428")nichtworkItem(iid: 16428) groups/<id>/work_itemsist 404 –groups/<id>/epics(REST) oder GraphQL verwendenprojectstelltworkItems(Plural) bereit, nichtworkItem– unterprojectworkItems(first: 1, iid: "IID")ohnefilter:-Argument verwenden; das singuläreworkItem(iid:)-Feld existiert nur untergroup/namespace- Epic schließen/wiederöffnen via REST –
state_event=close/reopenaufPUT groups/<id>/epics/<iid>funktioniert; kein GraphQL nötig - Bereichsbezogene Labels ersetzen automatisch –
--label "status::doing"entfernt jedes vorhandenestatus::*-Label; kein--unlabelnötig (dies ist eine Plattform-Tatsache, gilt allgemein über die API, nicht nur für glab) - Idempotente Kommentare →
--unique–glab mr note create -m "..." --uniqueüberspringt das Posten, wenn ein identischer Text bereits existiert; stimmt nur mit dem Text überein, daher werden identische Texte in verschiedenen Diff-Zeilen trotzdem gepostet - Nicht-Origin-Remotes →
remote_alias– wennoriginauf eine Instanz zeigt, aber glab auf einen anderen Remote abzielen soll (z. B. eine lokale GDK, die alsgdkhinzugefügt wurde), führen Sieglab config set remote_alias gdkaus, anstattGITLAB_HOSTpro Befehl zu setzen. Siehe references/multi-host.md - Backticks in Nachrichten → zuerst in Datei schreiben – niemals
`/$in-m "..."oder--description "..."einbetten; in eine Datei schreiben, die Sie benennen (eindeutig pro Aufruf) mit<< 'EOF'(einfach angführtes Trennzeichen, kritisch), dann via$(cat "$FILE")übergeben. Siehe den Abschnitt Nachrichten-Escaping oben. - Zweiter Remote derselben Familie führt
mr createfalsch – bei einemsecurity-Spiegel nebenoriginwählt nicht-interaktivesmr create(kein TTY) stillschweigend den Fork als Head aus. Behebung einmal pro Checkout:git config remote.origin.glab-resolved-head head; Fallback pro Befehl:-H <owner/repo>(-Rbehebt es nicht). Siehe den Abschnitt "Merge Requests erstellen". glab apiNotiztext: Datei →-F "body=@datei"