2013-10-10 164 views
2

我喜歡在我們的git服務器中設置一個預接收掛鉤,用於檢查配置文件並在推送無效時放棄推送(我想根據分支名稱檢查是否存在某些標記) 。但我已經看到,先前的鉤子只是收到(old-rev,new-rev,refname)列表,我發現檢查文件內容的唯一方法是對那些引用進行區分,這不是很舒適。Git預接收掛鉤檢查配置

有沒有簡單的方法來做到這一點? 預先提交掛鉤會更容易,但我想在服務器中有最後一道屏障。

回答

5

在新對象(提交,註釋標記對象,樹和blob)已被加載到存儲庫中之後,但在引用(分支名稱,標記名稱等)之前調用預接收或更新掛鉤被改變了。

這是爲什麼預收到鉤得到的名單(oldnewref)的三倍:現有回購有對象和現有REF(如果有的話)指向對象(通常提交,有時標籤)的SHA-1是old。 Git建議將其更改爲指向其SHA-1爲new(或者如果其中的一個是全零「空SHA-1」,則創建或刪除它)的對象。

我發現檢查文件內容的唯一方法就是版本比較這些引用

這是一個辦法,但你必須混帳的整套命令解壓的一切。例如,您可以在某個地方創建一個新的空目錄(mkdir path)並運行git --work-tree=path checkout sha1以獲取完整的樹到該路徑中。 (如果樹很大,這可能需要一些時間,當然你在其上運行的任何測試都需要更多的時間。)

你必須決定你想要檢查的內容。因爲你希望它是這是複雜的,但對於分支名稱(形式refs/heads/name,其中name是任何分支機構名稱,即可以包含更多的斜線的ref),認爲裁判更新可能會做一個或多個以下的(一些組合顯然是不可能的):

  • 添加一個新的分支名
  • 添加新的提交到現有的分支
  • 刪除現有的分支
  • 刪除承諾現有的分支名

舉例來說,如果我有一個裸露的回購origin的克隆,我這樣做:

git fetch origin      # get up-to-date with origin 
git checkout -b branch origin/branch # make tracking branch for origin/branch 
git reset --hard HEAD~3    # back up 3 commits 
echo more stuff >> existing_file  # modify something 
git commit -a -m 'add new text'  # commit the change 
git revert --no-edit HEAD    # add another commit that undoes change 
git push -f origin branch    # and push 

那麼更新將移除三個提交和增加兩個。樹,你會如果你簽出的new SHA-1(再次使用oldnewref三重符號)獲得看起來完全一樣的版本,我也問過推。如果有一些樹木必須通過的測試,大概HEAD~3的版本確實通過了這些測試,所以這個版本也是如此。然而,我承諾增加一行existing_file可能而不是通過測試,並且您可能不喜歡我刪除了三個提交的事實。

因此,再次,由您決定要檢查的內容,並編寫代碼來實現這一點。檢查強制推送是否刪除提交;允許或禁止這一點。檢查是否正在創建新的分支名稱;允許或禁止。檢查分支名稱是否被刪除;允許或禁止。如果正在添加提交,請檢查每個中間提交的樹,或僅檢查最終的樹;允許或禁止。提交被添加涉及合併?標籤被添加,刪除或更改了嗎?等等。

只是爲了好玩,前一段時間我寫了一個pre-receive shell script(在POSIX風格的shell),它做了許多這些(它不檢查任何提交的內容)。我做了一些非常輕的測試,它似乎工作。它可以作爲更徹底檢查的起點。

如果您正在認真檢查,您可能需要使用gitolite進行調查。

+0

這是一個很好的答案@torek。你可以澄清一件事,接近你推薦檢查的結尾(例如)強制推送是否刪除提交,如何檢查?你計算'old'和'new'的祖先數量嗎? – Segfault

+0

@Segfault:快速簡單的方法來看看'$ new'丟棄提交'$ old'保持可達狀態是使用'git rev-list $ new .. $ old'(添加'--count'來得到一個計數,而不是這種轉速的實際列表)。如果你拼寫'git rev-list $ old^$ new':''old''''''''''''''''''''''''''''無法從'$ new'到達提交。 – torek