यह मानते हुए कि दूरस्थ रिपॉजिटरी में विकास की एक प्रति है शाखा (आपका प्रारंभिक विवरण स्थानीय रिपॉजिटरी में इसका वर्णन करता है, लेकिन ऐसा लगता है कि यह रिमोट में भी मौजूद है), आपको वह हासिल करने में सक्षम होना चाहिए जो मुझे लगता है कि आप चाहते हैं, लेकिन दृष्टिकोण आपने जो कल्पना की है, उससे थोड़ा अलग है।
Git का इतिहास कमिट्स के DAG पर आधारित है। शाखाएँ ("सामान्य रूप से") केवल क्षणिक लेबल हैं जो निरंतर बढ़ते हुए DAG में विशिष्ट कमिट की ओर इशारा करती हैं। जैसे, शाखाओं का संबंध समय के साथ अलग-अलग हो सकता है, लेकिन आवागमन के बीच का संबंध नहीं होता है।
---o---1 foo
\
2---3---o bar
\
4
\
5---6 baz
ऐसा लगता है कि baz
(पुराने संस्करण पर) आधारित है bar
? लेकिन अगर हम हटा दें तो क्या होगा bar
?
---o---1 foo
\
2---3
\
4
\
5---6 baz
अब ऐसा लग रहा है कि baz
यह पर आधारित है foo
। लेकिन पूर्वजों में baz
बदलाव नहीं हुआ, हमने सिर्फ एक लेबल (और परिणामस्वरूप झूलने की प्रतिबद्धता) को हटा दिया। और क्या होगा अगर हम एक नया लेबल जोड़ते हैं 4
?
---o---1 foo
\
2---3
\
4 quux
\
5---6 baz
अब ऐसा लग रहा है कि baz
यह पर आधारित है quux
। फिर भी, वंश नहीं बदला, केवल लेबल बदल गए।
यदि, हालांकि, हम पूछ रहे थे "प्रतिबद्ध का 6
एक वंशज है 3
?" (मानकर 3
और 6
पूर्ण SHA-1 प्रतिबद्ध नाम हैं), तो उत्तर "हां" होगा, चाहे लेबल bar
और quux
मौजूद हों या नहीं।
तो, आप ऐसे सवाल पूछ सकते हैं जैसे "धक्का दिया गया है कि विकसित शाखा की वर्तमान टिप का एक वंशज है ?", लेकिन आप मज़बूती से नहीं पूछ सकते हैं "धक्का दिया प्रतिबद्ध की मूल शाखा क्या है?"।
एक सबसे विश्वसनीय प्रश्न जो आप चाहते हैं, उसके करीब पहुंचने के लिए लगता है:
सभी पुश किए गए पूर्वजों के लिए ( विकास और उसके पूर्वजों की वर्तमान टिप को छोड़कर ), जिनके पास माता-पिता के रूप में विकसित होने की वर्तमान टिप है :
- कम से कम एक ऐसी प्रतिबद्धता मौजूद है?
- क्या सभी ऐसे एकल-अभिभावक कमिट हैं?
जिसे इस प्रकार लागू किया जा सकता है:
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
echo "'$basename' is missing, call for help!"
exit 1
fi
parents_of_children_of_base="$(
git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
grep -F "$baserev"
)"
case ",$parents_of_children_of_base" in
,) echo "must descend from tip of '$basename'"
exit 1 ;;
,*\ *) echo "must not merge tip of '$basename' (rebase instead)"
exit 1 ;;
,*) exit 0 ;;
esac
यह कुछ को कवर करेगा जिसे आप प्रतिबंधित करना चाहते हैं, लेकिन शायद सब कुछ नहीं।
संदर्भ के लिए, यहां एक विस्तारित उदाहरण इतिहास है:
A master
\
\ o-----J
\ / \
\ | o---K---L
\ |/
C--------------D develop
\ |\
F---G---H | F'--G'--H'
| |\
| | o---o---o---N
\ \ \ \
\ \ o---o---P
\ \
R---S
ऊपर दिए गए कोड को अस्वीकार करने के लिए इस्तेमाल किया जा सकता है H
और S
, जबकि स्वीकार करने H'
, J
, K
, या N
, लेकिन यह भी स्वीकार करेंगे L
और P
(वे आपस में विलय शामिल है, लेकिन वे की नोक आपस में नहीं मिलाते विकसित )।
अस्वीकार करने के लिए L
और P
, आप प्रश्न को बदल सकते हैं और पूछ सकते हैं
सभी पुश किए गए पूर्वजों के लिए ( विकास और उसके पूर्वजों की वर्तमान टिप को छोड़कर ):
- क्या दो माता-पिता के साथ कोई विवाद है?
- यदि नहीं, तो क्या कम से कम एक ऐसे प्रतिबद्ध के पास अपने (केवल) माता-पिता को विकसित करने की वर्तमान टिप है ?
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
echo "'$basename' is missing, call for help!"
exit 1
fi
parents_of_commits_beyond_base="$(
git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
grep -v '^commit '
)"
case "$parents_of_commits_beyond_base" in
*\ *) echo "must not push merge commits (rebase instead)"
exit 1 ;;
*"$baserev"*) exit 0 ;;
*) echo "must descend from tip of '$basename'"
exit 1 ;;
esac