工程地址: https://pypi.python.org/pypi/GitPython/
需要安裝先安裝: gitdb https://pypi.python.org/pypi/gitdb
GitPython使用模塊對象訪問git配置庫。
倉庫操作
初始倉庫對象
from git import * repo = Repo(repo_path) assert repo.bare == False 創建裸庫 repo = Repo.init(repo_path,bare=True) assert repo.bare == True 倉庫數據高層接口可以新增/刪除 heads/tags/remotes和訪問倉庫的配置信息 repo.config_reader() #獲得倉庫中只讀的配置信息 repo.config_writer() #更新倉庫中的配置信息 獲取活動分支、未被管理的文件和判斷是否有變更 repo.is_dirty() #返回布爾值 repo.untracked_files #返回未被管理的文件列表 克隆和初始化一個新的倉庫 cloned_repo = repo.clone(to/this/path) new_repo = repo.init(path/for/new/repo)
數據庫對象
repo對象的性能優於數據庫對象,repo對象一般用於獲取大數據和新增對象。
GitDB
在操作大文件時,GitDB可以使用更少的內存,但處理速度慢2到5倍 repo = Repo('path/to/repo',odbt=GitDB)
GitCmdObjectDB
使用git-cat-file實例讀取配置庫信息,訪問速度比較快,但內存占用比GitDB嚴重。
repo = Repo('path/to/repo',odbt=GitCmdObjectDB)
引用操作的實例
head操作
heads = repo.heads
master = heads.master #lists can be accessed by name for convenience
master.commit #the commit pointed to by head called master master.rename('new_name') #rename heads tag(tag通常是不變的)是一個commit或tag對象的引用 tags = repo.tags tagref = tags[0] #tag可以有一個tag對象,存儲額外的信息 tagref.commit #tag總是指向一個commit repo.delete_tag(tagref) #刪除一個tag repo.create_tag('my_tag') #創建一個tag 符號引用可以替代具體commit指向一個引用 head = repo.head #the head points to the active branch/ref master = head.reference #but they always point to commits master.commit #from here you use it as any other reference 訪問reflog log = master.log() log[0] #first reflog entry log[-1] #last reflog entry 修改引用 創建、刪除各種引用和修改指向 repo.delete_head('master') #delete an existing head master = repo.create_head('master') #create a new one master.commit = 'HEAD~10' #set branch to another commit without changing index or working tree 創建、刪除tags new_tag = repo.create_tag('my_tag','my message') repo.delete_tag(new_tag) 分支直接切換 new_branch = repo.craete_head('new_branch') repo.head.reference = new_branch git庫的各種對象 git的所有對象都存在git數據庫中。對象包含的信息有類型、未壓縮的大小、每個對象都有一個20個字節的唯一的SHA1值。 git有四類對象Blobs、Trees、Commits and Tags git所有的對象都可以訪問,但通常是通過引用或git倉庫的方法來訪問,不是直接從數據庫中讀取。 hc = repo.head.commit hct = hc.tree hc != hct hc != repo.tags[0] hc == repo.head.reference.commit git對象基本字段有 hct.type hct.size hct.hexsha hct.binsha 索引對象可以用作git的索引,這些對象是Trees/Blobs和Submodules ,這些對象含有文件路徑的信息。 hct.path #root tree has no path hct.trees[0].path #the first subdirectory has one though hct.mode #trees have the mode of a linux directory hct.blobs[0].mode #blobs have a specific mode though compareable to a standard linux fs 使用stream訪問blob數據或者其他對象數據 hct.blobs[0].data_stream.read() #stream object to read data from hct.blobs[0].stream_data(open("blob_data","w")) #write data to given stream Commit對象 commit對象包含固定commit的信息。通過引用或者指定版本可以獲取到commit對象 repo.commit('master') repo.commit('v0.1') repo.commit('HEAD~10') 獲取100指定引用上100commit repo.iter_commits('master',max_count=100) 分頁顯示 顯示21-30的記錄 repo.iter_commits('master',max_count=10,skip=20) headcommit = repo.head.commit headcommit.hexsha headcommit.parents headcommit.author headcommit.tree headcommit.committer headcommit.committed_date headcommit.message 時間格式化 import time time.asctime(time.gmtime(headcommit.committed_date)) #'Web May 7 05:56:02 2013' tiem.strftime("%a,%d %b %Y %H:%M",time.gmtime(headcommit.committed_date)) #'Web,7 May 2013 05:56' 訪問commit祖先 headcommit.parents[0].parents[0].parents[0].parents[0] 等價於master^^^^ 或者master~4 Tree對象 tree對象指向當前目錄的內容。獲取master分支最新提交的根tree對象 tree = repo.heads.master.commit.tree 通過tree對象可以獲取的內容有 tree.trees #trees are subdirectories tree.blobs #blobs are files 可以通過名稱獲取tree對象 tree[0] = tree['dir'] #access by index and by sub-path blob = tree[0][0] blob.name blob.path blob.abspath 有簡便的方法通過子目錄名稱就可以獲取對象 tree/"lib" tree/"dir/file" == blob 如果指定tree對象的名稱也可以直接從git數據庫中讀取 repo.tree() #返回<git.Tree "master"> repo.tree("c1c7214dde86...") repo.tree('0.1.6') 遍歷tree對象 tree.traverse() for entry in tree.traverse():do_something_with(entry) 如果tree對象返回的是子模塊對象,默認為是當前head的commit 索引對象 git的索引對象包含了commit變更和合並信息。通過索引對象可以獲得更復雜的信息 index = repo.index 讀取、添加、刪除實例,Commit變更: for stage,blob in index.iter_blobs():do_something(...) #Access blob object for (path,stage),entry in index.entries.iteritems: pass #Access the entries directly index.add(['my_new_file']) #add a new file to the index index.remove(['dir/existing_file']) new_commit = index.commit("my commit message") 通過tree或者merge創建新索引 tmp_index = Index.from_tree(repo,'HEAD~1') #load a tree into a temporary index merge_index = Index.from_tree(repo,'base','HEAD','some_branch') #merge two trees three-way merge_index.write('merged_index') 遠程倉庫 遠程名稱作為外部從倉庫的別名,可以通過它push和fetch數據 test_remote = repo.create_remote('test','git@server:repo.git') repo.delete_remote(test_remote) # create and delete remotes origin = repo.remotes.origin #get default remote by name origin.refs #local remote reference o = origin.rename('new_origin') #rename remotes o.fetch() #fetch,pull and push from and to the remote o.pull() o.push() 遠程庫的配置信息 o.url 修改配置信息 o.config_writer.set('pushurl','other_url') 子模塊 對象比較 可以比較index和Trees或者Index和working tree 或者trees和trees以及trees和working copy hcommit = repo.head.commit idiff = hcommit.diff() #diff tree against index tdiff = hcommit.diff('HEAD~1') #diff tree against previous tree wdiff = hcommit.diff(None) #diff tree against working tree index = repo.index index.diff() #diff index agginst itself yielding empty idff index.diff(None) #diff index against working copy index.diff('HEAD') #diff index against current HEAD tree 比較返回的比較索引本質上是一個Diff對象列表,通過額外的過濾方法你可以找到你想要的內容 for diff_added in wdiff.iter_change_type('A'): do_something_with(diff_added) 分支切換 想切換分支,你需要設置HEAD指向新分支,重置index和工作區 repo.head.reference = repo.heads.other_branch repo.head.reset(index=True,working_tree=True) 上面的方法會覆蓋掉工作區中所有修改未提交的邊更新,下面的方法則不會 repo.heads.master.checkout() #checkout the branch using git-checkout repo.heads.other_branch.checkout() 直接使用git庫 通過git實例使用git命令 git = repo.git git.checkout('head',b='my_new_branch') #default command git.for_each_ref() #'-' becomes '_' when calling it