Git Pull Force - So überschreiben Sie lokale Änderungen mit Git

Wenn Sie das Codieren lernen, lernen Sie früher oder später auch Versionskontrollsysteme kennen. Und obwohl es in diesem Bereich viele konkurrierende Tools gibt, ist eines davon der De-facto-Standard, der von fast allen in der Branche verwendet wird. Es ist so beliebt, dass es Unternehmen gibt, die ihren Namen in ihrem Branding verwenden. Wir reden natürlich über Git.

Während Git ein mächtiges Werkzeug ist, ist seine Kraft gut versteckt. Es gibt einige wesentliche Konzepte, die Sie verstehen müssen, um Git wirklich zu beherrschen. Die gute Nachricht ist, dass Sie, sobald Sie sie gelernt haben, kaum in Schwierigkeiten geraten, denen Sie nicht entkommen können.

Der typische Workflow

In einem typischen Git-Workflow verwenden Sie ein lokales Repository, ein Remote-Repository und einen oder mehrere Zweige. In Repositorys werden alle Informationen zum Projekt gespeichert, einschließlich des gesamten Verlaufs und aller Zweige. Ein Zweig ist im Grunde eine Sammlung von Änderungen, die von einem leeren Projekt zum aktuellen Status führen.

Nach dem Klonen eines Repositorys arbeiten Sie an Ihrer lokalen Kopie und führen neue Änderungen ein. Bis Sie lokale Änderungen in das Remote-Repository übertragen, ist Ihre gesamte Arbeit nur auf Ihrem Computer verfügbar.

Wenn Sie eine Aufgabe abgeschlossen haben, ist es Zeit, mit dem Remote-Repository zu synchronisieren. Sie möchten die Remote-Änderungen abrufen, um mit dem Projektfortschritt Schritt zu halten, und Sie möchten die lokalen Änderungen verschieben, um Ihre Arbeit mit anderen zu teilen.

Lokale Änderungen

Alles ist gut, wenn Sie und der Rest Ihres Teams an völlig getrennten Dateien arbeiten. Was auch immer passiert, Sie werden sich nicht gegenseitig auf die Füße treten.

Es gibt jedoch Zeiten, in denen Sie und Ihre Teamkollegen gleichzeitig Änderungen an derselben Stelle vornehmen. Und hier beginnen normalerweise die Probleme.

Haben Sie jemals git pullnur hingerichtet , um die gefürchteten zu sehen error: Your local changes to the following files would be overwritten by merge:? Früher oder später stößt jeder auf dieses Problem.

Was hier verwirrender ist, ist, dass Sie nichts zusammenführen möchten, sondern nur ziehen, oder? Tatsächlich ist das Ziehen etwas komplizierter, als Sie vielleicht gedacht haben.

Wie genau funktioniert Git Pull?

Ziehen ist keine einzelne Operation. Es besteht aus dem Abrufen von Daten vom Remote-Server und dem anschließenden Zusammenführen der Änderungen mit dem lokalen Repository. Diese beiden Vorgänge können manuell ausgeführt werden, wenn Sie möchten:

git fetch git merge origin/$CURRENT_BRANCH

Der origin/$CURRENT_BRANCHTeil bedeutet, dass:

  • Git führt die Änderungen aus dem Remote-Repository mit dem Namen origin(dem, aus dem Sie geklont haben) zusammen.
  • das wurden hinzugefügt $CURRENT_BRANCH
  • die nicht bereits in Ihrer lokalen ausgecheckten Filiale vorhanden sind

Da Git nur Zusammenführungen durchführt, wenn keine nicht festgeschriebenen Änderungen vorhanden sind, kann jedes Mal, wenn Sie git pullmit nicht festgeschriebenen Änderungen ausgeführt werden, Probleme auftreten. Glücklicherweise gibt es Möglichkeiten, Probleme in einem Stück zu lösen!

Wir sind eine Familie

Unterschiedliche Ansätze

Wenn Sie lokale Änderungen nicht festgeschrieben haben und dennoch eine neue Version vom Remoteserver abrufen möchten, fällt Ihr Anwendungsfall normalerweise in eines der folgenden Szenarien. Entweder:

  • Sie interessieren sich nicht für die lokalen Änderungen und möchten sie überschreiben.
  • Sie interessieren sich sehr für die Änderungen und möchten sie nach den Remote-Änderungen anwenden.
  • Sie möchten die Remote-Änderungen herunterladen, aber noch nicht anwenden

Jeder der Ansätze erfordert eine andere Lösung.

Die lokalen Änderungen interessieren Sie nicht

In diesem Fall möchten Sie nur alle nicht festgeschriebenen lokalen Änderungen löschen. Möglicherweise haben Sie eine Datei zum Experimentieren geändert, aber Sie benötigen die Änderung nicht mehr. Alles, was Sie interessiert, ist, mit dem Upstream auf dem neuesten Stand zu sein.

Dies bedeutet, dass Sie einen weiteren Schritt zwischen dem Abrufen der Remote-Änderungen und dem Zusammenführen hinzufügen. Dieser Schritt setzt den Zweig in seinen unveränderten Zustand zurück und ermöglicht so das git mergeArbeiten.

git fetch git reset --hard HEAD git merge origin/$CURRENT_BRANCH

Wenn Sie den Zweignamen nicht jedes Mal eingeben möchten, wenn Sie diesen Befehl ausführen, hat Git eine nette Verknüpfung, die auf den vorgelagerten Zweig verweist : @{u}. Ein Upstream-Zweig ist der Zweig im Remote-Repository, in den Sie pushen und von dem Sie ihn abrufen.

So würden die obigen Befehle mit der Verknüpfung aussehen:

git fetch git reset --hard HEAD git merge '@{u}'

Wir zitieren die Verknüpfung im Beispiel, um zu verhindern, dass die Shell sie interpretiert.

Sie kümmern sich sehr um die lokalen Änderungen

Wenn Ihre nicht festgeschriebenen Änderungen für Sie von Bedeutung sind, gibt es zwei Möglichkeiten. Sie können sie festschreiben und dann ausführen git pull, oder Sie können sie verstauen.

Verstecken bedeutet, die Änderungen für einen Moment wegzulegen, um sie später zurückzubringen. Genauer gesagt, git stasherstellt ein Commit, das in Ihrem aktuellen Zweig nicht sichtbar ist, auf das Git jedoch weiterhin zugreifen kann.

Verwenden Sie den git stash popBefehl , um die im letzten Stash gespeicherten Änderungen wiederherzustellen . Nach erfolgreichem Anwenden der versteckten Änderungen entfernt dieser Befehl auch das Stash-Commit, da es nicht mehr benötigt wird.

Der Workflow könnte dann folgendermaßen aussehen:

git fetch git stash git merge '@{u}' git stash pop

By default, the changes from the stash will become staged. If you want to unstage them, use the command git restore --staged (if using Git newer than 2.25.0).

You Just Want to Download the Remote Changes

The last scenario is a little different from the previous ones. Let's say that you are in the middle of a very messy refactoring. Neither losing the changes nor stashing them is an option. Yet, you still want to have the remote changes available to run git diff against them.

As you have probably figured out, downloading the remote changes does not require git pull at all! git fetch is just enough.

One thing to note is that by default, git fetch will only bring you changes from the current branch. To get all the changes from all the branches, use git fetch --all. And if you'd like to clean up some of the branches that no longer exist in the remote repository, git fetch --all --prune will do the cleaning up!

Some Automation

Have you heard of Git Config? It's a file where Git stores all of the user-configured settings. It resides in your home directory: either as ~/.gitconfig or ~/.config/git/config. You can edit it to add some custom aliases that will be understood as Git commands.

For example, to have a shortcut equivalent to git diff --cached (that shows the difference between the current branch and the staged files), you'd add the following section:

[alias] dc = diff --cached

After that, you can run git dc whenever you wish to review the changes. Going this way, we can set up a few aliases related to the previous use cases.

[alias] pull_force = !"git fetch --all; git reset --hard HEAD; git merge @{u}" pf = pull_force pull_stash = !"git fetch --all; git stash; git merge @{u}; git stash pop"

This way, running git pull_force will overwrite the local changes, while git pull_stash will preserve them.

The Other Git Pull Force

Curious minds may have already discovered that there is such a thing as git pull --force. However, this is a very different beast to what's presented in this article.

It may sound like something that would help us overwrite local changes. Instead, it lets us fetch the changes from one remote branch to a different local branch. git pull --force only modifies the behavior of the fetching part. It is therefore equivalent to git fetch --force.

Like git push, git fetch allows us to specify which local and remote branch do we want to operate on. git fetch origin/feature-1:my-feature will mean that the changes in the feature-1 branch from the remote repository will end up visible on the local branch my-feature. When such an operation modifies the existing history, it is not permitted by Git without an explicit --force parameter.

Just like git push --force allows overwriting remote branches, git fetch --force (or git pull --force) allows overwriting local branches. It is always used with source and destination branches mentioned as parameters. An alternative approach to overwriting local changes using git --pull force could be git pull --force "@{u}:HEAD".

Conclusion

Die Welt von Git ist riesig. Dieser Artikel behandelte nur eine der Facetten der Repository-Wartung: das Einbeziehen von Remote-Änderungen in ein lokales Repository. Selbst in diesem alltäglichen Szenario mussten wir die internen Mechanismen dieses Versionskontrolltools etwas genauer untersuchen.

Wenn Sie die tatsächlichen Anwendungsfälle kennenlernen, können Sie besser verstehen, wie Git unter der Haube funktioniert. Dies wiederum gibt Ihnen das Gefühl, gestärkt zu sein, wenn Sie in Schwierigkeiten geraten. Das machen wir alle von Zeit zu Zeit.