Zusammenführen, Aktualisieren und Ziehen von Git-Zweigen ohne Verwendung von Kassen


628

Ich arbeite an einem Projekt mit zwei Zweigen, A und B. Ich arbeite normalerweise an Zweig A und füge Dinge aus Zweig B zusammen. Für das Zusammenführen würde ich normalerweise Folgendes tun:

git merge origin/branchB

Ich möchte jedoch auch eine lokale Kopie von Zweig B behalten, da ich gelegentlich den Zweig auschecken kann, ohne ihn zuerst mit meinem Zweig A zusammenzuführen. Dazu würde ich Folgendes tun:

git checkout branchB
git pull
git checkout branchA

Gibt es eine Möglichkeit, das oben genannte in einem Befehl auszuführen, ohne den Zweig hin und her wechseln zu müssen? Soll ich das verwenden git update-ref? Wie?



1
Jakubs Antwort auf die erste verknüpfte Frage erklärt, warum dies im Allgemeinen unmöglich ist. Eine andere (a posteriori) Erklärung ist, dass Sie nicht in einem nackten Repo zusammengeführt werden können, so dass eindeutig der Arbeitsbaum erforderlich ist.
Cascabel

3
@Eric: Die häufigsten Gründe sind, dass das Auschecken für große Repos zeitaufwändig ist und Zeitstempel aktualisiert, selbst wenn Sie zur gleichen Version zurückkehren. Denken Sie also, dass alles neu erstellt werden muss.
Cascabel

Die zweite Frage, die ich verlinkt habe, betrifft einen ungewöhnlichen Fall - Zusammenführungen, die schnell vorgespult werden könnten , die das OP jedoch mithilfe der --no-ffOption zusammenführen wollte, wodurch ohnehin ein Zusammenführungs-Commit aufgezeichnet wird. Wenn Sie daran interessiert sind, zeigt meine Antwort dort, wie Sie das tun können - nicht ganz so robust wie meine hier veröffentlichte Antwort, aber die Stärken der beiden könnten sicherlich kombiniert werden.
Cascabel

Antworten:


972

Die kurze Antwort

Solange Sie eine Schnellvorlaufzusammenführung durchführen , können Sie diese einfach verwenden

git fetch <remote> <sourceBranch>:<destinationBranch>

Beispiele:

# Merge local branch foo into local branch master,
# without having to checkout master first.
# Here `.` means to use the local repository as the "remote":
git fetch . foo:master

# Merge remote branch origin/foo into local branch foo,
# without having to checkout foo first:
git fetch origin foo:foo

Während Bernsteins Antwort auch in Fällen mit schnellem Vorlauf funktioniert, ist die Verwendung git fetchauf diese Weise etwas sicherer als nur das gewaltsame Verschieben der Verzweigungsreferenz, da git fetchein versehentliches Nicht-Schnellvorlauf automatisch verhindert wird, solange Sie es nicht verwenden+ in der verwenden refspec.

Die lange Antwort

Sie können einen Zweig B nicht mit Zweig A zusammenführen, ohne vorher A ausgecheckt zu haben, wenn dies zu einer Zusammenführung ohne schnellen Vorlauf führen würde. Dies liegt daran, dass eine Arbeitskopie erforderlich ist, um potenzielle Konflikte zu lösen.

Bei Schnellvorlaufzusammenführungen ist dies jedoch möglich , da solche Zusammenführungen per Definition niemals zu Konflikten führen können. Um dies zu tun, ohne vorher einen Zweig git fetchauszuchecken , können Sie ihn mit einer Referenzspezifikation verwenden.

Hier ist ein Beispiel für die Aktualisierung master(das Nicht-Schnellvorlauf-Änderungen nicht zulässt), wenn Sie einen anderen Zweig featureausgecheckt haben:

git fetch upstream master:master

Dieser Anwendungsfall ist so häufig, dass Sie wahrscheinlich einen Alias ​​dafür in Ihrer Git-Konfigurationsdatei erstellen möchten, wie diesen:

[alias]
    sync = !sh -c 'git checkout --quiet HEAD; git fetch upstream master:master; git checkout --quiet -'

Dieser Alias ​​bewirkt Folgendes:

  1. git checkout HEAD: Dadurch wird Ihre Arbeitskopie in einen Zustand mit getrenntem Kopf versetzt. Dies ist nützlich, wenn Sie ein Update durchführen möchten, masterwährend Sie es auschecken lassen. Ich denke, es war notwendig, damit zu tun, weil sich sonst die Zweigreferenz für masternicht bewegt, aber ich erinnere mich nicht, ob das wirklich direkt von meinem Kopf ist.

  2. git fetch upstream master:master: Dies spult Ihren Einheimischen schnell masteran den gleichen Ort wie vor upstream/master.

  3. git checkout -checkt Ihren zuvor ausgecheckten Zweig aus (das -macht das in diesem Fall).

Die Syntax git fetchfür (Nicht-) Schnellvorlaufzusammenführungen

Wenn Sie möchten, dass der fetchBefehl fehlschlägt, wenn die Aktualisierung nicht schnell vorspult, verwenden Sie einfach eine Referenz des Formulars

git fetch <remote> <remoteBranch>:<localBranch>

Wenn Sie Aktualisierungen ohne schnellen Vorlauf zulassen möchten, fügen Sie +an der Vorderseite der Referenz ein hinzu:

git fetch <remote> +<remoteBranch>:<localBranch>

Beachten Sie, dass Sie Ihr lokales Repo als "Remote" -Parameter übergeben können, indem Sie .:

git fetch . <sourceBranch>:<destinationBranch>

Die Dokumentation

Aus der git fetchDokumentation, die diese Syntax erklärt (Hervorhebung von mir):

<refspec>

Das Format eines <refspec>Parameters ist ein optionales Plus +, gefolgt von der Quellreferenz <src>, gefolgt von einem Doppelpunkt :, gefolgt von der Zielreferenz <dst>.

Die übereinstimmende Remote-Referenz <src>wird abgerufen, und wenn <dst>es sich nicht um eine leere Zeichenfolge handelt, wird die übereinstimmende lokale Referenz mithilfe von weitergeleitet<src> . Wenn das optionale Plus+verwendet wird, wird die lokale Referenz aktualisiert, auch wenn dies nicht zu einer Schnellvorlaufaktualisierung führt.

Siehe auch

  1. Git checkout und zusammenführen, ohne den Arbeitsbaum zu berühren

  2. Zusammenführen ohne das Arbeitsverzeichnis zu ändern


3
git checkout --quiet HEADist git checkout --quiet --detachab Git 1.7.5.
Rafa

6
Ich stellte fest, dass ich tun musste: git fetch . origin/foo:fooum mein lokales foo auf meinen lokalen Ursprung / foo zu aktualisieren
weston

3
Gibt es einen Grund, warum die Teile "git checkout HEAD --quiet" und "git checkout --quiet -" in der langen Antwort enthalten sind, aber nicht in der kurzen Antwort? Ich denke, das liegt daran, dass das Skript möglicherweise ausgeführt wird, wenn Sie den Master ausgecheckt haben, obwohl Sie nur einen Git-Pull ausführen könnten.
Sean

8
Warum ist 'Fetch' der Befehl, hier 'Merge' auszuführen? Es macht einfach keinen Sinn. Wenn 'pull' 'fetch' gefolgt von 'merge' ist, muss es ein logischeres 'merge --ff-only'-Äquivalent geben, das' branch 'von' origin / branch 'lokal aktualisiert, vorausgesetzt, ein' fetch 'hat bereits ausgeführt worden.
Ed Randall

1
Danke für den git checkout -Trick! Genauso einfach wie cd -.
Steed

84

Nein, da ist kein. Ein Auschecken des Zielzweigs ist erforderlich, damit Sie unter anderem Konflikte lösen können (wenn Git diese nicht automatisch zusammenführen kann).

Wenn es sich bei der Zusammenführung jedoch um eine Zusammenführung handelt, müssen Sie den Zielzweig nicht auschecken, da Sie eigentlich nichts zusammenführen müssen. Sie müssen lediglich den Zweig aktualisieren, um auf den zu verweisen neuer Kopf ref. Sie können dies tun mit git branch -f:

git branch -f branch-b branch-a

Wird aktualisiert branch-b, um auf den Kopf von zu zeigen branch-a.

Die -fOption steht für --force, was bedeutet, dass Sie bei der Verwendung vorsichtig sein müssen.

Verwenden Sie es nur, wenn Sie absolut sicher sind, dass die Zusammenführung schnell erfolgt.


46
Seien Sie nur sehr vorsichtig, es sei denn, Sie haben absolut sichergestellt, dass die Zusammenführung ein schneller Vorlauf ist! Ich möchte später nicht feststellen, dass Sie Commits verlegt haben.
Cascabel

@ FuadSaud Nicht genau. git resetFunktioniert nur in der aktuell ausgecheckten Filiale.
Amber

9
Das gleiche Ergebnis (Schnellvorlauf) wird erzielt durch git fetch upstream branch-b:branch-b( aus dieser Antwort entnommen ).
Oliver

6
Um den Kommentar von @ Oliver zu erweitern, können Sie auch Folgendes tun git fetch <remote> B:A: B und A sind völlig unterschiedliche Zweige. B kann jedoch schnell in A zusammengeführt werden. Sie können Ihr lokales Repository auch als "Remote" übergeben, indem Sie .als Remote-Alias ​​Folgendes verwenden: git fetch . B:A.

8
Die Frage des OP macht ziemlich deutlich, dass die Fusion tatsächlich schnell vor sich gehen wird. Unabhängig davon, branch -fkönnte gefährlich sein, wie Sie betonen. Also benutze es nicht! Verwenden Sie fetch origin branchB:branchBdiese Option, die sicher fehlschlägt, wenn die Zusammenführung nicht schnell vorspult.
Bennett McElwee

30

Wie Amber sagte, sind Schnellvorlaufzusammenführungen der einzige Fall, in dem Sie dies möglicherweise tun könnten. Jede andere Zusammenführung muss möglicherweise die gesamte Drei-Wege-Zusammenführung durchlaufen, Patches anwenden, Konflikte lösen - und das bedeutet, dass Dateien vorhanden sein müssen.

Ich habe zufällig ein Skript, das ich genau dafür verwende: Schnellvorlauf-Zusammenführungen durchführen, ohne den Arbeitsbaum zu berühren (es sei denn, Sie führen eine Zusammenstellung mit HEAD durch). Es ist ein bisschen lang, weil es zumindest ein bisschen robust ist - es prüft, ob die Zusammenführung ein schneller Vorlauf ist, und führt sie dann aus, ohne den Zweig auszuchecken, aber die gleichen Ergebnisse zu erzielen, als ob Sie es getan hätten - Sie sehen das diff --statZusammenfassung der Änderungen, und der Eintrag im Reflog ist genau wie eine Schnellvorlauf-Zusammenführung, anstelle der "Zurücksetzen", die Sie erhalten, wenn Sie verwenden branch -f. Wenn Sie es benennen git-merge-ffund in Ihrem bin-Verzeichnis ablegen, können Sie es als git-Befehl aufrufen : git merge-ff.

#!/bin/bash

_usage() {
    echo "Usage: git merge-ff <branch> <committish-to-merge>" 1>&2
    exit 1
}

_merge_ff() {
    branch="$1"
    commit="$2"

    branch_orig_hash="$(git show-ref -s --verify refs/heads/$branch 2> /dev/null)"
    if [ $? -ne 0 ]; then
        echo "Error: unknown branch $branch" 1>&2
        _usage
    fi

    commit_orig_hash="$(git rev-parse --verify $commit 2> /dev/null)"
    if [ $? -ne 0 ]; then
        echo "Error: unknown revision $commit" 1>&2
        _usage
    fi

    if [ "$(git symbolic-ref HEAD)" = "refs/heads/$branch" ]; then
        git merge $quiet --ff-only "$commit"
    else
        if [ "$(git merge-base $branch_orig_hash $commit_orig_hash)" != "$branch_orig_hash" ]; then
            echo "Error: merging $commit into $branch would not be a fast-forward" 1>&2
            exit 1
        fi
        echo "Updating ${branch_orig_hash:0:7}..${commit_orig_hash:0:7}"
        if git update-ref -m "merge $commit: Fast forward" "refs/heads/$branch" "$commit_orig_hash" "$branch_orig_hash"; then
            if [ -z $quiet ]; then
                echo "Fast forward"
                git diff --stat "$branch@{1}" "$branch"
            fi
        else
            echo "Error: fast forward using update-ref failed" 1>&2
        fi
    fi
}

while getopts "q" opt; do
    case $opt in
        q ) quiet="-q";;
        * ) ;;
    esac
done
shift $((OPTIND-1))

case $# in
    2 ) _merge_ff "$1" "$2";;
    * ) _usage
esac

PS Wenn jemand Probleme mit diesem Skript sieht, kommentieren Sie bitte! Es war ein Job zum Schreiben und Vergessen, aber ich würde ihn gerne verbessern.


Sie könnten an stackoverflow.com/a/5148202/717355 zum Vergleich interessiert sein
Philip Oakley

@PhilipOakley Auf den ersten Blick macht das im Kern genau das Gleiche wie bei mir. Aber meine ist nicht auf ein einzelnes Zweigpaar fest codiert, sie hat viel mehr Fehlerbehandlung, simuliert die Ausgabe von Git-Merge und macht das, was Sie meinen, wenn Sie es aufrufen, während Sie sich tatsächlich in der Verzweigung befinden.
Cascabel

Ich habe deine in meinem \ bin-Verzeichnis ;-) Ich hatte es gerade vergessen und sah mich um, sah das Skript und es veranlasste mich zum Rückruf! Meine Kopie hat diesen Link und # or git branch -f localbranch remote/remotebrancherinnert mich an die Quelle und die Optionen. Hat Ihren Kommentar zum anderen Link mit +1 bewertet.
Philip Oakley

3
+1, kann auch standardmäßig "$branch@{u}"als Committish zum Zusammenführen verwendet werden, um den Upstream-Zweig zu erhalten (von kernel.org/pub/software/scm/git/docs/gitrevisions.html )
orip

Vielen Dank! Gibt es eine Chance, dass Sie ein einfaches Beispiel in die Antwort einfließen lassen?
nmr

20

Sie können dies nur tun, wenn die Zusammenführung ein schneller Vorlauf ist. Wenn dies nicht der Fall ist, muss git die Dateien auschecken lassen, damit sie zusammengeführt werden können!

Um dies nur für einen schnellen Vorlauf zu tun :

git fetch <branch that would be pulled for branchB>
git update-ref -m "merge <commit>: Fast forward" refs/heads/<branch> <commit>

Wo <commit>ist das abgerufene Commit, das Sie schnell vorspulen möchten? Dies ist im Grunde wie mitgit branch -f das Verschieben des Zweigs, außer dass er auch im Reflog aufgezeichnet wird, als ob Sie die Zusammenführung tatsächlich durchgeführt hätten.

Bitte, bitte, bitte tun Sie dies nicht für etwas, das kein schneller Vorlauf ist, oder Sie setzen Ihren Zweig einfach auf das andere Commit zurück. (Um zu überprüfen, ob git merge-base <branch> <commit>SHA1 des Zweigs angezeigt wird.)


4
Gibt es eine Möglichkeit, es zum Scheitern zu bringen, wenn es nicht schnell vorspulen kann?
Gman

2
@ gman können Sie verwenden git merge-base --is-ancestor <A> <B>. "B" ist das, was in "A" zusammengeführt werden muss. Beispiel wäre A = Master und B = Entwickeln, um sicherzustellen, dass Entwickeln schnell in Master vorspulbar ist. Hinweis: Es existiert mit 0, wenn es nicht ff-fähig ist, existiert mit 1, wenn es ist.
Eddiemoya

1
Nicht in git-scm dokumentiert, aber auf kernal.org. kernel.org/pub/software/scm/git/docs/git-merge-base.html
eddiemoya

Ich habe einen kurzen Überblick darüber gegeben, wovon ich spreche (habe es nicht wirklich getestet, sollte dich aber meistens dorthin bringen). gist.github.com/eddiemoya/ad4285b2d8a6bdabf432 ---- Als Randnotiz hatte ich das meiste davon zur Hand. Ich habe ein Skript, das nach ff sucht und wenn nicht, können Sie zuerst den gewünschten Zweig neu gründen - dann ff zusammenführen - alles ohne etwas zu überprüfen.
Eddiemoya

12

In Ihrem Fall können Sie verwenden

git fetch origin branchB:branchB

was macht, was Sie wollen (vorausgesetzt, die Zusammenführung ist ein schneller Vorlauf). Wenn der Zweig nicht aktualisiert werden kann, weil eine Zusammenführung ohne schnellen Vorlauf erforderlich ist, schlägt dies mit einer Nachricht sicher fehl.

Diese Form des Abrufs bietet auch einige weitere nützliche Optionen:

git fetch <remote> <sourceBranch>:<destinationBranch>

Beachten Sie, dass <remote> dies ein lokales Repository und <sourceBranch>ein Tracking-Zweig sein kann. So können Sie einen lokalen Zweig aktualisieren, auch wenn er nicht ausgecheckt ist, ohne auf das Netzwerk zuzugreifen .

Derzeit erfolgt mein Upstream-Serverzugriff über ein langsames VPN. Daher verbinde ich mich regelmäßig, git fetchum alle Fernbedienungen zu aktualisieren und dann die Verbindung zu trennen. Wenn sich dann beispielsweise der Remote-Master geändert hat, kann ich dies tun

git fetch . remotes/origin/master:master

um meinen lokalen Master sicher auf den neuesten Stand zu bringen, auch wenn ich gerade eine andere Filiale ausgecheckt habe. Kein Netzwerkzugriff erforderlich.


11

Ein anderer, zugegebenermaßen ziemlich brutaler Weg besteht darin, den Zweig einfach neu zu erstellen:

git fetch remote
git branch -f localbranch remote/remotebranch

Dadurch wird der lokale veraltete Zweig weggeworfen und ein gleichnamiger Zweig neu erstellt. Gehen Sie also vorsichtig vor ...


Ich habe gerade gesehen, dass in der ursprünglichen Antwort bereits branch -f erwähnt wird. Dennoch sehe ich keinen Vorteil darin, die Zusammenführung im Reflog für den ursprünglich beschriebenen Anwendungsfall zu haben.
Kkoehne

7

Sie können das Repo klonen und die Zusammenführung im neuen Repo durchführen. Auf demselben Dateisystem werden die meisten Daten fest verknüpft, anstatt sie zu kopieren. Zum Abschluss ziehen Sie die Ergebnisse in das ursprüngliche Repo.


4

Geben Sie git-forward-merge ein :

Ohne das Ziel auschecken zu müssen, wird git-forward-merge <source> <destination>die Quelle in den Zielzweig zusammengeführt.

https://github.com/schuyler1d/git-forward-merge

Funktioniert nur für automatische Zusammenführungen. Wenn Konflikte auftreten, müssen Sie die reguläre Zusammenführung verwenden.


2
Ich denke, dies ist besser als git fetch <remote> <source>: <destination>, da ein schneller Vorlauf eine Operation ist, bei der das Zusammenführen nicht abgerufen wird und das Schreiben einfacher ist. Schlechte Sache, es ist nicht im Standard-Git.
Binarian

4

In vielen Fällen (z. B. beim Zusammenführen) können Sie nur den Remote-Zweig verwenden, ohne den lokalen Tracking-Zweig aktualisieren zu müssen. Das Hinzufügen einer Nachricht zum Reflog klingt nach Overkill und verhindert, dass es schneller geht. Fügen Sie Ihrer Git-Konfiguration Folgendes hinzu, um die Wiederherstellung zu vereinfachen

[core]
    logallrefupdates=true

Geben Sie dann ein

git reflog show mybranch

um den aktuellen Verlauf Ihrer Branche anzuzeigen


Ich denke der Abschnitt muss [core]nicht sein [user]? (und es ist standardmäßig aktiviert für Repos mit einem Arbeitsbereich (dh nicht nackt).
eckes

3

Ich habe eine Shell-Funktion für einen ähnlichen Anwendungsfall geschrieben, auf den ich täglich bei Projekten stoße. Dies ist im Grunde eine Abkürzung, um lokale Filialen mit einer gemeinsamen Filiale wie "Entwickeln" vor dem Öffnen einer PR usw. auf dem neuesten Stand zu halten.

Veröffentlichen Sie dies, obwohl Sie es nicht verwenden möchten checkout, falls andere diese Einschränkung nicht stören.

glmh("git pull and merge here") wird automatisch checkout branchB, pullspätestens checkout branchA, neu undmerge branchB .

Behebt nicht die Notwendigkeit, eine lokale Kopie von branchA aufzubewahren, kann jedoch leicht geändert werden, indem ein Schritt hinzugefügt wird, bevor branchB ausgecheckt wird. Etwas wie...

git branch ${branchA}-no-branchB ${branchA}

Bei einfachen Zusammenführungen mit schnellem Vorlauf wird zur Eingabeaufforderung für die Festschreibungsnachricht gesprungen.

Bei Zusammenführungen ohne schnellen Vorlauf versetzt dies Ihre Niederlassung in den Konfliktlösungsstatus (Sie müssen wahrscheinlich eingreifen).

Zum Einrichten zu .bashrcoder hinzufügen .zshrcusw.:

glmh() {
    branchB=$1
    [ $# -eq 0 ] && { branchB="develop" }
    branchA="$(git branch | grep '*' | sed 's/* //g')"
    git checkout ${branchB} && git pull
    git checkout ${branchA} && git merge ${branchB} 
}

Verwendungszweck:

# No argument given, will assume "develop"
> glmh

# Pass an argument to pull and merge a specific branch
> glmh your-other-branch

Hinweis: Dies ist nicht robust genug, um Argumente über den Filialnamen hinaus an zu übergebengit merge


2

Ein anderer Weg, dies effektiv zu tun, ist:

git fetch
git branch -d branchB
git branch -t branchB origin/branchB

Da es sich um Kleinbuchstaben handelt -d, wird es nur gelöscht, wenn die Daten noch irgendwo vorhanden sind. Es ähnelt der Antwort von @ kkoehne, außer dass es nicht erzwingt. Aufgrund dessen -twird die Fernbedienung erneut eingerichtet.

Ich hatte ein etwas anderes Bedürfnis als OP, das darin bestand , nach dem Zusammenführen einer Pull-Anfrage einen neuen Feature-Zweig ab develop(oder master) zu erstellen . Dies kann in einem Einzeiler ohne Kraftaufwand erreicht werden, aktualisiert jedoch nicht den lokalen developZweig. Es geht nur darum, eine neue Niederlassung zu überprüfen und sie zu gründen origin/develop:

git checkout -b new-feature origin/develop

1

Nur um den Master zu ziehen, ohne den Master zu überprüfen, den ich benutze

git fetch origin master:master


1

Es ist absolut möglich, Zusammenführungen durchzuführen, auch nicht schnelles Zusammenführen ohne git checkout. Die worktreeAntwort von @grego ist ein guter Hinweis. Um das zu erweitern:

cd local_repo
git worktree add _master_wt master
cd _master_wt
git pull origin master:master
git merge --no-ff -m "merging workbranch" my_work_branch
cd ..
git worktree remove _master_wt

Sie haben jetzt den lokalen Arbeitszweig mit dem lokalen masterZweig zusammengeführt, ohne die Kasse zu wechseln.


1

Wenn Sie den gleichen Baum wie einer der Zweige behalten möchten, die Sie zusammenführen möchten (dh keine echte "Zusammenführung"), können Sie dies folgendermaßen tun.

# Check if you can fast-forward
if git merge-base --is-ancestor a b; then
    git update-ref refs/heads/a refs/heads/b
    exit
fi

# Else, create a "merge" commit
commit="$(git commit-tree -p a -p b -m "merge b into a" "$(git show -s --pretty=format:%T b)")"
# And update the branch to point to that commit
git update-ref refs/heads/a "$commit"

1
git worktree add [-f] [--detach] [--checkout] [--lock] [-b <new-branch>] <path> [<commit-ish>]

Sie können versuchen git worktree, zwei Zweige nebeneinander zu öffnen. Das hört sich so an, als ob es das ist, was Sie wollen, aber ganz anders als einige der anderen Antworten, die ich hier gesehen habe.

Auf diese Weise können Sie zwei separate Zweige im selben Git-Repo verfolgen, sodass Sie nur einmal abrufen müssen, um Aktualisierungen in beiden Arbeitsbäumen zu erhalten (anstatt zweimal git-Klonen und jeweils git ziehen zu müssen).

Worktree erstellt ein neues Arbeitsverzeichnis für Ihren Code, in dem Sie gleichzeitig einen anderen Zweig auschecken lassen können, anstatt die Zweige auszutauschen.

Wenn Sie es entfernen möchten, können Sie mit aufräumen

git worktree remove [-f] <worktree>
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.