Wenn du Inhalte aus einem Remote-Repository herunterladen möchtest, stehen dir die Befehle git pull und git fetch zur Verfügung. Dabei ist git fetch sozusagen die "sichere" Variante: Damit werden die Remote-Inhalte heruntergeladen, aber es erfolgt keine Aktualisierung des Arbeitsstatus deines lokalen Repositorys, sodass deine aktuelle Arbeit davon unberührt bleibt. Dagegen ist git pull der "aggressivere" Befehl: Damit werden die Remote-Inhalte für den aktiven lokalen Branch heruntergeladen, unmittelbar gefolgt von der Ausführung des Befehls git merge zum Erstellen eines Merge-Commits für die neuen Remote-Inhalte. Wenn noch ausstehende Änderungen vorhanden sind, entstehen Konflikte, und der Ablauf zum Lösen von Merge-Konflikten wird gestartet.

So funktioniert "git fetch" bei Remote-Branches

git branch
main
feature1
debug2

Eine Abfrage der Inhalte des Verzeichnisses /.git/refs/heads/ hätte eine ähnliche Ausgabe.

ls ./.git/refs/heads/
main
feature1
debug2

Im Grunde genommen sind Remote-Branches dasselbe wie lokale Branches. Der einzige Unterschied: Sie sind Commits aus dem Repository eines anderen Benutzers zugeordnet. Bei Remote-Branches wird als Präfix das Remote-Repository angegeben, zu dem sie gehören. So ist eine Verwechslung mit lokalen Branches ausgeschlossen. Ebenso wie bei lokalen Branches gibt es in Git Verweise auf Remote-Branches. Diese Remote-Branch-Verweise sind im Verzeichnis ./.git/refs/remotes/ zu finden. Der Codeausschnitt unten beispielsweise zeigt Branches, die beim Abrufen eines Remote-Repositorys mit dem Namen "remote-repo" zurückgegeben würden:

git branch -r
# origin/main
# origin/feature1
# origin/debug2
# remote-repo/main
# remote-repo/other-feature

In dieser Ausgabe sind dieselben lokalen Branches enthalten wie zuvor, nun aber mit dem Präfix origin/. Die Remote-Branches sind jetzt mit dem Präfix remote-repo gekennzeichnet. Genau wie lokale Branches kannst du auch Remote-Branches auschecken. Dadurch wechselst du jedoch in einen Zustand mit losgelöstem HEAD. (Gleiches passiert, wenn du einen alten Commit auscheckst.) Du kannst dir Branches dieses Typs wie schreibgeschützte Branches vorstellen. Wenn du deine Remote-Branches abrufen möchtest, übergib einfach das Flag -r an den Befehl git branch.

Genauer ansehen kannst du dir Remote-Branches mit den regulären Befehlen git checkout und git log. Möchtest du die Änderungen in einem Remote-Branch übernehmen, kannst du den Branch mit dem normalen Befehl git merge mit einem deiner lokalen Branches mergen. Anders als in SVN ist die Synchronisierung eines lokalen Repositorys mit einem Remote-Repository also ein zweistufiger Prozess: Zuerst musst du einen Fetch durchführen, anschließend einen Merge. Abkürzen kannst du das Ganze über den Befehl git pull.

"git fetch" – Befehle und Optionen

git fetch <remote>

Ruft alle Branches vom Repository ab. Dabei werden auch alle erforderlichen Commits und Dateien des anderen Repositorys heruntergeladen.

git fetch <remote> <branch>

Wie der Befehl oben, aber nur der angegebene Branch wird abgerufen

git fetch --all

Ein wichtiger Befehl, mit dem alle registrierten Remote-Repositorys und deren Branches abgerufen werden:

git fetch --dry-run

Mit der Option --dry-run wird die Ausführung des Befehls demonstriert. Die Ausgabe zeigt Beispiele für die Aktionen, die beim Abrufen ausgeführt werden. Diese werden jedoch nicht tatsächlich angewendet.

"git fetch" – Beispiele

"git fetch" bei Remote-Branches

Das nächste Beispiel zeigt, wie du einen Remote-Branch abrufen und deinen lokalen Arbeitsstatus mit den Remote-Inhalten aktualisieren kannst. Für das Beispiel gehen wir davon aus, dass es ein zentrales Repository als Ursprung gibt, aus dem das lokale Repository mit dem Befehl git clone geklont wurde. Außerdem treffen wir die Annahme, dass ein weiteres Remote-Repository namens "coworkers_repo" vorhanden ist, das einen feature_branch enthält, den wir konfigurieren und abrufen möchten. Unter diesen angenommenen Voraussetzungen kommen wir nun zu unserem Beispiel.

git remote add coworkers_repo git@bitbucket.org:coworker/coworkers_repo.git

Hier haben wir mithilfe der Repository-URL einen Verweis auf das coworkers-Repository erstellt. Wir übergeben diesen Remote-Namen nun an git fetch, um die Inhalte herunterzuladen.

git fetch coworkers_repo coworkers/feature_branch
fetching coworkers/feature_branch
git checkout coworkers/feature_branch
Note: checking out coworkers/feature_branch'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b <new-branch-name>

Die Ausgabe dieses Checkout-Vorgangs zeigt uns, dass wir uns in einem Zustand mit losgelöstem HEAD befinden. Dies entspricht unserer Erwartung und bedeutet, dass der HEAD-Verweis auf einen Verweis zeigt, der nicht mit dem lokalen Verlauf synchron ist. Da HEAD auf coworkers/feature_branch verweist, können wir daraus einen neuen lokalen Branch erstellen. Die Ausgabe mit losgelöstem HEAD zeigt uns, wie wir dies mit dem Befehl git checkout erreichen können:

git checkout -b local_feature_branch

Hier haben wir einen neuen lokalen Branch mit der Bezeichnung "local_feature_branch" erstellt. Auf diese Weise wird HEAD so aktualisiert, dass er auf die aktuellen Remote-Inhalte verweist. An diesem Punkt können wir mit der Entwicklung fortfahren.

Synchronisierung des Ursprungs mit "git fetch"

Im folgenden Beispiel spielen wir den typischen Workflow zur Synchronisierung deines lokalen Repositorys mit dem Master-Branch des zentralen Repositorys durch.

git fetch origin

So können die heruntergeladenen Branches angezeigt werden:

a1e8fb5..45e66a4 main -> origin/main
a1e8fb5..9e8ab1c develop -> origin/develop
* [new branch] some-feature -> origin/some-feature

Die Commits aus diesen neuen Remote-Branches sind im Schaubild als Quadrate statt als Kreise dargestellt. Wie du siehst, hast du über git fetch Zugriff auf die gesamte Branch-Struktur eines anderen Repositorys.

Wenn du herausfinden möchtest, welche Commits zum Upstream-Master hinzugefügt wurden, kannst du git log mit dem Filter origin/master ausführen:

git log --oneline main..origin/main

Führe die folgenden Befehle aus, um die Änderungen zu genehmigen und in deinen lokalen Master-Branch zu mergen:

git checkout main
git log origin/main

Jetzt führst du git merge origin/master aus:

git merge origin/main

Die origin/master- und master-Branches verweisen nun auf denselben Commit und die Synchronisierung mit Upstream-Entwicklungen ist abgeschlossen.

"git fetch" – Zusammenfassung