Dengan asumsi bahwa repositori jarak jauh memiliki salinan cabang pengembangan (deskripsi awal Anda menjelaskannya dalam repositori lokal, tetapi kedengarannya seperti itu juga ada di remote), Anda harus dapat mencapai apa yang saya pikir Anda inginkan, tetapi pendekatannya sedikit berbeda dari apa yang Anda bayangkan.
Sejarah Git didasarkan pada DAG komitmen. Cabang (dan "ref" secara umum) hanyalah label sementara yang menunjukkan komitmen spesifik dalam DAG commit yang terus berkembang. Dengan demikian, hubungan antar cabang dapat bervariasi dari waktu ke waktu, tetapi hubungan antara komitmen tidak.
---o---1 foo
\
2---3---o bar
\
4
\
5---6 baz
Sepertinya bazdidasarkan pada (versi lama) bar? Tetapi bagaimana jika kita menghapus bar?
---o---1 foo
\
2---3
\
4
\
5---6 baz
Sekarang sepertinya bazdidasarkan pada foo. Tetapi nenek moyang baztidak berubah, kami hanya menghapus label (dan hasilnya menjuntai komit). Dan bagaimana jika kita menambahkan label baru di 4?
---o---1 foo
\
2---3
\
4 quux
\
5---6 baz
Sekarang sepertinya bazdidasarkan pada quux. Meski begitu, nenek moyang tidak berubah, hanya label yang berubah.
Namun, jika kita bertanya "apakah melakukan 6turunan dari komitmen 3?" (dengan asumsi 3dan nama 6lengkap SHA-1 komit), maka jawabannya adalah "ya", apakah label bardan quuxada atau tidak.
Jadi, Anda dapat mengajukan pertanyaan seperti "apakah komit yang didorong adalah turunan dari ujung cabang pengembangan saat ini ?", Tetapi Anda tidak dapat dengan andal bertanya "apa cabang induk dari komit yang didorong?".
Sebagian besar pertanyaan yang andal yang tampaknya mendekati apa yang Anda inginkan adalah:
Untuk semua leluhur komit terdorong (tidak termasuk ujung kembang saat ini dan leluhurnya), yang memiliki kembang ujung saat ini sebagai induk:
- apakah setidaknya ada satu komit seperti itu ada?
- apakah semua komitmen seperti itu dilakukan oleh orang tua tunggal?
Yang dapat diimplementasikan sebagai:
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
Ini akan mencakup sebagian dari apa yang Anda inginkan dibatasi, tetapi mungkin tidak semuanya.
Untuk referensi, berikut adalah sejarah contoh yang diperluas:
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
Kode di atas dapat digunakan untuk menolak Hdan Ssaat menerima H', J, K, atau N, tetapi akan juga menerima Ldan P(mereka melibatkan gabungan, tetapi mereka tidak menggabungkan ujung berkembang ).
Untuk juga menolak Ldan P, Anda dapat mengubah pertanyaan dan bertanya
Untuk semua leluhur komit yang terdorong (tidak termasuk tip perkembangan saat ini dan leluhurnya):
- apakah ada komitmen dengan dua orang tua?
- jika tidak, apakah setidaknya satu komit tersebut memiliki tip mengembangkan (hanya) induknya?
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