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 baz
didasarkan pada (versi lama) bar
? Tetapi bagaimana jika kita menghapus bar
?
---o---1 foo
\
2---3
\
4
\
5---6 baz
Sekarang sepertinya baz
didasarkan pada foo
. Tetapi nenek moyang baz
tidak 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 baz
didasarkan pada quux
. Meski begitu, nenek moyang tidak berubah, hanya label yang berubah.
Namun, jika kita bertanya "apakah melakukan 6
turunan dari komitmen 3
?" (dengan asumsi 3
dan nama 6
lengkap SHA-1 komit), maka jawabannya adalah "ya", apakah label bar
dan quux
ada 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 H
dan S
saat menerima H'
, J
, K
, atau N
, tetapi akan juga menerima L
dan P
(mereka melibatkan gabungan, tetapi mereka tidak menggabungkan ujung berkembang ).
Untuk juga menolak L
dan 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