vs. Branch Pipelines: der Unterschied
Wer in GitLab CI ploetzlich zwei Pipelines fuer denselben Commit sieht, stoesst meist auf den Unterschied zwischen Branch-Pipelines und Merge-Request-Pipelines: Erstere testen den tatsaechlichen Push-Zustand eines Branches, Letztere simulieren, wie der Code nach einem Merge aussehen wuerde. Dieser Artikel erklaert den Unterschied im Detail und zeigt, wie sich mit workflow:rules doppelte Pipelines zuverlaessig vermeiden lassen.
Inhaltsverzeichnis
- 1. Was eine Branch-Pipeline tatsaechlich testet
- 2. Wie Merge-Request-Pipelines den Ergebniszustand testen
- 3. CI_PIPELINE_SOURCE als zentrale Unterscheidung
- 4. Das Problem doppelter Pipelines ohne workflow:rules
- 5. workflow:rules als saubere Loesung
- 6. Merge-Widget und Pipeline-Erfolgs-Anforderungen
- 7. Performance-Aspekt: Merge-Ref-Berechnung und Caching
- 8. Wann reine Branch-Pipelines ausreichen
- 9. Fazit: Zwei Pipeline-Typen fuer zwei unterschiedliche Fragen
- 10. Zusammenfassung
- 11. FAQ
1. Was eine Branch-Pipeline tatsaechlich testet
Eine Branch-Pipeline, in GitLab intern als push-Pipeline gefuehrt, startet automatisch bei jedem Push auf einen Branch und testet exakt den Zustand des Codes, wie er in diesem Branch zu diesem Zeitpunkt vorliegt. Das ist das Standardverhalten, das viele Entwickler von GitLab kennen, und es beantwortet eine klare Frage: Funktioniert der Code so, wie er gerade im Branch steht. Fuer Feature-Branches ohne aktiven Merge Request ist das oft die einzig sinnvolle Frage, weil noch gar nicht feststeht, in welchen Ziel-Branch der Code irgendwann gemerged wird.
Der entscheidende Punkt ist, dass eine Branch-Pipeline nichts darueber aussagt, wie der Code sich verhaelt, nachdem er mit dem Ziel-Branch zusammengefuehrt wurde. Wenn zwischen dem letzten Push auf den Feature-Branch und dem tatsaechlichen Merge noch Aenderungen am Ziel-Branch, meist main oder develop, dazukommen, kann es zu Konflikten oder zu subtilen Inkompatibilitaeten kommen, die eine reine Branch-Pipeline niemals aufdeckt, weil sie den Ziel-Branch bei ihrem Testlauf komplett ignoriert. Genau diese Luecke schliessen Merge-Request-Pipelines.
2. Wie Merge-Request-Pipelines den Ergebniszustand testen
Eine Merge-Request-Pipeline wird ausgeloest, sobald ein Merge Request geoeffnet oder aktualisiert wird, und sie testet nicht den reinen Branch-Zustand, sondern einen simulierten Merge-Commit, der aus dem aktuellen Stand des Feature-Branches und dem aktuellen Stand des Ziel-Branches gebildet wird. GitLab erzeugt dafuer intern einen temporaeren Merge-Ref, der beide Zustaende zusammenfuehrt, und fuehrt die Pipeline gegen diesen simulierten Zustand aus, nicht gegen den reinen Feature-Branch. Damit beantwortet eine Merge-Request-Pipeline die eigentlich relevante Frage: Funktioniert der Code, nachdem er tatsaechlich gemerged wurde, inklusive aller zwischenzeitlichen Aenderungen am Ziel-Branch.
Diese Eigenschaft macht Merge-Request-Pipelines besonders wertvoll in Teams mit hoher Commit-Frequenz auf dem Ziel-Branch, weil dort die Wahrscheinlichkeit steigt, dass sich Ziel-Branch und Feature-Branch zwischenzeitlich auseinanderentwickeln. Ein zusaetzlicher praktischer Vorteil ist, dass Merge-Request-Pipelines im Merge-Request-Interface direkt sichtbar sind, inklusive Diff-Annotationen bei fehlgeschlagenen Tests und der Moeglichkeit, das Merge-Widget so zu konfigurieren, dass ein Merge erst erlaubt wird, wenn die Merge-Request-Pipeline erfolgreich war, was bei reinen Branch-Pipelines ohne Zusatzkonfiguration nicht garantiert ist.
test_mr:
stage: test
script:
- vendor/bin/phpunit
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
3. CI_PIPELINE_SOURCE als zentrale Unterscheidung
Technisch unterscheiden sich beide Pipeline-Typen ueber die vordefinierte Variable CI_PIPELINE_SOURCE, die bei einer Branch-Pipeline den Wert push und bei einer Merge-Request-Pipeline den Wert merge_request_event annimmt. Diese Variable ist die zentrale Grundlage fuer alle rules- und workflow:rules-Bedingungen, mit denen sich das Verhalten von Jobs je nach Pipeline-Typ steuern laesst. Zusaetzlich stehen bei Merge-Request-Pipelines weitere Variablen wie CI_MERGE_REQUEST_TARGET_BRANCH_NAME und CI_MERGE_REQUEST_SOURCE_BRANCH_NAME zur Verfuegung, die bei reinen Branch-Pipelines gar nicht gesetzt sind, weil dort schlicht kein Merge Request existiert, auf den sie sich beziehen koennten.
Diese zusaetzlichen Variablen sind praktisch fuer Jobs, die sich unterschiedlich verhalten sollen, je nachdem in welchen Ziel-Branch gemerged werden soll, etwa um bei einem Merge Request Richtung main strengere Test-Anforderungen zu stellen als bei einem Merge Request zwischen zwei Feature-Branches. Wer diese Variablen in einer Branch-Pipeline referenziert, erhaelt schlicht einen leeren Wert, was ein haeufiger Grund fuer unerwartetes Job-Verhalten ist, wenn Teams beide Pipeline-Typen parallel einsetzen, ohne die Unterschiede in der Variablen-Verfuegbarkeit zu beruecksichtigen.
4. Das Problem doppelter Pipelines ohne workflow:rules
Ohne explizite Konfiguration laufen fuer denselben Commit potenziell zwei komplette Pipelines gleichzeitig: eine Branch-Pipeline, weil ein Push stattgefunden hat, und eine Merge-Request-Pipeline, weil fuer diesen Branch bereits ein offener Merge Request existiert. Beide Pipelines fuehren im Wesentlichen dieselben Jobs aus, verdoppeln damit den CI-Minuten-Verbrauch und ueberladen sowohl die Commit-Ansicht als auch die Merge-Request-Ansicht mit zwei parallelen, oft leicht unterschiedlichen Status-Icons, was bei Entwicklern regelmaessig zu Verwirrung fuehrt, welcher der beiden Status eigentlich massgeblich ist.
Dieses Verhalten ist kein Fehler, sondern die logische Konsequenz daraus, dass GitLab beide Pipeline-Typen unabhaengig voneinander ausloest, sofern nichts anderes konfiguriert ist. Fuer Projekte, die noch keine Merge-Request-Pipelines nutzen, faellt das Problem nicht auf, aber sobald ein Team von reinen Branch-Pipelines auf Merge-Request-Pipelines umstellt, ohne gleichzeitig die Branch-Pipeline fuer Branches mit offenem Merge Request zu unterdruecken, verdoppelt sich der CI-Ressourcenverbrauch faktisch ueber Nacht, oft unbemerkt, bis jemand die CI-Minuten-Abrechnung genauer pruft.
5. workflow:rules als saubere Loesung
Die von GitLab empfohlene Loesung ist eine workflow:rules-Konfiguration auf oberster Ebene der .gitlab-ci.yml, die festlegt, unter welchen Bedingungen ueberhaupt eine Pipeline gestartet wird, bevor einzelne Job-Regeln ausgewertet werden. Das gaengige Muster besagt: Wenn ein Merge Request fuer den aktuellen Branch existiert, soll ausschliesslich die Merge-Request-Pipeline laufen und die Branch-Pipeline unterdrueckt werden; existiert kein Merge Request, etwa bei einem frischen Feature-Branch ohne geoeffneten Merge Request, soll die Branch-Pipeline weiterhin normal laufen, damit Entwickler auch ohne Merge Request sofortiges Feedback zu ihrem Push bekommen.
Diese Logik laesst sich mit einer Kombination aus $CI_PIPELINE_SOURCE und der Variable $CI_OPEN_MERGE_REQUESTS oder direkter mit einer Regel-Reihenfolge abbilden, die Merge-Request-Events zuerst zulaesst und Branch-Pushes nur dann, wenn kein passender Merge Request existiert. GitLab bietet dafuer inzwischen auch eine vorkonfigurierte Vorlage namens Workflows/MergeRequest-Pipelines, die per include eingebunden werden kann und genau dieses empfohlene Muster fertig implementiert, sodass Teams nicht jedes Mal die exakte Bedingungslogik von Grund auf neu schreiben muessen.
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- if: '$CI_COMMIT_TAG'
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: '$CI_COMMIT_BRANCH'
6. Merge-Widget und Pipeline-Erfolgs-Anforderungen
Ein wichtiger praktischer Vorteil von Merge-Request-Pipelines ist ihre enge Integration mit dem Merge-Widget im Merge Request selbst. In den Projekteinstellungen unter Merge requests laesst sich die Option Pipelines must succeed aktivieren, die einen Merge erst erlaubt, wenn die zugehoerige Merge-Request-Pipeline erfolgreich durchgelaufen ist. Diese Kopplung funktioniert zuverlaessig nur mit echten Merge-Request-Pipelines, weil GitLab bei reinen Branch-Pipelines nicht immer eindeutig zuordnen kann, welcher Pipeline-Lauf tatsaechlich fuer den aktuellen Merge-Request-Zustand massgeblich ist, insbesondere wenn zwischen dem letzten Push und dem Merge-Versuch Zeit vergangen ist.
Zusaetzlich lassen sich mit Merge-Request-Pipelines auch Approval-Regeln kombinieren, etwa dass ein Merge Request erst gemerged werden darf, wenn sowohl die Pipeline erfolgreich war als auch eine bestimmte Anzahl an Code-Owner-Genehmigungen vorliegt. Diese Kombination aus technischer Absicherung durch die Pipeline und menschlicher Absicherung durch Reviewer ist in Teams mit strengen Qualitaetsanforderungen, etwa bei sicherheitskritischer Software oder bei Projekten mit vielen gleichzeitig arbeitenden Contributor, ein zentraler Baustein, um zu verhindern, dass fehlerhafter Code ungeprueft in den Ziel-Branch gelangt.
7. Performance-Aspekt: Merge-Ref-Berechnung und Caching
Ein oft uebersehener Aspekt ist, dass die Berechnung des simulierten Merge-Ref fuer eine Merge-Request-Pipeline zusaetzlichen Overhead gegenueber einer reinen Branch-Pipeline bedeutet, weil GitLab vor dem eigentlichen Pipeline-Start pruefen muss, ob Feature-Branch und Ziel-Branch konfliktfrei zusammengefuehrt werden koennen. Bei den meisten Projekten ist dieser Overhead vernachlaessigbar gering, kann aber bei sehr grossen Repositories mit langer Historie und haeufigen Merge-Konflikten spuerbar werden, insbesondere wenn viele Merge Requests gleichzeitig gegen denselben, sich schnell aendernden Ziel-Branch getestet werden.
Fuer Caching-Strategien ist ausserdem relevant, dass eine Merge-Request-Pipeline typischerweise einen anderen Cache-Key-Kontext hat als eine Branch-Pipeline, weil sich der zugrunde liegende simulierte Commit bei jedem Update des Ziel-Branches technisch aendert, auch wenn der Feature-Branch selbst unveraendert bleibt. Teams, die aggressive Caching-Strategien mit dem Ziel-Branch-Namen im Cache-Key verwenden, sollten das beruecksichtigen, um zu vermeiden, dass ein Cache staendig neu aufgebaut wird, obwohl sich der fuer den Cache relevante Code gar nicht geaendert hat.
8. Wann reine Branch-Pipelines ausreichen
Nicht jedes Projekt braucht zwingend Merge-Request-Pipelines. Bei kleinen internen Tools, bei Projekten mit sehr niedriger Commit-Frequenz auf dem Ziel-Branch oder bei Solo-Entwicklern ohne Review-Prozess ist der Zusatznutzen der Merge-Ergebnis-Simulation gering, weil sich Feature-Branch und Ziel-Branch selten so weit auseinanderentwickeln, dass ein reiner Branch-Test die Realitaet nicht mehr widerspiegelt. In solchen Faellen reicht eine einfache Branch-Pipeline-Konfiguration oft aus und vermeidet die zusaetzliche Komplexitaet von workflow:rules und Merge-Request-spezifischen Variablen.
Anders sieht es bei Teams mit mehreren aktiven Contributor und einem Ziel-Branch aus, der mehrfach taeglich aktualisiert wird, etwa durch andere parallel gemergte Merge Requests. Dort steigt die Wahrscheinlichkeit, dass ein Feature-Branch zum Zeitpunkt seines letzten Pushes zwar problemlos funktioniert, nach dem tatsaechlichen Merge aber durch zwischenzeitliche Aenderungen am Ziel-Branch bricht, deutlich, und genau dieses Szenario ist der Hauptgrund, warum sich Merge-Request-Pipelines in aktiven Teams langfristig durchsetzen, trotz des zusaetzlichen Konfigurationsaufwands mit workflow:rules.
9. Fazit: Zwei Pipeline-Typen fuer zwei unterschiedliche Fragen
Branch-Pipelines und Merge-Request-Pipelines beantworten unterschiedliche Fragen, die beide ihre Berechtigung haben: Funktioniert der Code so, wie er im Branch steht, gegenueber Funktioniert der Code so, wie er nach dem Merge aussehen wuerde. Fuer Teams mit aktivem Merge-Request-Workflow und mehreren Contributor ist die Kombination aus Merge-Request-Pipelines und einer sauberen workflow:rules-Konfiguration, die doppelte Branch-Pipelines unterdrueckt, der empfohlene Standardansatz, weil er sowohl realistischere Tests als auch geringeren CI-Ressourcenverbrauch liefert.
Die folgende Tabelle stellt beide Pipeline-Typen entlang der wichtigsten praktischen Kriterien gegenueber, als schnelle Referenz fuer die eigene Konfigurationsentscheidung.
| Kriterium | Branch-Pipeline | Merge-Request-Pipeline | Praxis-Hinweis |
|---|---|---|---|
| Getesteter Zustand | reiner Push-Zustand des Branches | simulierter Merge-Commit mit Ziel-Branch | MR-Pipeline naeher an der Realitaet nach Merge |
| CI_PIPELINE_SOURCE | push | merge_request_event | Basis fuer rules-Unterscheidung |
| Merge-Widget-Integration | eingeschraenkt | vollstaendig, inkl. Pipelines-must-succeed | fuer verbindliche Qualitaetschecks MR-Pipeline nutzen |
| Ohne Konfiguration bei offenem MR | laeuft zusaetzlich, oft ungewollt | laeuft zusaetzlich, oft ungewollt | workflow:rules zur Vermeidung doppelter Laeufe einsetzen |
| Verfuegbare Variablen | CI_COMMIT_BRANCH etc. | zusaetzlich CI_MERGE_REQUEST_* Variablen | fuer ziel-branch-abhaengige Logik MR-Variablen nutzen |
Mironsoft
CI/CD-Pipelines, Zero-Downtime-Deployments und Release-Automatisierung
Deployments, die ohne Ausfallzeit und ohne Nervenkitzel laufen?
Wir prüfen bestehende GitLab-Pipelines auf fragile Deployment-Schritte und fehlende Absicherung und bauen daraus einen Release-Prozess mit Zero-Downtime-Deployments, automatisierten Checks und einem Rollback, dem ihr im Ernstfall vertrauen könnt.
Pipeline-Review
Bestehende .gitlab-ci.yml auf Fragilität, fehlende Stages und Sicherheitslücken prüfen.
Zero-Downtime-Deployment
Symlink-Releases, Health-Checks und Rollback-Strategien für Magento-Shops aufbauen.
CI/CD-Automatisierung
Tests, Security-Scans und Deployments zu einer zuverlässigen Pipeline verbinden.
10. Zusammenfassung
MR-Pipelines vs. Branch-Pipelines: Das Wichtigste auf einen Blick
Branch-Pipeline testet
Den reinen Push-Zustand eines Branches, unabhaengig davon, ob und wohin spaeter gemerged wird.
Merge-Request-Pipeline testet
Einen simulierten Merge-Commit aus Feature-Branch und aktuellem Ziel-Branch-Stand.
Doppelte Pipelines vermeiden
workflow:rules auf oberster Ebene unterdrueckt Branch-Pipelines, sobald ein offener Merge Request existiert.
Merge-Widget-Vorteil
Nur Merge-Request-Pipelines lassen sich zuverlaessig mit Pipelines-must-succeed und Approval-Regeln koppeln.