Aggregieren Sie Git-Protokolle mit Git Python und analysieren Sie Assoziationen mit Orange

Es ist mir eine Ehre, am Lux Adventskalender 2016 für Heiligabend verantwortlich zu sein. Ich poste verantwortungsbewusst bei Eve (während ich die M-Station beobachte).


Einführung

Der Befehl git log ist ein praktisches Tool, das für die Versionsverwaltung unverzichtbar ist und mit dem Sie wissen, wann, wer was und wie festgeschrieben hat. Wenn Sie dies jedoch für die Qualitätskontrolle und -analyse nutzen möchten, müssen Sie ein wenig überlegen. In Einführung habe ich versucht, zusammenzufassen, wie "Git Log" mit einem Liner formatiert wird, aber es gibt eine Grenze für die Möglichkeiten in einer Zeile. In der eigentlichen Arbeit gibt es nach dem Formen der Protokolle noch andere Dinge zu tun, z. B. jeden Morgen Protokolle zu sammeln, um den Entwicklungsstatus zu überprüfen, Tests zu planen und die Qualität am Ende des Projekts zu bewerten. Diesmal also Ich dachte darüber nach, wie man das Protokoll praktisch benutzt.

Aggregation mit Python

Dieses Mal habe ich zusammengefasst, wie Git-Protokolle mit Git Python aggregiert und analysiert werden. Ich denke, es gibt Möglichkeiten, mit Git in anderen Sprachen umzugehen, aber ich kann gut tabellieren und analysieren, da es eine Sprache ist, mit der Sie den Code einfach umschreiben können, damit Sie die Qualität entsprechend der Situation des Projekts leicht überprüfen können. Ich dachte, Python sei als Skriptsprache einfach zu handhaben. Übrigens hat Python nur Code auf Einweg-Ebene geschrieben, wie zum Beispiel eine kleine Aggregation wie diese. Bitte verzeihen Sie mir, obwohl der Code möglicherweise einen schlechten Teil enthält. Bitte kommentieren Sie, wenn Sie welche haben.

Der hier zusammengefasste Beispielcode wird mit Python 2.7 bestätigt.

GitPython

Es gibt eine praktische Bibliothek namens GitPython für die Arbeit mit Git in Python. Informationen zur Installation finden Sie unter Offizielle Dokumente.

Informationen zum Festschreiben abrufen

Geben Sie dies an, indem Sie das lokale Repository mit "Repo (" / path ") angeben. Die Commit-Informationen für einen bestimmten Zweig erhalten Sie mit Repo.iter_commits. ..

from git import *
import datetime, time

repo = Repo('./')
for item in repo.iter_commits('master', max_count=10):
    dt = datetime.datetime.fromtimestamp(item.authored_date).strftime("%Y-%m-%d %H:%M:%S")
    print("%s %s %s " % (item.hexsha, item.author, dt))

Informationen zum Festschreiben finden Sie unter Objects.Commit API-Referenz.

Im obigen Beispiel werden der Hashwert, der festgeschriebene Benutzer sowie das festgeschriebene Datum und die festgeschriebene Uhrzeit der letzten 10 Git-Protokolle aus dem Hauptzweig des Repositorys im aktuellen Verzeichnis ausgegeben.

Ausgabebeispiel


ddffe26850e8175eb605f975be597afc3fca8a03 Sebastian Thiel 2016-12-22 20:51:02 
3d6e1731b6324eba5abc029b26586f966db9fa4f Sebastian Thiel 2016-12-22 20:48:59 
82ae723c8c283970f75c0f4ce097ad4c9734b233 Sebastian Thiel 2016-12-22 20:44:14 
15b6bbac7bce15f6f7d72618f51877455f3e0ee5 Sebastian Thiel 2016-12-22 20:35:30 
c823d482d03caa8238b48714af4dec6d9e476520 Sebastian Thiel 2016-12-09 00:34:04 
b0c187229cea1eb3f395e7e71f636b97982205ed Sebastian Thiel 2016-12-09 00:07:11 
f21630bcf83c363916d858dd7b6cb1edc75e2d3b Sebastian Thiel 2016-12-09 00:01:35 
06914415434cf002f712a81712024fd90cea2862 Sebastian Thiel 2016-12-08 22:32:58 
2f207e0e15ad243dd24eafce8b60ed2c77d6e725 Sebastian Thiel 2016-12-08 21:20:52 
a8437c014b0a9872168b01790f5423e8e9255840 Vincent Driessen 2016-12-08 21:14:27 

Das obige Ausgabebeispiel ist übrigens das Festschreibungsprotokoll von GitPython vom 23. Dezember 2016.

Festlegen der Commit-Begrenzung

Die in der Einführung eingeführte Commit-Begrenzung von "git log" kann durch das Argument "iter_commits" angegeben werden (im obigen Beispiel wird "max_count = 10" angegeben). Sie können mehrere mit , angeben. Ersetzen Sie außerdem den - Teil durch _, um dies anzugeben. Die Angabe von "no_merge" führte übrigens zu einem Syntaxfehler. Wie in [hier](https://git-scm.com/docs/git-rev-list#git-rev-list --- no-merges) als optionale Spezifikation von "git log" beschrieben Da es dasselbe ist wie "max-parent = 1", konnte ich "max_parents = 1" verwenden.

Geben Sie den Revisionsbereich an

Sie können auch die in der Einführung eingeführte Doppelpunktsyntax angeben. Dies lässt den obigen "Master" -Teil einfach wie "Master ... Experiment" aussehen.

Anwendung zur Protokollierung von Aggregation und Analyse

Betrachten wir nun die Anwendung zum Protokollieren der Aggregation und Analyse. Alle Informationen der festgeschriebenen Datei sind in den Festschreibungsinformationen enthalten, die durch den obigen Code erhalten werden. Sie können eine Liste der festgeschriebenen Dateiinformationen mit stats.files erhalten.

Informationsdetails für jede Festschreibungsdatei

Dies ist ein Beispiel für eine Standardausgabe im CSV-Format zusammen mit Informationen wie Datum und Uhrzeit, zu denen die hinzugefügte und gelöschte Zeile für jede festgeschriebene Datei festgeschrieben wurden.

from git import *
import datetime, time

repo = Repo('./')
print('hexsha,author,authored_date,file_name,deletions,lines,insertions')
for item in repo.iter_commits('master', max_count=10):
    file_list = item.stats.files
    for file_name in file_list:
        dt = datetime.datetime.fromtimestamp(item.authored_date).strftime("%Y-%m-%d %H:%M:%S")
        insertions = file_list.get(file_name).get('insertions')
        deletions = file_list.get(file_name).get('deletions')
        lines = file_list.get(file_name).get('lines')
        print("%s,%s,%s,%s,%s,%s,%s" % (item.hexsha, item.author, dt, file_name, insertions, deletions, lines))

Es ist ziemlich schwierig, diese Informationen mit nur einem Befehl abzurufen und in eine Zeile zu setzen, aber mit GitPython müssen Sie nur die Schleife umgehen und sie abrufen.

Anzahl der Commits pro Datei

Zählen wir nun die Anzahl der während des Zeitraums vorgenommenen Änderungen nach Datei anstatt nach Festschreiben. Im Folgenden wird angegeben, wie oft innerhalb von 6 Monaten für jede Datei ein Commit durchgeführt wurde.

from git import *
import datetime, time

repo = Repo('./')
print('file_name,commit_count')
file_list = {}
for item in repo.iter_commits('master', since='6 months ago'):
    for fileName in item.stats.files:
        if file_name not in file_list:
            fileList[fileName] = []
        author = {}
        author[item.author] = datetime.datetime.fromtimestamp(item.authored_date).strftime("%Y-%m-%d %H:%M:%S")
        file_list[file_name].append(author)

for file_name in file_list:
    print("%s,%d" % (file_name, len(fileList[file_name])))

Darüber hinaus scheint dies angewendet werden zu können, um die Anzahl der geänderten Zeilen für jede Datei innerhalb des Projektzeitraums zu aggregieren und das Festschreibungsintervall (die Anzahl der Tage seit der letzten Änderung) zu berechnen. Sie können nicht nur nach Datei, sondern auch nach Tag, Monat und engagierter Person aggregieren.

Verwendung des Git-Protokolls

Wenn Python frei für die Aggregation verwendet werden kann, können Protokolle für neue Zwecke verwendet werden, z. B. zum Importieren in andere Python-Bibliotheken zur Analyse und zum Verknüpfen mit externen Tools und Diensten.

Assoziationsanalyse

Denken wir also darüber nach, die Analyse von Commit-Informationen zuzuordnen. Was ich tun möchte, ist, wie ich die Information bekomme, dass "die Person, die diese Datei geändert hat, auch diese geändert hat". In Python kann die Assoziationsanalyse mit einer Bibliothek namens Orange durchgeführt werden.

Wie benutzt man Orange?

Gemäß dem offiziellen Dokument Zuordnungsregeln und häufige Artikelgruppen lautet die zu analysierende Liste ".basket" im CSV-Format. Wenn Sie es mit der Erweiterung `speichern, scheint Orange die Zuordnung zu analysieren. Daher geben wir die Dateien, die zusammen in einem Commit festgeschrieben wurden, im CSV-Format aus.

Assoziationsanalyse der im letzten Jahr festgeschriebenen Dateien

Zunächst wird GitPython durch Anwenden der oben genannten Methode verwendet, um die gleichzeitig festgeschriebenen Dateien durch Kommas getrennt auszugeben.

commit-file-list.py


from git import *

repo = Repo('./')
for item in repo.iter_commits('master', since='1 years ago'):
    print(",".join(item.stats.files.keys()))
$ python commit-file-list.py > commit-file-list.basket

Lassen Sie uns die oben erstellte Zuordnung von commit-file-list.basket anhand des Beispielcodes von Orange analysieren.

import Orange
data = Orange.data.Table('commit-file-list.basket')
rules = Orange.associate.AssociationRulesSparseInducer(data, support=0.02, confidence=0.5)
print "%4s %4s %4s" % ("Supp", "Conf", "Rule")
for r in rules:
    if 'git/config.py' in r.name:
        print "%4.1f %4.1f  %s" % (r.support, r.confidence, r)

Ausgabebeispiel


Supp Conf Rule
 0.0  0.6  git/test/test_git.py -> git/cmd.py
 0.0  0.2  git/cmd.py -> git/test/test_git.py
 0.1  0.7  git/test/test_diff.py -> git/diff.py
 0.1  0.7  git/diff.py -> git/test/test_diff.py
 0.0  0.4  git/test/test_diff.py -> git/diff.py doc/source/changes.rst

"Unterstützung" ist in diesem Fall nicht sehr wichtig, da es sich um den Prozentsatz der Regel handelt, der im Ganzen erscheint. Stellen Sie daher den Schwellenwert so niedrig wie möglich ein. "Vertrauen" ist das Verhältnis der gesamten Regel, das unter der Voraussetzung eines Teils der Regel erscheint (das Verhältnis von A und B basierend auf allen Mustern einschließlich A), also ist dieser Wert genau in diesem Fall. Ich möchte die hohen Regeln hervorheben.

Suchen Sie in den Zuordnungsanalyseregeln nach "Ich ändere auch diese Datei", bevor Sie mit dem Master zusammenführen

Geben Sie zunächst die zusammenzuführende Datei im CSV-Format mit einer Zeile für jedes Commit aus und erstellen Sie eine ".basket" -Datei. Da es sich um ein Ziel handelt, das mit dem Master zusammengeführt werden soll, erhält es ein Commit mithilfe der Doppelpunktsyntax und gibt die zugehörige Datei aus.

merge-target-list.py


from git import *

repo = Repo('./')
for item in repo.iter_commits('master..experiment', max_parents=1):
    print(",".join(item.stats.files.keys()))
$ python merge-target-list.py > merge-target-list.basket

Es ist möglicherweise besser, die oben erwähnte Methode zum Extrahieren von Regeln basierend auf dem Git-Protokoll für ein Jahr anzuwenden, diejenige zu finden, deren zusammenzuführender "merge-target-list.basket" mit der linken Seite der Regel übereinstimmt, und auch rechts festzuschreiben. Gibt das Ergebnis aus, dass dies nicht möglich ist (es wird beispielsweise angenommen, dass A, B, C ein Jahr lang als Regeln aus dem Protokoll extrahiert werden und C als Kandidat ausgegeben wird, wenn A, B im Zusammenführungsziel vorhanden sind).

import Orange
data = Orange.data.Table('commit-file-list.basket')
rules = Orange.associate.AssociationRulesSparseInducer(data, support=0.02, confidence=0.5)
for r in rules:
    if 'git/config.py' in r.name:
        print "%4.1f %4.1f  %s" % (r.support, r.confidence, r)

merge_data = Orange.data.Table('merge-target-list.basket')
for d in merge_data:
    for rule in rules:
        #print rule
        if rule.applies_left(d):
            print (u"%Wer hat s begangen%3.1f %%Mit der Rate von%s ist auch verpflichtet" %(rule.left.get_metas(str).keys(), (rule.confidence*100), rule.right.get_metas(str).keys()))

Ausgabebeispiel


['git/test/test_remote.py']Wer hat 55 begangen.0 %Mit der Rate von['git/test/lib/helper.py']Ist auch verpflichtet
['git/test/test_remote.py']Wer hat 55 begangen.0 %Mit der Rate von['git/test/test_base.py']Ist auch verpflichtet
['git/test/test_remote.py']50 Menschen, die sich verpflichtet haben.0 %Mit der Rate von['git/util.py']Ist auch verpflichtet
['git/test/test_base.py']Wer hat 55 begangen.0 %Mit der Rate von['git/test/test_git.py']Ist auch verpflichtet
...(Kürzung)

Die Kandidaten wurden mehr ausgegeben, als ich erwartet hatte, um das Vertrauen auf 0,5 zu setzen. Ich denke, es ist am besten, diesen Bereich entsprechend der Situation und den Merkmalen des Projekts abzustimmen.

abschließend

Da Python viele nützliche Bibliotheken hat, scheint es, dass es nicht nur auf Assoziationsanalysen, sondern auch auf verschiedene Anwendungen angewendet werden kann. Eigentlich habe ich darüber nachgedacht, matplotlib zu verwenden, das Diagramme verarbeiten und ChatBot erstellen kann, aber diesmal liegt es daran, dass die Assoziationsanalyse länger geworden ist als erwartet. Ich möchte meine Hausaufgaben in den Winterferien fortsetzen.

Referenz

Apriori von Python mit Orange ausführen Git-Protokoll mit einem Liner formatieren


Der Spaß Lux Adventskalender 2016 ist morgen endlich der letzte Tag. Bitte freuen Sie sich auf den Abschluss von @ kawanamiyuu. Ich wünsche allen ein schönes Weihnachtsfest.

Recommended Posts

Aggregieren Sie Git-Protokolle mit Git Python und analysieren Sie Assoziationen mit Orange
Aggregieren und analysieren Sie Produktpreise mit der Rakuten Product Search API [Python]
Python-Entwicklungsablauf mit Poetry, Git und Docker
Authentifizierung mit Tweepy-User-Authentifizierung und Anwendungsauthentifizierung (Python)
Clustering und Visualisierung mit Python und CytoScape
Analysieren Sie das Git-Commit-Protokoll in Python
Hinweise zur Verwendung von cChardet und python3-chardet in Python 3.3.1.
Von Python bis zur Verwendung von MeCab (und CaboCha)
Verwenden von Python und MeCab mit Azure Databricks
Ich möchte Protokolle mit Python analysieren
Ich verwende Tox und Python 3.3 mit Travis-CI
Aggregieren Sie die Testergebnisse mithilfe der QualityForward Python-Bibliothek
Schätzung der Kopforientierung mit Python und OpenCV + dlib
Ich habe versucht, Web-Scraping mit Python und Selen
Hinweise zur Installation von Python3 und zur Verwendung von pip unter Windows7
Entwickeln und Bereitstellen von Python-APIs mit Kubernetes und Docker
Ich habe versucht, Objekte mit Python und OpenCV zu erkennen
Holen Sie sich den Git-Zweignamen und den Tag-Namen mit Python
Analysieren Sie Apache-Zugriffsprotokolle mit Pandas und Matplotlib
Erstellen Sie eine Webmap mit Python und GDAL
[Python3] Automatische Texterzeugung mit janome und markovify
Versuchen Sie es mit Tensorflow. ① Erstellen Sie eine Python-Umgebung und führen Sie Tensorflow ein
Versuchen Sie, die ChatWork-API und die Qiita-API in Python zu verwenden