Git Force Push: Was der Befehl macht und wann er sicher ist

Programmierung

Ein normaler git push weigert sich, wenn Ihr lokaler Branch nicht der direkte Nachfolger des Remote-Branches ist. Genau dann kommt der Force Push ins Spiel: Er drückt Ihren lokalen Stand durch und überschreibt die Historie auf dem Server. Das ist mächtig – und genau deshalb das häufigste Mittel, mit dem Teams sich gegenseitig Commits löschen. Dieser Text zeigt, was beim erzwungenen Push technisch passiert, wann Sie ihn wirklich brauchen, warum --force-with-lease fast immer die bessere Wahl als --force ist und wie Sie einen versehentlich überschriebenen Branch zurückholen.

Was passiert bei einem normalen Push?

Git speichert Ihre Historie als Kette von Commits. Jeder Commit zeigt auf seinen Vorgänger. Ein Branch ist nur ein Zeiger auf den jeweils obersten Commit.

Wenn Sie git push ausführen, prüft der Server: Enthält mein aktueller Branch-Stand als Vorgänger genau den Commit, auf dem Sie aufsetzen? Ist das der Fall, hängt Git Ihre neuen Commits an – ein sogenannter Fast-Forward. Ist es nicht der Fall (weil jemand anderes zwischenzeitlich gepusht hat oder Sie Ihre Historie umgeschrieben haben), lehnt Git ab:

! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs

Diese Ablehnung ist ein Schutzmechanismus. Sie sagt: „Dein Push würde Commits auf dem Server unerreichbar machen.” Der Force Push hebt genau diesen Schutz auf.

Was ein Force Push wirklich tut

git push --force setzt den Branch-Zeiger auf dem Remote hart auf Ihren lokalen Commit – unabhängig davon, was vorher dort stand. Commits, die nur über den alten Zeiger erreichbar waren, sind danach im Branch nicht mehr enthalten.

git push --force origin feature-login

Wichtig: Die Commits werden nicht sofort physisch gelöscht. Git behält sie eine Weile über den Reflog und die Garbage Collection. Aber für alle praktischen Zwecke sind sie aus dem Branch verschwunden, und andere Entwickler bekommen sie beim nächsten git pull nicht mehr.

Typische Situationen, in denen Sie das brauchen:

  • Rebase Ihres Feature-Branches. Nach git rebase main haben Ihre Commits neue Hashes. Der alte Stand auf dem Server passt nicht mehr, ein normaler Push wird abgelehnt – ein Force Push ist hier der reguläre Weg.
  • Commit-Nachricht oder Autor korrigieren. Nach git commit --amend weicht der letzte Commit vom bereits gepushten ab.
  • Versehentlich committete Datei entfernen. Etwa ein Passwort oder eine große Binärdatei, die per git rebase -i oder git reset aus der Historie geholt wurde.

Warum --force gefährlich ist

Das Problem am reinen --force: Er fragt nicht, was auf dem Server steht. Er überschreibt bedingungslos.

Stellen Sie sich vor, Sie arbeiten an feature-login. Sie rebasen und wollen pushen. Zwischen Ihrem letzten pull und dem Push hat eine Kollegin aber noch zwei Commits auf denselben Branch geschoben. Ihr --force löscht diese zwei Commits – ohne Warnung. Die Arbeit ist aus dem Branch weg, und niemand merkt es sofort.

Deshalb gilt für geteilte Branches (main, develop, Release-Branches): niemals ein Force Push. Diese Branches erzwungen umzuschreiben zwingt jeden im Team zu manuellen Reparaturen an ihren lokalen Kopien. Viele Teams sperren das serverseitig über protected branches.

Die sichere Variante: --force-with-lease

Für fast jeden legitimen Force-Push-Fall gibt es die bessere Option:

git push --force-with-lease origin feature-login

--force-with-lease merkt sich, welchen Remote-Stand Ihr Git zuletzt gesehen hat (Ihr origin/feature-login). Vor dem Überschreiben prüft Git: Steht auf dem Server noch genau dieser Stand?

  • Ja – dann hat niemand dazwischengefunkt, der Push geht durch.
  • Nein – dann wurde in der Zwischenzeit gepusht, und Git bricht ab, statt fremde Commits zu löschen.

Damit fangen Sie genau den gefährlichen Fall ab: Sie überschreiben nur, wenn Sie tatsächlich auf dem aktuellsten Stand aufsetzen. Machen Sie sich --force-with-lease zur Standardgewohnheit und greifen Sie nur in Ausnahmen zum harten --force.

Ein Detail, das viele überrascht: Wenn Sie zwischendurch git fetch (oder ein git pull, das intern fetcht) ausgeführt haben, aktualisiert das Ihre Referenz auf origin/…. Dann glaubt --force-with-lease, der fremde Stand sei „Ihr” bekannter Stand, und lässt den Push wieder zu. Fetchen Sie also nicht blind, bevor Sie mit Lease pushen. Um das zusätzlich abzusichern, geben Sie die erwartete Commit-ID explizit an:

git push --force-with-lease=feature-login:<erwarteter-hash> origin feature-login

Kurzformen und praktische Aliase

Git kennt Kurzflaggen:

  • git push -f ist identisch mit git push --force.
  • Für --force-with-lease gibt es keine offizielle Kurzflagge, daher lohnt ein Alias:
git config --global alias.pushf 'push --force-with-lease'

Danach reicht git pushf origin feature-login. Sie bekommen die Sicherheit des Lease, ohne jedes Mal die lange Flagge tippen zu müssen.

Einen überschriebenen Branch wiederherstellen

Angenommen, es ist doch passiert: Jemand hat mit --force Ihre Commits plattgemacht. Solange die Person, deren Commits verloren gingen, sie noch lokal hat, ist die Rettung einfach – sie pusht ihren Stand erneut (idealerweise nach Absprache).

Falls die Commits nur auf dem Server existierten, hilft der Reflog auf der Maschine, die zuletzt den guten Stand hatte:

git reflog

Der Reflog listet jede Bewegung des Branch-Zeigers mit Hash, auch die vor dem Force Push. Sie finden dort eine Zeile wie abc1234 HEAD@{5}: commit: …. Diesen Stand holen Sie zurück:

git checkout -b rettung abc1234

Prüfen Sie anschließend, ob wirklich alles vorhanden ist, und setzen Sie den Branch sauber neu auf. Auf dem Server selbst hilft bei GitHub oder GitLab oft das Event-Log oder die API, um verwaiste Commit-Hashes zu finden, solange die Garbage Collection sie nicht entfernt hat.

Wenn Sie regelmäßig mit riskanten Historien-Operationen arbeiten, machen Sie sich mit den Grundlagen von Git und Versionskontrolle vertraut und legen Sie vorher immer einen benannten Sicherungs-Branch an: git branch backup-vor-rebase kostet nichts und erspart die Reflog-Sucherei.

FAQ

Kann ein Force Push Commits endgültig löschen? Nicht sofort. Die Commits verschwinden aus dem Branch, bleiben aber über den Reflog und als lose Objekte erreichbar, bis Gits Garbage Collection sie aufräumt. Zwei Standardwerte bestimmen das Zeitfenster: Der Reflog hält unerreichbare Einträge rund 30 Tage vor (gc.reflogExpireUnreachable), lose Objekte ohne Referenz räumt git gc nach etwa zwei Wochen weg (gc.pruneExpire). Bis dahin greift die Wiederherstellung per Reflog.

Was ist der Unterschied zwischen --force und --force-with-lease? --force überschreibt den Remote-Branch bedingungslos. --force-with-lease überschreibt nur, wenn der Server noch auf dem Stand ist, den Ihr Git zuletzt gesehen hat. Sobald jemand anderes zwischendurch gepusht hat, bricht die Lease-Variante ab und schützt so vor verlorener Fremdarbeit.

Darf ich main force-pushen, wenn ich alleine am Projekt arbeite? Technisch ja, und in reinen Solo-Repos ist das Risiko gering. Trotzdem lohnt die Gewohnheit, main in Ruhe zu lassen: Sobald ein zweiter Klon dazukommt – ein zweiter Rechner, ein CI-System, ein Kollege – ist der überschriebene Verlauf sofort ein Problem. Nutzen Sie Feature-Branches für Historien-Umbauten und halten Sie main fast-forward-only.

→ Mehr zum Thema: Alle Artikel unter Programmierung