この記事ではPythonのGitPythonを用いてGITのコミットログを解析する方法について解説する。
前提条件として、下記の通り
・Gitがインストールされていること。
・Python2.7系であること。
Python3.3への互換性は現時点でないようだ(ゴールに設定されている)
開発ソース
https://github.com/gitpython-developers/GitPython
ドキュメント
http://pythonhosted.org/GitPython/0.3.2/
インストール
以下を実行する。
# easy_install GitPython
サンプル
指定のリポジトリのコミットの一覧を列挙する
以下のサンプルは指定のリポジトリのコミットのハッシュIDの一覧と、コミット情報を格納するクラス名を出力するスクリプトである。
# -*- coding: utf-8 -*-
from git import *
repo = Repo("/share/testgit/searchTwitter")
for item in repo.iter_commits('master', max_count=100):
print(item.hexsha)
print(item.__class__)
Repoにはローカルのリポジトリへのパスを入力すること。
Subversionのような集中管理システムと違い、GITはローカルに構成管理に必要なすべての情報を保持している。この情報はリポジトリの.gitフォルダの中にすべて格納されている。
このコマンドを実行すると、コミットの情報はgit.objects.commit.Commitに格納されていることがわかる。
Commitの主なプロパティ
名前 | 説明 |
---|---|
author | その作業をもともと行った人 |
authored_date | Author の日付時刻 |
author_tz_offset | authorのタイムゾーンのオフセット |
committer | その作業を適用した人 |
committed_date | committerの日付時刻 |
committer_tz_offset | committerのタイムゾーンのオフセット |
message | コミットメッセージ |
summary | コミットメッセージの1行目 |
stats | Diffから作られる統計情報。stats.filesに更新があったファイルの情報が格納されている。 |
parents | 親になるgit.objects.commit.Commitの一覧。親がないのが初回コミットになる。これを利用すればコミットの順番を作成できる。 |
tree | blobを格納するツリー構造のデータ。Treeクラスで定義されている |
Treeの主な構造
ツリー構造を表現するデータ。Treeクラスで定義されている。
tree.blobsにはツリーに所属するすべてのBlobが格納されているので、以下のように再帰的に呼び出せば、コミットに紐づくBlobをすべて抜き出せる。
def show_tree(tree, indent):
"""
Treeの情報を出力
"""
print ('%shexsha :%s' % (indent, tree.hexsha))
print ('%spath :%s' % (indent, tree.path))
print ('%sabspath :%s' % (indent, tree.abspath))
print ('%smode :%s' % (indent, tree.mode))
for t in tree.trees:
show_tree(t, indent + ' ')
print ('%s[blobs]' % indent)
for b in tree.blobs:
show_blob(b, indent + ' ')
Blobは実際のファイルの内容を表すもので、自身のサイズと内容から計算される SHA-1 ハッシュによって名付けられる。
また、コミットのtreeに紐づくBlobは変更があったものだけでなく、すべてのファイルが紐づいている。
変更がないものは前回のコミットと同じハッシュ値、変更があったものは違うハッシュ値で格納されている。。
Gitは「ディレクトリのスナップショットを保全している」ことがこれからわかると思う。
最終的なサンプル
リポジトリのコミットを抜き出し、各コミットのBlobまで抜き出すサンプルは以下の通りになる。
# -*- coding: utf-8 -*-
from git import *
import time
def show_blob(b, indent):
"""
Blobの情報を出力
"""
print ('%s---------------' %(indent))
print ('%shexsha:%s' % (indent,b.hexsha))
print ('%smime_type:%s' % (indent,b.mime_type))
print ('%spath:%s' %(indent,b.path))
print ('%sabspath:%s' %(indent,b.abspath))
def show_tree(tree, indent):
"""
Treeの情報を出力
"""
print ('%shexsha :%s' % (indent, tree.hexsha))
print ('%spath :%s' % (indent, tree.path))
print ('%sabspath :%s' % (indent, tree.abspath))
print ('%smode :%s' % (indent, tree.mode))
for t in tree.trees:
show_tree(t, indent + ' ')
print ('%s[blobs]' % indent)
for b in tree.blobs:
show_blob(b, indent + ' ')
def show_commitlog(item):
"""
Commitの情報を出力
"""
print ("hexsha %s" %item.hexsha)
print (item.author)
print (item.author_tz_offset)
print (time.strftime("%a, %d %b %Y %H:%M", time.gmtime(item.committed_date)))
print (item.committer)
print (item.committer_tz_offset)
print (item.encoding)
print (item.message)
print (item.name_rev)
print (item.summary)
print ('[stats]')
print (item.stats.total)
print (item.stats.files)
print ('[parents]')
for i in item.parents:
print(' %s' % i.hexsha)
print '[Tree]'
show_tree(item.tree, ' ')
repo = Repo("/share/testgit/searchTwitter")
for item in repo.iter_commits('master', max_count=100):
print ('================================')
show_commitlog(item)
まとめ
ローカルにCloneしたGitのリポジトリに対してはGitPythonを用いることで、コミットログを簡単に解析できることを説明した。
これを利用することにより、リポジトリに対するコミットの統計情報を作成し、プロジェクト管理の助けに利用することが期待できる。
参考
GitPython Documentation
https://pythonhosted.org/GitPython/0.3.2/index.html
見えないチカラ
http://keijinsonyaban.blogspot.jp/2011/05/git.html
Git Book
http://git-scm.com/book/ja/