Git vs. Mercurial - Lieblingsfeatures: Revsets (Teil 4)

Posted by Start Bootstrap on November 10, 2012

In den letzten Folgen ging um das, was beide Tools können. Heute werfe ich mal einen Blick auf ein Feature, das nur in Mercurial vorhanden ist.

Mercurial Revsets

Wenn viele Entwickler an einer Software arbeiten, kann die Commit-Historie unübersichtlich werden. Sowohl Git als auch Mercurial bieten zahlreiche Kommandos, um die Historie zu analysieren. Aber nur Mercurial hat eine eigene Query Language dafür:

Ein Beispiel: Die aktuelle Software hat die Version 1_1_3. Ein neues Feature soll ausgeliefert werden. Die QA entdeckt einen Fehler, den es in 1_1_3 noch nicht gegeben hat. Das Beispiel zeigt die Branches releases und myfeature:

> hg log --graph
@  myfeature: Create file file4
|
o    myfeature: merge releases into feature
|\
| o  myfeature: Edit file user-roles.xml
| |
o |  releases: Added tag release_1_1_3 for changeset c9cd4f3a5334
| |
o |  releases: Edit line 0 in file user-roles.xml
| |
o |  releases: merge myfeature into releases
|\|
| o  myfeature: Create file file3
|/
o  releases: Create file file2
|
o  releases: Create line 0,1,2 in file user-roles.xml
|
o  releases: Create file hgrc

Zeige alle Änderungen auf dem Branch myfeature.

> hg log -r "branch(myfeature)"
myfeature: Create file file3
myfeature: Edit file user-roles.xml
myfeature: merge releases into feature
myfeature: Create file file4

Oha, ganz schön viele! Aber halt: Teile von myfeature wurden schon in 1_1_3 ausgeliefert. Die können wir aussortieren.

> hg log -r "branch(myfeature) 
             and not ancestors(release_1_1_3)"
myfeature: Edit file user-roles.xml
myfeature: merge releases into feature
myfeature: Create file file4

QA sagt, der Fehler könnte was mit Berechtigungen zu tun haben. Wir untersuchen, ob auf dem Branch seit release_1_1_3 die Datei user-roles.xml verändert wurde.

> hg log -r "branch(myfeature) 
             and not ancestors(release_1_1_3)
             and file('user-roles.xml')"
myfeature: Edit file user-roles.xml
myfeature: merge releases into feature

Falls wir jetzt Commits gefunden haben, lohnt es sich vielleicht noch zu prüfen, ob die Änderung wirklich auf myfeature stattgefunden haben, und nicht von woanders “hereingemerged” wurde.

> hg log -r "branch(myfeature)
             and not ancestors(release_1_1_3)
             and modifies('user-roles.xml')
             and not merge()"
myfeature: Edit file user-roles.xml

Mehr? Herausfinden, welche Bugfixes im release_1_1_3 noch nicht enthalen sind:

> hg log -r "branch('re:^FIX_.*')
             - ancestors('release_1_1_3')"

Stimmt noch nicht ganz. Bugfixes könne ja auch per Cherry-Pick (graft, transplant oder rebase) übertragen worden sein:

> hg log -r "branch('re:^FIX_.*')
             - (ancestors('release_1_1_3')
                or origin(ancestors('release_1_1_3')))"

Noch ein Beispiel: Wissen, welche Sachen ich noch nicht abgeschlossen habe.

hg log -r "head()
           and author("stachi")
           and not closed()"

Das Ganze funktioniert übrigens nicht nur für hg log sondern für jedes Kommando, das eine Option -r bzw. --rev Option bietet.

Großartiges Feature! Wer mehr darüber wissen möchte:

hg help revsets

Und Git?

Natürlich bietet auch Git zahlreiche Möglichkeiten, Dinge über das Repository herauszufinden. Aber sie sind verteilt auf viele Optionen, verschiedene Befehle und ein paar syntaktische Sonderlocken. Sie lassen sich nicht nicht so frei kombinieren und sind oft schlechter lesbar als die SQL-artige Syntax der Query Language von Mercurial.

Fazit

Die Mercurial-Revsets Query Language ist ein ungemein nützliches Tool, um die Historie zu analysieren. Ich wünschte, dass Git so etwas auch hätte.

*(Artikelserie “Git vs. Mercurial”: Die Kontrahenten / Branches / Kommandozeile / Geschichtsfälschung / Revsets / Interactive Rebasing / Git Repository

)*