用 JGit 初始化 Git 庫
最近,我被問及如何用 JGit 來初始化一個新的 Git 庫,比如實現初始化一個庫 /path/to/repodoes。
當我用 JGit 來建立庫時其實並不難,這裡有些細節值得提一提。因為在網上幾乎少有關於這個主題的資料,而且有些還是錯誤的,因此本文就總結了如何使用 JGit API 來初始化一個 Git 庫的方法。
本地庫
為了用 JGit 來初始化一個庫,那就要使用初始化命令。factoryGit 命令擁有一個靜態方法 init() 來建立初始化命令。
Git git = Git.init().setDirectory( directory ).call();
在上述程式碼執行後,一個新的Git庫就已經建立完成了。這個庫的儲存位置是通過setDirectory()來給定的,這個庫構成了工作目錄,它包含了已簽出的檔案及資料夾。若這個目錄並不存在,那麼通過上述方法會一直建立這個工作目錄。
一個名為 .git 的子目錄在整個工作目錄中處於最頂層。這裡麵包含了本地庫的歷史日誌,配置引數,分支指標,索引(又名中轉區)等等。
上面的截圖中展示了.git 目錄的內部結構。refs 目錄維護了分支和標籤資訊。其實際內容將會儲存在物件目錄中。在 logs 目錄中,有關對分割槽的修改都會被記錄。舉個例子,一個提交和簽出操作都將建立一個日誌記錄,這個記錄可以用 gitreflog 命令來檢視。多年前我寫的這個帖子 Explore Git Internals with the JGit API 裡面詳細的寫明瞭如何使用 Git 來管理這個庫裡內容。
為了確保命令事實上成功執行,狀態命令常用於查詢庫的狀態,很像git status做的一樣。但不幸的是JGit的status實現不同於原生Git,因為如果沒有庫,它不會報錯。這使得檢查一個已存在HEAD ref變得更為必要,它表示事實上有一個庫。
assertNotNull( git.getRepository().getRef( Constants.HEAD ) ); assertTrue( git.status().call().isClean() );
對於最近初始化的庫來說,isClean()返回true,是因為在工作目錄裡邊沒有任何改動或者有未跟蹤檔案。
斷言使用theInitCommandscall()方法返回的GIT例項。這個類充當工廠的作用,並且常用於建立在庫上執行的Git命令(例如:add,commit,checkout)。
新初始化的庫比較特殊,由於還沒有分支被建立。儘管有一個引用分支的HEAD(指向當前分支),(預設叫做master)這個特有的分支並不存在。
就第一個提交來說通常沒有什麼需要擔心的,缺少的分支將會被建立。不管怎樣,像git branch這樣的操作可以建立分支並會在最初的提交被提交之前,會伴隨著略微令人誤導的錯誤資訊’Ref HEAD cannot be resolved’而失敗。
確定庫是否包含一個提交,檢查HEAD ref如下:
Ref headRef = git.getRepository().getRef( Constants.HEAD ); if( headRef == null || headRef.getObjectId() == null ) { // no commit yet }
將目錄變成庫
如上所示,在必要的情況下,InitCommand會建立缺少的目錄。但是這個命令也常用於已存在的目錄,從而將其變成一個git庫。
下面的程式碼片段在一個包含一個檔案的已存在目錄裡邊初始化庫,並保留其內容。
File file = new File( "/path/to/existing/directory/readme.txt" ); file.createNewFile(); Git git = Git.init().setDirectory( file.getParentFile() ).call(); assertTrue( git.status().call().getUntracked().contains( file.getName() ) );
由於檔案未被跟蹤,status命令會提示這個檔案。直到將這個檔案加入索引才能夠被提交到剛剛建立的庫裡邊。
如果指定的目錄已經持有一個Git庫,那就沒有必要擔心。既然這樣,JGit將不做任何事並返回一個指向已存在庫的例項。
分離工作和.git目錄
預設情況下,儘管一個庫有一個工作目錄,它的.git目錄直接位於工作目錄下面,但這不是必須的。一個庫完全可以沒有工作目錄(後續討論)或者工作目錄可以位於一個除.git目錄之外完全不同的位置。
下面的初始化命令建立了這樣一個庫
Git git = Git.init().setDirectory( workDir ).setGitDir( gitDir ).call();
最終的庫將會位於gitDir目錄(儲存歷史記錄,分支,標籤等的目錄),但這將會使它的工作目錄在workDir上面。
對於一個已存在的庫來說,工作目錄配置也是可以改變的。要麼手動編輯配置檔案.git,或者通過JGit API配置。
StoredConfig config = git.getRepository().getConfig(); config.setString( "core", null, "worktree", workDir.getCanonicalPath() ); config.save();
沒有必要把工作目錄內容手動從舊的位置移動到新的位置。
空倉庫
剛剛建立的庫是在本地處理的,也叫非空倉庫。另一種Git庫叫做空倉庫。
這些目的在於用作中心倉庫,將被其他使用者共享。沒有直接的提交可以提交到空倉庫中。一個空倉庫收到提交,是由於它們從使用者本地倉庫被推送。團隊成員從這個倉庫中拿下其他人提交的提交。
下面的程式碼片段將建立一個空倉庫。
Git git = Git.init().setDirectory( directory ).setBare( true ).call();
一個空倉庫沒有工作目錄。反之,它的目錄結構可以在一個非空倉庫中的.git目錄下面找到並在指定的目錄中直接被建立。
因為status命令需要一個工作目錄,所以它不能夠驗證上述程式碼成功執行。而是倉庫例項應該為空並想下面驗證指向所需目錄。
assertTrue( git.getRepository().isBare() ); assertEquals( directory, git.getRepository().getDirectory() );
值得注意的是為這個工作目錄查詢倉庫(也就是callinggetWorkTree())將會對空倉庫丟擲NoWorkTreeException。
可選API: Repository.create()
一個可選的方法來初始化倉庫就是使用Repository的create方法。
Repository repository = new FileRepositoryBuilder().setGitDir( directory ).build(); repository.create(); assertNotNull( git.getRepository().getRef( Constants.HEAD ) ); assertTrue( Git.wrap( repository ).status().call().isClean() );
在FileRepositoryBuilder幫助下,Repository例項被建立,代表沒有現有的庫。Callingcreate()方法具體化倉庫。結果和InitCommand一樣。
為了建立空倉庫,還有一個過載的方法:create(boolean bare)。
結論
我希望這篇文章能夠幫助理解怎樣用JGit建立一個新倉庫。這裡使用的程式碼收集於學習測試,可以在這裡發現它的全部內容:
https://gist.github.com/rherrmann/4bacb68b23be1f12c73d
它詳細說明了對InitCommand API正確和不正確的使用,或許可以作為進一步實驗JGit的一個起點。
如果你有任何難點或問題,可以留下評論或在友善且樂於助人的JGit社群提問以獲得幫助。
相關文章
- 如何用JGit管理Git子模組Git
- git初始化--本地建立git倉庫Git
- 我的Git教程 之 初始化本地庫Git
- 使用git初始化本地倉庫並提交到遠端分支Git
- git安裝與初始化Git
- 第7章:備用資料庫之初始化備用資料庫資料庫
- Git應用詳解第十講:Git子庫:submodule與subtreeGit
- git倉庫配置git sshGit
- Git 倉庫Git
- git 為已有工程建立git倉庫Git
- Git 子庫使用Git
- Git清空版本庫Git
- Git 建立倉庫Git
- 資料庫表初始化資料庫
- oa資料庫初始化資料庫
- postgresql資料庫初始化SQL資料庫
- PG資料庫初始化資料庫
- 初用gitGit
- 【Git】Git reset/revert的應用Git
- git操作之四:git branch(本地倉庫)Git
- Git使用系列03-->Git倉庫建立Git
- Git Step by Step (6):Git遠端倉庫Git
- git 遠端倉庫Git
- GIT倉庫匯入Git
- git換倉庫命令Git
- 取得 Git 倉庫 —— Git 學習筆記 04Git筆記
- 手把手教你配置git和git倉庫Git
- Git專案匯入其他的git倉庫Git
- Git Step by Step (7):Git遠端倉庫(續)Git
- Git 實用指南Git
- 實用git指令Git
- GIT實用指北Git
- Git 本地倉庫和裸倉庫Git
- git倉庫修改遠端倉庫Git
- 【git學習三】git基礎之git管理遠端倉庫Git
- 搭建個人部落格,Docsify+Github webhook+JGit解決方案GithubWebHook
- 達夢7資料庫初始化資料庫
- Android功能庫初始化管理利器Android