Einrichten und Verwenden von Meld als Git-Difftool und Mergetool


255

Obwohl ein Großteil der Informationen in dieser Frage und Antwort auf StackOverflow verfügbar ist, sind sie auf viele Seiten und andere Antworten verteilt, die entweder falsch oder irreführend sind. Ich brauchte eine Weile, um alles zusammenzusetzen, was ich wissen wollte.

Es gibt viele verschiedene Programme, die als Git-Difftool und Mergetool verwendet werden können, und es gibt sicherlich keinen Konsens darüber, welches das beste ist (Meinungen, Anforderungen und Betriebssysteme unterscheiden sich deutlich).

Meld ist eine beliebte kostenlose, Open-Source- und plattformübergreifende Option (UNIX / Linux, OSX, Windows), wie in der StackOverflow- Frage gezeigt: Was ist das beste visuelle Zusammenführungstool für Git? , in der die Antwort, die Meld vorschlägt, mehr als dreimal so viele Stimmen hat wie jedes andere Tool.

Die folgenden 2 Fragen werden in meiner Antwort unten beantwortet:

  • Wie richte ich Meld als Git-Difftool ein und verwende es?
  • Wie richte ich Meld als Git-Mergetool ein und verwende es?

Hinweis: Es ist nicht erforderlich, dasselbe Programm wie Ihr Difftool und Ihr Mergetool zu verwenden. Für beide können unterschiedliche Programme festgelegt werden.


1
In Verbindung stehender Beitrag - So konfigurieren Sie ein Diff-Tool in Git im Allgemeinen .
RBT

Antworten:


423

Wie richte ich Meld als Git-Difftool ein und verwende es?

git difftool zeigt das Diff mit einem GUI-Diff-Programm (dh Meld) an, anstatt die Diff-Ausgabe in Ihrem Terminal anzuzeigen.

Obwohl Sie das GUI-Programm über die Befehlszeile festlegen können, -t <tool> / --tool=<tool>ist es sinnvoller, es in Ihrer .gitconfigDatei zu konfigurieren . [Hinweis: Siehe die Abschnitte zum Anhalten von Anführungszeichen und Windows-Pfaden unten.]

# Add the following to your .gitconfig file.
[diff]
    tool = meld
[difftool]
    prompt = false
[difftool "meld"]
    cmd = meld "$LOCAL" "$REMOTE"

[Hinweis: Diese Einstellungen ändern nicht das Verhalten, git diffdas weiterhin wie gewohnt funktioniert.]

Sie verwenden git difftoolgenau so, wie Sie verwenden git diff. z.B

git difftool <COMMIT_HASH> file_name
git difftool <BRANCH_NAME> file_name
git difftool <COMMIT_HASH_1> <COMMIT_HASH_2> file_name

Bei ordnungsgemäßer Konfiguration wird ein Meld-Fenster geöffnet, in dem das Diff über eine GUI-Oberfläche angezeigt wird.

Die Reihenfolge der Meld-GUI-Fensterfenster kann durch die Reihenfolge von $LOCALund $REMOTEin gesteuert werden cmd, dh welche Datei im linken Bereich und welche im rechten Bereich angezeigt wird. Wenn Sie sie umgekehrt haben möchten, tauschen Sie sie einfach so aus:

    cmd = meld "$REMOTE" "$LOCAL"

Schließlich verhindert die prompt = falseZeile einfach, dass git Sie dazu auffordert, ob Sie Meld starten möchten oder nicht. Standardmäßig gibt git eine Eingabeaufforderung aus.


Wie richte ich Meld als Git-Mergetool ein und verwende es?

Mit git mergetool können Sie ein GUI-Zusammenführungsprogramm (z. B. Meld) verwenden, um die Zusammenführungskonflikte zu lösen, die während einer Zusammenführung aufgetreten sind.

Wie bei difftool können Sie das GUI-Programm in der Befehlszeile über festlegen. Nach -t <tool> / --tool=<tool>wie vor ist es jedoch sinnvoller, es in Ihrer .gitconfigDatei zu konfigurieren . [Hinweis: Siehe die Abschnitte zum Anhalten von Anführungszeichen und Windows-Pfaden unten.]

# Add the following to your .gitconfig file.
[merge]
    tool = meld
[mergetool "meld"]
    # Choose one of these 2 lines (not both!) explained below.
    cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"
    cmd = meld "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"

Sie verwenden NICHT git mergetool, um eine tatsächliche Zusammenführung durchzuführen. Vor der Verwendung führen git mergetoolSie eine Zusammenführung mit git auf die übliche Weise durch. z.B

git checkout master
git merge branch_name

Wenn es einen Zusammenführungskonflikt gibt, zeigt git ungefähr Folgendes an:

$ git merge branch_name
Auto-merging file_name
CONFLICT (content): Merge conflict in file_name
Automatic merge failed; fix conflicts and then commit the result.

Zu diesem Zeitpunkt file_nameenthält die teilweise zusammengeführte Datei die Informationen zum Zusammenführungskonflikt (dies ist die Datei mit allen >>>>>>>und <<<<<<<Einträgen darin).

Mergetool kann jetzt verwendet werden, um die Zusammenführungskonflikte zu lösen. Sie beginnen es sehr einfach mit:

git mergetool

Bei ordnungsgemäßer Konfiguration wird ein Meldungsfenster mit 3 Dateien geöffnet. Jede Datei wird in einem separaten Bereich der GUI-Oberfläche enthalten sein.

Im .gitconfigobigen Beispieleintrag werden 2 Zeilen als [mergetool "meld"] cmdZeile vorgeschlagen. Tatsächlich gibt es für fortgeschrittene Benutzer alle Arten von Möglichkeiten, die cmdLeitung zu konfigurieren , aber das würde den Rahmen dieser Antwort sprengen.

Diese Antwort enthält zwei alternative cmdZeilen, die für die meisten Benutzer geeignet sind und einen guten Ausgangspunkt für fortgeschrittene Benutzer darstellen, die das Tool auf die nächste Komplexitätsstufe bringen möchten.

Erstens bedeuten die Parameter Folgendes:

  • $LOCAL ist die Datei im aktuellen Zweig (zB Master).
  • $REMOTE ist die Datei in der Verzweigung, die zusammengeführt wird (z. B. Verzweigungsname).
  • $MERGED ist die teilweise zusammengeführte Datei mit den darin enthaltenen Informationen zum Zusammenführungskonflikt.
  • $BASEist der Vorfahr des gemeinsam genutzten Commits von $LOCALund $REMOTE, dh die Datei ist so, wie sie war, als der Zweig, der sie enthielt, $REMOTEursprünglich erstellt wurde.

Ich schlage vor, Sie verwenden entweder:

[mergetool "meld"]
    cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"

oder:

[mergetool "meld"]
    cmd = meld "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED"
    # See 'Note On Output File' which explains --output "$MERGED".

Die Wahl ist, ob $MERGEDoder $BASEzwischen $LOCALund verwendet werden soll $REMOTE.

In beiden Fällen zeigt Meld 3 Fenster mit $LOCALund $REMOTEim linken und rechten Fenster sowie entweder $MERGEDoder $BASEim mittleren Bereich an.

In BEIDEN Fällen ist der mittlere Bereich die Datei, die Sie bearbeiten sollten, um die Zusammenführungskonflikte zu lösen. Der Unterschied besteht darin, in welcher Startposition Sie die Bearbeitung bevorzugen. $MERGEDfür die Datei, die die teilweise zusammengeführte Datei mit den Zusammenführungskonfliktinformationen enthält, oder $BASEfür den gemeinsam genutzten Commit-Vorfahren von $LOCALund $REMOTE. [Da beide cmdZeilen nützlich sein können, behalte ich beide in meiner .gitconfigDatei. Die meiste Zeit benutze ich die $MERGEDZeile und die $BASEZeile ist auskommentiert, aber das Auskommentieren kann vertauscht werden, wenn ich $BASEstattdessen die Zeile verwenden möchte .]

Hinweis zur Ausgabedatei: Machen Sie sich keine Sorgen, dass diese verwendet --output "$MERGED"wird, cmdunabhängig davon, ob sie früher in der Zeile verwendet wurde $MERGEDoder $BASEwurde cmd. Die --outputOption teilt Meld einfach mit, in welchem ​​Dateinamen git die Konfliktlösungsdatei gespeichert werden soll. Meld speichert Ihre Konfliktbearbeitungen in dieser Datei, unabhängig davon, ob Sie sie verwenden $MERGEDoder $BASEals Startpunkt für die Bearbeitung verwenden.

Speichern Sie nach dem Bearbeiten des mittleren Bereichs zur Lösung der Zusammenführungskonflikte einfach die Datei und schließen Sie das Meldungsfenster. Git führt das Update automatisch durch und die Datei im aktuellen Zweig (z. B. Master) enthält jetzt alles, was Sie im mittleren Bereich gefunden haben.

git hat eine Sicherungskopie der teilweise zusammengeführten Datei mit den darin enthaltenen Informationen zum Zusammenführungskonflikt erstellt, indem es .origan den ursprünglichen Dateinamen angehängt wurde. zB file_name.orig. Nachdem Sie überprüft haben, ob Sie mit dem Zusammenführen zufrieden sind, und alle Tests ausgeführt haben, die Sie möglicherweise durchführen möchten, kann die .origDatei gelöscht werden.

An diesem Punkt können Sie jetzt ein Commit ausführen, um die Änderungen festzuschreiben.

Wenn Sie während der Bearbeitung der Zusammenführungskonflikte in Meld die Verwendung von Meld aufgeben möchten, beenden Sie Meld, ohne die Zusammenführungsauflösungsdatei im mittleren Bereich zu speichern. git antwortet mit der Nachricht file_name seems unchangedund fragt dann Was the merge successful? [y/n], wenn Sie antworten, nwird die Lösung des Zusammenführungskonflikts abgebrochen und die Datei bleibt unverändert. Beachten Sie, dass Sie die Warnung und Aufforderung von git nicht erhalten, wenn Sie die Datei zu irgendeinem Zeitpunkt in Meld gespeichert haben. [Natürlich können Sie die Datei einfach löschen und durch die Sicherungsdatei ersetzen .orig, die git für Sie erstellt hat.]

Wenn Sie mehr als eine Datei mit Zusammenführungskonflikten haben, öffnet git nacheinander jeweils ein neues Meld-Fenster, bis alle fertig sind. Sie werden nicht alle gleichzeitig geöffnet, aber wenn Sie die Bearbeitung der Konflikte in einem abgeschlossen und Meld geschlossen haben, öffnet git den nächsten und so weiter, bis alle Zusammenführungskonflikte gelöst sind.

Es ist sinnvoll, ein Dummy-Projekt zu erstellen, um die Verwendung zu testen, git mergetoolbevor Sie es in einem Live- Projekt verwenden. Stellen Sie sicher, dass Sie in Ihrem Test einen Dateinamen verwenden, der ein Leerzeichen enthält, falls Ihr Betriebssystem erfordert, dass Sie die Anführungszeichen in der cmdZeile umgehen, siehe unten.


Anführungszeichen entkommen

Bei einigen Betriebssystemen müssen die Anführungszeichen möglicherweise maskiert sein cmd. Weniger erfahrene Benutzer sollten sich daran erinnern, dass Konfigurationsbefehlszeilen mit Dateinamen getestet werden sollten, die Leerzeichen enthalten. Wenn die cmdZeilen nicht mit den Dateinamen funktionieren, die Leerzeichen enthalten, versuchen Sie, die Anführungszeichen zu umgehen. z.B

cmd = meld \"$LOCAL\" \"$REMOTE\"

In einigen Fällen kann ein komplexeres Anführungszeichen erforderlich sein. Der erste der folgenden Windows-Pfadlinks enthält ein Beispiel für das dreifache Escapezeichen für jedes Zitat. Es ist langweilig, aber manchmal notwendig. z.B

cmd = meld \\\"$LOCAL\\\" \\\"$REMOTE\\\"

Windows-Pfade

Windows-Benutzer benötigen wahrscheinlich eine zusätzliche Konfiguration, die den Meldungszeilen hinzugefügt cmdwird. Möglicherweise müssen sie den vollständigen Pfad zu verwenden meldc, der unter Windows über die Befehlszeile aufgerufen werden soll, oder sie benötigen oder möchten möglicherweise einen Wrapper. Sie sollten die lesen Stackoverflow zu verlinkenden Seiten unter denen etwa die richtige Meld Einstellung cmdLinie für Windows. Da ich ein Linux-Benutzer bin, kann ich die verschiedenen Windows- cmdZeilen nicht testen und habe keine weiteren Informationen zu diesem Thema, als zu empfehlen, meine Beispiele mit einem vollständigen Pfad zu Meld oder meldcoder dem Hinzufügen des Meld-Programmordners zu Ihrem zu verwenden path.

Ignorieren von nachgestellten Leerzeichen mit Meld

Meld verfügt über eine Reihe von Einstellungen, die in der GUI konfiguriert werden können.

Auf der Text FiltersRegisterkarte "Einstellungen" gibt es mehrere nützliche Filter, mit denen Sie beispielsweise Kommentare ignorieren können, wenn Sie einen Diff ausführen. Es gibt zwar Filter zum Ignorieren All whitespaceund Leading whitespacees gibt keinen Ignorierfilter Trailing whitespace(dies wurde als Ergänzung in der Meld-Mailingliste vorgeschlagen, ist aber in meiner Version nicht verfügbar).

Das Ignorieren von nachgestellten Leerzeichen ist häufig sehr nützlich, insbesondere bei der Zusammenarbeit, und kann einfach manuell mit einem einfachen regulären Ausdruck auf der Text FiltersRegisterkarte Meld-Einstellungen hinzugefügt werden .

# Use either of these regexes depending on how comprehensive you want it to be.
[ \t]*$
[ \t\r\f\v]*$

Ich hoffe das hilft allen.


2
Danke, das ist so viel einfacher zu bedienen [mergetool "meld"] cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"in ~/.gitconfig, dann lösen Sie einfach die rot markierten Konflikte in der Mitte Pfanne und sparen! Dies sollte die Standardeinstellung sein.
KrisWebDev

1
$LOCAL $MERGED $REMOTEist die Einstellung, die ich die meiste Zeit verwende, wenn es nur wenige Konflikte gibt, um sie zu lösen. Sie ist ausgezeichnet und auch meine Standardeinstellung. $LOCAL $BASE $REMOTEkommt wirklich zur Geltung, wenn es viel zu tun gibt und Sie genau wissen, welche Codeabschnitte aus welcher Datei stammen. Der Shared Commit-Vorfahr kann ein guter, übersichtlicher Ausgangspunkt sein. Manchmal stört die Hervorhebung von Konflikten tatsächlich und eine sauberere Basis ist ein Segen.
Mattst

4
Hinweis: Wenn Sie unter OSX arbeiten und meld über Homebrew installiert haben, erfordert der Ausgabeparameter =cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output="$MERGED"
Folgendes

2
Befolgen Sie für Mac-Benutzer, die die .dmg-Datei installiert haben und feststellen, dass sich 'meld' nicht in ihrem Pfad befindet, die alternativen Anweisungen hier: yousseb.github.io/meld
KC Baltz

3
Das ist so viel besser als die Erklärung bei Git Configuration - git mergetool . Vielen Dank, insbesondere für die Erklärung des Unterschieds zwischen $ MERGED und $ BASE. Hat mich davor bewahrt, verrückt zu werden!
ChrisG

81

Während die andere Antwort richtig ist, ist hier der schnellste Weg, um Meld als Ihr visuelles Diff-Tool zu konfigurieren. Kopieren Sie einfach Folgendes:

git config --global diff.tool meld
git config --global difftool.prompt false

Führen Sie es nun git difftoolin einem Verzeichnis aus und Meld wird für jede andere Datei gestartet.

Randnotiz: Meld vergleicht CSV-Dateien überraschend langsam , und kein Linux-Diff-Tool, das ich gefunden habe, ist schneller als dieses Windows-Tool namens Compare It! (zuletzt aktualisiert im Jahr 2010).


13
Sie möchten git config --global difftool.meld.cmd 'meld "$LOCAL" "$REMOTE"'dort wahrscheinlich auch eine Zeile. Dies ist die "Standardeinstellung", aber sobald Sie a konfigurieren mergetool, difftoolwird die Mergetool-Konfiguration als Standard verwendet, wenn die Diff-Konfiguration nicht gefunden wird. Da die Zusammenführung im Allgemeinen so konfiguriert ist, dass drei Dateien für eine 3-Wege-Zusammenführung übergeben werden, bedeutet dies, dass Ihr meld Diff- Fenster plötzlich drei Bereiche hat, was keinen Sinn ergibt.
BeeOnRope

Warum nicht die Konfiguration überprüfen, nachdem sie mit $ git config -l
agfe2 am

56

Für Windows . Führen Sie diese Befehle in Git Bash aus:

git config --global diff.tool meld
git config --global difftool.meld.path "C:\Program Files (x86)\Meld\Meld.exe"
git config --global difftool.prompt false

git config --global merge.tool meld
git config --global mergetool.meld.path "C:\Program Files (x86)\Meld\Meld.exe"
git config --global mergetool.prompt false

(Aktualisieren Sie den Dateipfad für Meld.exe, falls Ihr Pfad anders ist.)

Für Linux . Führen Sie diese Befehle in Git Bash aus:

git config --global diff.tool meld
git config --global difftool.meld.path "/usr/bin/meld"
git config --global difftool.prompt false

git config --global merge.tool meld
git config --global mergetool.meld.path "/usr/bin/meld"
git config --global mergetool.prompt false

Sie können den Pfad von Meld mit diesem Befehl überprüfen:

which meld

1
Ich habe eine Fehlermeldung erhalten, als ich git difftool "Das Diff-Tool meld ist nicht als 'D: \ software \ melddiff \ Meld.exe' verfügbar" ausgeführt habe
Allen Vork

@AllenVork: Haben Sie bestätigt, dass sich Meld.exe in dem von Ihnen angegebenen Ordner befindet? Können Sie es außerhalb von Git erfolgreich ausführen? Was gibt Git zurück, wenn Sie laufen git config --global --get-regex diff*?
MarredCheese

Ich habe es gelöst. Ich ändere es in "D: /software/melddiff/Meld.exe" und es funktioniert. Das Format von .gitconfig ist Ubuntu, nicht Windows.
Allen Vork

Sollte es nicht gewesen sein : git config --global difftool.meld.path "C:\Program Files (x86)\Meld\Meld.exe"?
Jonathan Rosenne

@ AllenVork, benutzt du Git für Cygwin?
Adrian

25

Ich bevorzuge es, meld als separaten Befehl einzurichten, wie folgt:

git config --global alias.meld '!git difftool -t meld --dir-diff'

Dies ähnelt dem Skript git-meld.pl hier: https://github.com/wmanley/git-meld

Sie können dann einfach laufen

git meld

Ich hatte gerade eine Zusammenarbeit mit Cygwin und jetzt ist es kaputt. Dies hat es behoben. Vielen Dank! (Obwohl ich den --dir-diffTeil als persönliche Präferenz entfernt habe.)
PfunnyGuy

3

Für Windows 10 musste ich dies in meine .gitconfig einfügen:

[merge]
  tool = meld
[mergetool "meld"]
  cmd = 'C:/Program Files (x86)/Meld/Meld.exe' $LOCAL $BASE $REMOTE --output=$MERGED
[mergetool]
  prompt = false

Alles , was Sie wissen müssen , ist in dieser super geschrieben Antwort weiter oben durch mattst.

PS: Aus irgendeinem Grund funktionierte dies nur mit Meld 3.18.x, Meld 3.20.x gibt mir einen Fehler.


1

Dies ist eine Antwort, die sich hauptsächlich an Entwickler richtet, die Windows verwenden, da sich die Pfadsyntax des Diff-Tools von anderen Plattformen unterscheidet.

Ich verwende Kdiff3 als Git-Mergetool, aber um das Git-Difftool als Meld einzurichten, habe ich zuerst die neueste Version von Meld von Meldmerge.org installiert und dann Folgendes zu meiner globalen .gitconfig hinzugefügt:

git config --global -e

Hinweis: Wenn Sie Sublime Text 3 anstelle des Standard-Vim als Hauptditor verwenden möchten, können Sie dies der .gitconfig-Datei hinzufügen:

[core]
editor = 'c:/Program Files/Sublime Text 3/sublime_text.exe'

Dann fügen Sie Inn Meld als Difftool hinzu

[diff]
tool = meld
guitool = meld 

[difftool "meld"]
cmd = \"C:/Program Files (x86)/Meld/Meld.exe\" \"$LOCAL\" \"$REMOTE\" --label \"DIFF 
(ORIGINAL MY)\"
prompt = false
path = C:\\Program Files (x86)\\Meld\\Meld.exe

Beachten Sie den führenden Schrägstrich im obigen cmd. Unter Windows ist dies erforderlich.

Es ist auch möglich, einen Alias ​​einzurichten, um das aktuelle Git-Diff mit der Option --dir-diff anzuzeigen . Dadurch werden die geänderten Dateien in Meld aufgelistet. Dies ist praktisch, wenn Sie mehrere Dateien geändert haben (ein sehr häufiges Szenario).

Der Alias ​​sieht in der .gitconfig-Datei unter dem Abschnitt [alias] folgendermaßen aus :

showchanges = difftool --dir-diff

Um die Änderungen anzuzeigen, die ich am Code vorgenommen habe, gebe ich einfach den folgenden Befehl ein:

git showchanges

Das folgende Bild zeigt, wie diese Option --dir-diff eine Liste geänderter Dateien anzeigen kann (Beispiel): Meldung mit einer Liste der Dateien mit Änderungen zwischen $ LOCAL und $ REMOTE

Dann ist es möglich, auf jede Datei zu klicken und die Änderungen in Meld anzuzeigen.


0

Es kann kompliziert sein, einen Unterschied in Ihrem Kopf aus den verschiedenen Abschnitten in $ MERGED zu berechnen und anzuwenden. In meinem Setup hilft meld, indem es Ihnen diese Unterschiede visuell zeigt, indem Sie Folgendes verwenden:

[merge]
    tool = mymeld
    conflictstyle = diff3

[mergetool "mymeld"]
    cmd = meld --diff $BASE $REMOTE --diff $REMOTE $LOCAL --diff $LOCAL $MERGED

Es sieht seltsam aus, bietet aber einen sehr praktischen Arbeitsablauf mit drei Registerkarten:

  1. In Tab 1 sehen Sie (von links nach rechts) die Änderung, die Sie in Tab 2 vornehmen sollten, um den Zusammenführungskonflikt zu lösen.

  2. Auf der rechten Seite von Registerkarte 2 übernehmen Sie die "Änderung, die Sie vornehmen sollten" und kopieren den gesamten Dateiinhalt in die Zwischenablage (mit Strg-a und Strg-c).

  3. In Registerkarte 3 ersetzen Sie die rechte Seite durch den Inhalt der Zwischenablage. Wenn alles korrekt ist, sehen Sie jetzt von links nach rechts dieselbe Änderung wie in Registerkarte 1 (jedoch mit unterschiedlichen Kontexten). Speichern Sie die auf dieser Registerkarte vorgenommenen Änderungen.

Anmerkungen:

  • Bearbeiten Sie nichts in Tab. 1
  • Speichern Sie nichts in Tab. 2, da dies zu störenden Popups in Tab. 3 führt

Ist dies besser als die 3-Wege-Zusammenführung (lokal / Basis / Remote) in einer einzelnen Registerkarte?
André Werlang

@ AndréWerlang Der Vorteil der 3-Wege-Zusammenführung in einer einzelnen Registerkarte besteht darin, dass Sie sich nur mit den widersprüchlichen Änderungen befassen müssen (die anderen Änderungen werden automatisch zusammengeführt). Aber ich bevorzuge "meinen" Ansatz in Fällen, in denen es schwierig ist, bei der 3-Wege-Zusammenführung zu verstehen, was sich geändert hat und wie man auf eine Weise zusammenführt, bei der alle Änderungen erhalten bleiben. Wenn mich die 3-Wege-Zusammenführung irgendwann nicht mehr verwirrt, kann ich wieder darauf zurückgreifen.
Mnieber

Wie der Benutzer mattst betonte, könnten Sie $BASEstattdessen verwenden $MERGED, um den Zusammenführungsvorgang zu starten
André Werlang
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.