สมมติว่าที่เก็บระยะไกลมีสำเนาของการพัฒนาสาขา (คำอธิบายเริ่มต้นของคุณอธิบายในพื้นที่เก็บข้อมูลในท้องถิ่น แต่ดูเหมือนว่ามันยังมีอยู่ในระยะไกล) คุณควรจะสามารถบรรลุสิ่งที่ฉันคิดว่าคุณต้องการ แต่วิธีการ แตกต่างจากที่คุณจินตนาการไว้เล็กน้อย
ประวัติของ 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