2010-01-11 107 views
8

我想要做什麼合併的提交:有遠程的Git倉庫拒絕推送

我想禁止任何合併提交到中央存儲庫。 唯一例外如果合併在中央存儲庫中存在的分支之間。我想在中央存儲庫執行此操作。

解釋我爲什麼要這麼做:

注:如果這份說明你天旋地轉的是我想做的線索,則忽略該項解釋。當然,我很高興聽到其他方法來解決我在下面解釋的問題,但我感興趣的答案是我想要如上所述做的。

我有一箇中央git存儲庫,有幾個開發人員跟蹤的分支。每個開發人員都爲該中央存儲庫的分支配置一個遠程。

我們遵循此項目的同步提交策略,因此每個開發人員在推送之前都必須始終在遠程分支頭頂部重新分配他們的最新工作。我想通過禁止任何合併提交被推送到中央存儲庫來執行此策略。唯一的例外是如果合併在中央存儲庫中存在的分支之間。

爲了簡化,我不希望開發人員的本地跟蹤分支與遠程分支合併。但總是在遠程分支上重新設計。

通過設置branch.NAME.rebase = true,我們已經在開發人員的機器上部分實施了這個功能,這有助於避免開發人員使用git pull時出現的問題,但是我們需要一個解決方案來在中央存儲庫一側執行此操作。

一個非常基礎的解決方案是拒絕提交註釋:「Merge branch'NAME'of GITURL」,但是,更多的檢查是否所有的父母都存在於中央存儲庫的分支路徑中更有趣。

對此提出建議?解決方案?

編輯:

這是我到目前爲止有:

#!/bin/sh 
read sha1old sha1new refname 

# check if this is merge commit 
merge_commit="`git rev-list --parents --merges --no-walk $sha1new 2> /dev/null`" 
if test -n "$merge_commit" 
then 
    # this was a merge commit 
    # $merge_commit contains: sha1new sha1parent_1 ... sha1parent_n 
fi 
exit 0 

它變得麻煩的地方是確定任何兩個父母的血統是否從單獨分支起源。另外,由於pre-receive鉤子在任何refs被更新之前被調用,如果一個push包含兩個分支在遠程存在的提交,包括這兩個分支之間的合併,那麼我不知道這裏的解決方案是什麼。

+0

完全重複:http://stackoverflow.com/questions/1997916/git-post-receive-how-to-check-if-pushed-branch-is-merged-with-master – Dustin 2010-01-11 04:00:52

+3

我完全不同意它是一個副本。它與我所問的事情很少有關。 – chris 2010-01-11 04:11:32

回答

10

防止推送會產生非線性歷史記錄的一種方法是設置一個pre-receive鉤子,它使用git rev-list --parents <OLD>..<NEW>來檢查任何具有多個父代的新提交,如果有錯誤則退出。要處理第二個要求,您可以檢查是否有多個父代,這些提交必須全部位於存儲庫中的現有分支上。我沒有測試這個非常多,但是這pre-receive機(或者它的一些變體)可能是你想要什麼:

#!/usr/bin/ruby -w 

# A pre-receive hook that should refuse any pushes that would update 
# master in such a way that a non-linear history would be created, 
# except where it involves a merge from another branch in this 
# repository. This has only had very cursory testing. 

# This is a suggested answer to: 
# http://stackoverflow.com/questions/2039773/have-remote-git-repository-refuse-local-branch-merge-commits-on-push 

ref_to_check = "refs/heads/master" 

rev_old, rev_new, ref = STDIN.read.split(" ") 

if ref == ref_to_check 
    merge_bases = `git merge-base #{rev_old} #{rev_new}`.strip.split(/\s+/) 
    unless $?.success? and merge_bases.length == 1 
    STDERR.puts "No unique merge base found between #{rev_old} and #{rev_new}" 
    exit(1) 
    end 
    rev_list_output = `git rev-list --parents #{merge_bases[0]}..#{rev_new}` 
    list_of_revs_with_parents = rev_list_output.strip.split(/[\r\n]+/) 
    list_of_revs_with_parents.each do |line| 
    rev_with_parents = line.strip.split(/\s+/) 
    if rev_with_parents.length > 2  
     parents = rev_with_parents.slice(1,rev_with_parents.length) 
     # The question says to permit non-linear history if the merge is 
     # from another branch in the central repository, so check 
     # whether that's the case. (If you just want to prevent all 
     # pushes that add non-linear history, just exit with error 
     # here.) 
     any_parent_not_on_any_branch = false 
     parents.each do |p| 
     branches = `git branch --contains #{p} 2> /dev/null` 
     if $?.success? and ! branches.strip.empty? 
      STDERR.puts "More than one parent of commit #{rev_with_parents[0]}" 
      STDERR.puts "... but parent #{p} is on branches:" 
      STDERR.puts branches 
     else 
      STDERR.puts "Parent #{p} not found on any other" 
      STDERR.puts "branch in this repository" 
      any_parent_not_on_any_branch = true 
      break 
     end 
     end 
     if any_parent_not_on_any_branch 
     STDERR.puts "Refusing push, since it would create non-linear history" 
     STDERR.puts "for #{ref} and the merges don't just involve commits on" 
     STDERR.puts "other branches in this repository." 
     exit(2) 
     end 
    end 
    end 
end 

我希望這是一些使用。

+0

謝謝!我當然不希望完全書面的實施。 它看起來像我想要的,我會通過一些測試來運行它。 – chris 2010-01-18 01:04:03

+0

首先,我不得不移除這個,因爲我沒有安裝ruby。 但是,據我瞭解這個腳本,它仍然會允許非線性歷史的情況下提交包括一個分支之間的發散提交路徑之間的合併點。這通常是您從非重新設計的本地跟蹤分支中看到的結果。我還沒有通過測試來證實這一點,所以我在閱讀劇本時可能會錯過一些東西。 – chris 2010-01-23 04:42:14

+0

如果用戶正在使用master,從origin/master和origin/master進行合併是線性的,我不認爲會發生這種情況。如果滿足這些條件,那麼除了主站不在主站/主站中的情況之外,該用戶的主站與其起源/主站之間的任何合併都將是線性快進。如果用戶然後嘗試推送這樣的合併,鉤子將看到其中一個父母不在主人身邊並拒絕它。 (雖然如果他們想要變得困難,他們可以將他們的主人推​​到服務器上的一個新分支,這樣父母就知道了。) – 2010-01-25 17:55:09

相關問題