Wie man mit Git einen „pull --force“ erzwingen kann, um lokale Dateien zu überschreiben
Du bist auf einem Server, in der Arbeitskopie wurden ein paar Dateien von Hand geändert, und Du willst nur
noch den Stand aus dem Repository — genau so, wie er in origin liegt, ohne Merge, ohne Rückfragen. Der
Befehl, nach dem die meisten suchen, ist git pull --force. Den gibt es, aber er tut das nicht. Der Schalter
geht an git fetch und erlaubt dort nur, Referenzen ohne Fast-Forward zu aktualisieren; Deine lokalen Dateien
sind nicht seine Sache.
Zwei Befehle machen die Arbeit.
Die zwei Schritte
git fetch --all
git reset --hard origin/main
git fetch --all lädt den aktuellen Stand aller Remotes, ohne Deine Dateien anzufassen. git reset --hard
setzt Deinen Zweig dann auf diesen Stand und überschreibt dabei jede versionierte Datei.
Wenn der Zweig nicht main heißt, nenne ihn:
git reset --hard origin/<zweigname>
Nicht sicher, welchen Zweig der aktuelle verfolgt? Das zeigt es:
git rev-parse --abbrev-ref --symbolic-full-name @{u}
Der Fehler, den reset nicht behebt
Ein Pull auf einem Server scheitert oft so:
error: Untracked working tree file 'data/datei.php' would be overwritten by merge.
Das entscheidende Wort ist untracked, unversioniert. Git kennt diese Datei nicht, also lässt
git reset --hard sie liegen, und der nächste Pull scheitert erneut. Unversionierte Dateien brauchen ihren
eigenen Befehl:
git clean -n -d # Probelauf: zeigt, was gelöscht würde
git clean -f -d # löscht unversionierte Dateien und Verzeichnisse
Immer zuerst den Probelauf. Und Vorsicht mit -x: das löscht auch Dateien, die in .gitignore stehen — auf
einem Live-Server typischerweise .env, hochgeladene Medien oder eine lokale Konfiguration. So wird aus einer
schnellen Reparatur eine Wiederherstellung aus dem Backup.
Vorher die eigene Arbeit sichern
git reset --hard und git clean -fd löschen beide ohne Rückfrage. Zwei Sekunden Versicherung:
git stash -u # sichert versionierte und unversionierte Änderungen
# oder
git branch sicherung-$(date +%F) # sichert die aktuellen Commits unter einem Namen
Mit dem Stash kannst Du den verworfenen Stand später mit git stash show -p ansehen oder mit
git stash pop zurückholen.
Für Deployments
Wenn Du durch einen Pull in eine Arbeitskopie ausrollst, mach den Reset zum Teil des Deploy-Skripts statt zur Rettungsaktion von Hand:
git fetch --all
git reset --hard "origin/$ZWEIG"
git clean -fd # ohne -x, damit .env und Uploads überleben
Das ergibt bei jedem Lauf dasselbe Ergebnis, unabhängig davon, was jemand auf dem Server geändert hat. Der saubere Weg ist, woanders zu bauen und das Ergebnis zu übertragen, damit auf dem Server gar kein Git-Repository liegt — aber solange Du auf dem Server pullst, sind die drei Zeilen oben die ehrliche Fassung von „force pull“.
Häufige Fragen
Gibt es ein echtes git pull --force?
Den Schalter gibt es, aber er überschreibt keine Dateien. Er wird an git fetch weitergegeben und erlaubt dort nur, lokale Referenzen ohne Fast-Forward zu aktualisieren. Damit eine Arbeitskopie dem Remote entspricht, brauchst Du git reset --hard und für unversionierte Dateien git clean.
Warum entfernt git reset --hard die Datei aus der Fehlermeldung nicht?
Weil die Datei unversioniert ist: Git kennt sie nicht und fasst sie darum nicht an. Nur git clean -fd entfernt unversionierte Dateien und Verzeichnisse.
Ich habe gerade einen lokalen Commit verloren. Kriege ich ihn zurück?
Meistens ja. git reflog zeigt, wo HEAD vor dem Reset stand, und git reset --hard <hash> geht auf diesen Stand zurück. Das gilt nur für Arbeit, die committet war; nicht gesicherte Änderungen ohne Stash sind weg.
Was ist der Unterschied zu git checkout -- . ?
git checkout -- . stellt versionierte Dateien aus dem aktuellen Commit wieder her, nimmt also lokale Änderungen zurück, lässt den Zweig aber stehen. git reset --hard origin/main verschiebt zusätzlich den Zweig auf den Stand des Remote — und genau das willst Du nach einem Fetch.