2010-01-11 25 views
8

मैं आपकी क्या अपेक्षाएं हैं पर प्रतिबद्ध विलय मना है:दूरस्थ Git भंडार धक्का

मैं चाहता हूँ को नामंज़ूर किसी भी मर्ज करताहोने के लिए केंद्रीय भंडार के लिए धक्का दे दिया। केवल अपवाद यह है कि विलय केंद्रीय भंडार में मौजूद शाखाओं के बीच है। मैं इसे केंद्रीय भंडार में लागू करना चाहता हूं।

कारण है कि मैं ऐसा करना चाहते हैं का स्पष्टीकरण:

नोट: इस स्पष्टीकरण मुझे क्या करना चाहते हैं, उसके निशान बंद आप फेंकता है, तो स्पष्टीकरण ध्यान न दें। निस्संदेह मुझे नीचे बताई गई समस्या को हल करने के अन्य तरीकों को सुनकर खुशी हुई है, लेकिन जिस उत्तर में मुझे रूचि है, वह है जो मैं ऊपर बताए अनुसार करना चाहता हूं।

मेरे पास एक शाखा के साथ केंद्रीय गिट भंडार है जो कई डेवलपर ट्रैक करते हैं। प्रत्येक डेवलपर के पास उस केंद्रीय भंडार की शाखा के लिए रिमोट कॉन्फ़िगर किया गया है।

हम इस परियोजना के लिए एक सिंक्रोनस प्रतिबद्ध नीति का पालन करते हैं, इसलिए प्रत्येक डेवलपर को हमेशा धक्का देने से पहले रिमोट शाखा HEAD के शीर्ष पर अपने नवीनतम काम को दोबारा जरूरी करना चाहिए। मैं इस नीति को केंद्रीय भंडार में कभी भी धकेलने के लिए किसी विलय की प्रतिबद्धता को अस्वीकार कर लागू करना चाहता हूं। एकमात्र अपवाद यह है कि विलय केंद्रीय भंडार में मौजूद शाखाओं के बीच है।

सरल बनाने के लिए, मैं नहीं चाहता कि डेवलपर की स्थानीय ट्रैकिंग शाखाओं को कभी भी दूरस्थ शाखा के साथ विलय किया जाए। बल्कि हमेशा रिमोट शाखा पर छूट दी जाएगी।

हमने शाखा को स्थापित करके डेवलपर की मशीन पर आंशिक रूप से इसे लागू किया है .NAME.rebase = सत्य जो डेवलपर गिट पुल का उपयोग करता है, समस्याओं को टालने में मदद करता है, हालांकि हमें केंद्रीय भंडार पक्ष पर इसे लागू करने के लिए एक समाधान की आवश्यकता है।

एक बहुत ही मूल समाधान टिप्पणी के साथ काम करने से इंकार कर देगा: "GITURL के शाखा 'NAME को मर्ज करें" हालांकि, जांच के आधार पर कुछ और अधिक है कि क्या केंद्रीय रिपोजिटरी के शाखा पथों में प्रतिबद्धता के सभी माता-पिता मौजूद हैं अधिक दिलचस्प हो।

सुझाव? समाधान की?

संपादित करें:

#!/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 

जगह यह परेशानी हो जाता है यह पता लगाना है किसी भी दो माता-पिता के वंश एक भी शाखा से हुई हों:

यह वही है मैं अब तक है। इसके अलावा, क्योंकि किसी भी रेफ को अपडेट करने से पहले पूर्व-प्राप्त हुक को बुलाया जाता है, अगर रिमोट में मौजूद दो शाखाओं के लिए एक पुश होता है, जिसमें उन दो शाखाओं के बीच विलय शामिल होता है, तो मुझे नहीं पता कि समाधान क्या होगा .. ।

+0

सटीक डुप्लिकेट: http://stackoverflow.com/questions/1997916/git-post-receive-how-to-check-if-pushed-branch-is-merged-with-master – Dustin

+3

मैं पूरी तरह असहमत हूं कि यह पूरी तरह से असहमत है एक डुप्लिकेट मैंने जो कुछ पूछा है उसके साथ कुछ भी करना बहुत कम है। – chris

उत्तर

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

+0

सबसे पहले, मुझे यह बंदरगाह करना है क्योंकि मेरे पास रूबी स्थापित नहीं है। हालांकि, जैसा कि मैं इस स्क्रिप्ट को समझता हूं, फिर भी यह उस मामले में गैर रेखीय इतिहास की अनुमति देगा जहां प्रतिबद्धता में एक शाखा पर अलग-अलग कार्य पथों के बीच विलय बिंदु होता है। आम तौर पर जो आप गैर-छूट वाली स्थानीय ट्रैकिंग शाखाओं से देखेंगे। मैंने अभी तक परीक्षण के माध्यम से यह सत्यापित नहीं किया है, इसलिए मुझे स्क्रिप्ट के पढ़ने में कुछ याद आ रहा है। – chris

+0

यदि कोई उपयोगकर्ता मास्टर पर काम कर रहा है, तो मूल/मास्टर और मूल/मास्टर से विलय होना रैखिक है, मुझे नहीं लगता कि ऐसा हो सकता है। यदि उन शर्तों को पूरा किया जाता है, तो उस उपयोगकर्ता के मास्टर और उनके मूल/मास्टर के बीच कोई विलय उन मामलों में से एक को छोड़कर एक रैखिक फास्ट-फॉरवर्ड होगा जहां मास्टर मूल/मास्टर में मौजूद नहीं है। यदि उपयोगकर्ता इस तरह के विलय को धक्का देने की कोशिश करता है, तो हुक देखेगा कि माता-पिता में से एक मास्टर में पहले से ही नहीं है और इसे मना कर दिया है। (हालांकि अगर वे मुश्किल होना चाहते थे तो वे अपने मास्टर को सर्वर पर एक नई शाखा में धकेल सकते थे, इसलिए माता-पिता वहां जाना जाता है।) –

संबंधित मुद्दे