Katakanlah saya memiliki repositori lokal berikut dengan pohon komit seperti ini:
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
master
adalah saya ini terbaru kode rilis stabil , develop
adalah saya ini adalah 'berikutnya' kode rilis , dan feature
merupakan fitur baru yang disiapkan untukdevelop
.
Apa yang saya ingin dapat lakukan pada repo jarak jauh saya menggunakan kait, adalah untuk mendorong untuk feature
ditolak kecuali komit f
adalah keturunan langsung develop
KEPALA. yaitu pohon komit terlihat seperti ini karena fitur telah git rebase
aktif d
.
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
Jadi apakah mungkin untuk:
- Identifikasi cabang induk dari
feature
? - Identifikasi komit di cabang induk yang
f
merupakan turunan dari?
Dari sana saya akan memeriksa apa KEPALA cabang induk, dan melihat apakah f
pendahulu cocok dengan cabang orangtua KEPALA, untuk menentukan apakah fitur perlu diubah kembali.
Jawaban:
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.
Sepertinya
baz
didasarkan pada (versi lama)bar
? Tetapi bagaimana jika kita menghapusbar
?Sekarang sepertinya
baz
didasarkan padafoo
. Tetapi nenek moyangbaz
tidak berubah, kami hanya menghapus label (dan hasilnya menjuntai komit). Dan bagaimana jika kita menambahkan label baru di4
?Sekarang sepertinya
baz
didasarkan padaquux
. Meski begitu, nenek moyang tidak berubah, hanya label yang berubah.Namun, jika kita bertanya "apakah melakukan
6
turunan dari komitmen3
?" (dengan asumsi3
dan nama6
lengkap SHA-1 komit), maka jawabannya adalah "ya", apakah labelbar
danquux
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:
Yang dapat diimplementasikan sebagai:
Ini akan mencakup sebagian dari apa yang Anda inginkan dibatasi, tetapi mungkin tidak semuanya.
Untuk referensi, berikut adalah sejarah contoh yang diperluas:
Kode di atas dapat digunakan untuk menolak
H
danS
saat menerimaH'
,J
,K
, atauN
, tetapi akan juga menerimaL
danP
(mereka melibatkan gabungan, tetapi mereka tidak menggabungkan ujung berkembang ).Untuk juga menolak
L
danP
, Anda dapat mengubah pertanyaan dan bertanyasumber
develop > release > feature
, saya akan mendapatkan kembali dan itu membutuhkan mengetahui orang tua. Solusi untuk masalah saya adalah stackoverflow.com/a/56673640/2366390Sebuah rephrasal
Cara lain untuk mengutarakan pertanyaannya adalah "Apa komit terdekat yang berada di cabang selain cabang saat ini, dan cabang mana yang itu?"
Sebuah solusi
Anda dapat menemukannya dengan sedikit sihir baris perintah
Dengan awk :
Begini cara kerjanya:
Dan Hasilnya
Menjalankan kode di atas
Akan memberi Anda
develop
jika Anda menjalankannya dari H danmaster
jika Anda menjalankannya dari I.Kode tersedia sebagai intisari
sumber
cannot handle more than 25 refs
ack
tidak tersedia di Mac (seseorang menyarankan untuk menggantiack
dengangrep
)git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
git show-branch | sed "s/].*//" | grep "\*" | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed "s/^.*\[//"
parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"
berfungsi untuk sayaAnda juga dapat mencoba:
sumber
git log --graph --decorate --simplify-by-decoration
dimana--graph
opsional.git log --graph --decorate --simplify-by-decoration --oneline
orangtua git
Anda bisa menjalankan perintah
git parent
untuk menemukan induk cabang, jika Anda menambahkan jawaban @ Jo Chrysler sebagai alias git . Ini akan menyederhanakan penggunaan.
Buka file gitconfig yang terletak di
"~/.gitconfig"
menggunakan editor teks apa pun. (Untuk linux). Dan untuk Windows jalur ".gitconfig" umumnya terletak dic:\users\your-user\.gitconfig
Tambahkan perintah alias berikut dalam file:
Simpan dan keluar dari editor.
Jalankan perintah
git parent
Itu dia!
sumber
cannot handle more than 25 refs
pengecualian.Saya punya solusi untuk masalah Anda secara keseluruhan (tentukan jika
feature
diturunkan dari ujungdevelop
), tetapi tidak berfungsi menggunakan metode yang Anda uraikan.Anda dapat menggunakan
git branch --contains
daftar semua cabang turun dari ujungdevelop
, kemudian gunakangrep
untuk memastikanfeature
ada di antara mereka.Jika ada di antara mereka, itu akan dicetak
" feature"
ke output standar dan memiliki kode pengembalian 0. Jika tidak, tidak akan mencetak apa pun dan memiliki kode pengembalian 1.sumber
<branch>
, di mana saya tampil:git checkout -b <branch-2>
dari ... INI adalah jawabannya! Tidak perlu grep, kok.git branch --contains <branch>
Ini bekerja dengan baik untuk saya.
Jawaban sopan dari: @droidbot dan @Jistanidiot
sumber
*
bukan regex yang tepat untuk diteruskan ke grep. Harus digunakangrep -F '*'
ataugrep '\*'
sebagai gantinya. Sebaliknya solusi yang bagus.Karena tidak ada jawaban di atas yang berfungsi pada repositori kami, saya ingin berbagi dengan cara saya sendiri, menggunakan gabungan terbaru di
git log
:Masukkan ke dalam skrip bernama
git-last-merges
, yang juga menerima nama cabang sebagai argumen (bukan cabang saat ini) serta yang laingit log
argumenDari output, kita dapat secara manual mendeteksi cabang induk berdasarkan esensi cabang sendiri dan jumlah penggabungan dari masing-masing cabang.
EDIT: Jika Anda sering menggunakan
git rebase
cabang anak (dan penggabungan sering diteruskan sehingga tidak ada terlalu banyak gabungan yang dilakukan), jawaban ini tidak akan berfungsi dengan baik, jadi saya menulis skrip untuk menghitung komit di depan (normal dan gabungan) , dan di belakang komit (seharusnya tidak ada penggabungan di belakang di cabang induk) pada semua cabang dibandingkan dengan cabang saat ini. Jalankan saja skrip ini dan beri tahu saya apakah ini cocok untuk Anda atau tidaksumber
rebase
sering menggunakan (dan penggabunganfast-forward
sering dilakukan). Saya akan mengedit jawaban saya jika saya menemukan solusi yang lebih baik.git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 1 | cut -d ' ' -f 8
Sebuah solusi
Solusi berdasarkan
git show-branch
tidak cukup bekerja untuk saya (lihat di bawah), jadi saya telah menggabungkannya dengan yang didasarkan padagit log
dan berakhir dengan ini:Keterbatasan dan Peringatan
log
perintahmaster
dandevelop
hasil (kebanyakan) di<SHA> Initial commit
Hasil
Meskipun keberadaan cabang lokal (mis. Hanya
origin/topic
ada sejak komitO
diperiksa langsung oleh SHA-nya), skrip harus dicetak sebagai berikut:G
,H
,I
(cabanghotfix
) →master
M
,N
,O
(cabangfeature/a
) →develop
S
,T
,U
(cabangfeature/c
) →develop
P
,Q
,R
(cabangfeature/b
) →feature/a
J
,K
,L
(cabangdevelop
) →<sha> Initial commit
*B
,D
,E
,F
(cabangmaster
) →<sha> Initial commit
* - atau
master
jikadevelop
komitmen berada di atas KEPALA master (~ master akan maju cepat untuk berkembang)Mengapa tidak menunjukkan cabang bekerja untuk saya
Solusi berdasarkan
git show-branch
terbukti tidak dapat diandalkan untuk saya dalam situasi berikut:grep '\*' \
untuk `grep '! \ - dan itu hanyalah awal dari semua masalahmaster
dandevelop
hasil dalamdevelop
dan `` masing-masingmaster
cabang (hotfix/
cabang) berakhir dengandevelop
sebagai induk karenamaster
induk cabang terdekat mereka ditandai dengan!
alih - alih*
karena suatu alasan.sumber
"!git log --decorate --simplify-by-decoration --oneline | grep -v '(HEAD' | head -n1 | sed 's/.* (\\(.*\\)) .*/\\1/' | sed 's/\\(.*\\), .*/\\1/' | sed 's/origin\\///'"
Ingat bahwa, seperti yang dijelaskan dalam "Git: Menemukan darimana asal sebuah komit berasal" , Anda tidak dapat dengan mudah menentukan cabang tempat komit tersebut dibuat (cabang dapat diubah namanya, dipindahkan, dihapus ...), meskipun itu
git branch --contains <commit>
adalah permulaan.git branch --contains <commit>
tidak mencantumkanfeature
cabang dan daftardevelop
cabang,/refs/heads/develop
Jika kedua melakukan id cocok, Anda baik untuk pergi (itu berarti
feature
cabang memiliki asal di KEPALAdevelop
).sumber
Sihir baris perintah JoeChrysler dapat disederhanakan. Inilah logika Joe - untuk singkatnya saya telah memperkenalkan parameter bernama
cur_branch
pengganti substitusi perintah`git rev-parse --abbrev-ref HEAD`
ke dalam kedua versi; yang dapat diinisialisasi seperti:Lalu, inilah pipa Joe:
Kita dapat mencapai hal yang sama seperti kelima perintah individu itu menyaring dalam perintah yang relatif sederhana
awk
:Itu rusak seperti ini:
membagi garis menjadi bidang di
]
,^
,~
, dan[
karakter.Temukan garis yang mengandung tanda bintang
... tetapi bukan nama cabang saat ini
Ketika Anda menemukan garis seperti itu, cetak bidang keduanya (yaitu, bagian antara kemunculan pertama dan kedua dari karakter pemisah bidang kami). Untuk nama-nama cabang yang sederhana, itu adalah apa yang ada di antara kurung; untuk referensi dengan lompatan relatif, itu hanya nama tanpa pengubah. Jadi, set pemisah bidang kami menangani maksud kedua
sed
perintah.Kemudian segera keluar. Ini berarti hanya memproses baris pencocokan pertama, jadi kami tidak perlu menyalurkan output
head -n 1
.sumber
Berikut ini adalah implementasi PowerShell dari solusi Mark Reed:
sumber
Saya tidak mengatakan ini adalah cara yang baik untuk menyelesaikan masalah ini, namun ini sepertinya bekerja untuk saya.
git branch --contains $(cat .git/ORIG_HEAD)
Masalahnya adalah bahwa menjalankan file sedang mengintip ke dalam git, jadi ini belum tentu kompatibel ke depan (atau kompatibel ke belakang).sumber
Implementasi lintas platform dengan Ant
sumber
@Mark Reed: Anda harus menambahkan bahwa garis komit seharusnya tidak hanya mengandung tanda bintang, tetapi mulai dengan tanda bintang! Kalau tidak, komit pesan yang mengandung tanda bintang juga termasuk dalam baris yang cocok. Jadi seharusnya:
git show-branch -a | awk -F'[]^~[]' '/^\*/ && !/'"$current_branch"'/ {print $2;exit}'
atau versi panjang:
sumber
Mencapai tujuan yang sama dengan jawaban Mark Reed, tetapi menggunakan pendekatan yang jauh lebih aman yang tidak nakal dalam sejumlah skenario:
-
tidak*
*
sumber
Siapa pun yang ingin melakukan ini akhir-akhir ini - aplikasi SourceTree dari Atlassian menunjukkan kepada Anda representasi visual yang hebat tentang bagaimana cabang Anda berhubungan satu sama lain, yaitu Di mana mereka memulai dan di mana mereka saat ini duduk dalam urutan komit (mis. HEAD atau 4 komit di belakang, dll.) .
sumber
Jika Anda menggunakan Source Tree lihat detail komit Anda> Parents> maka Anda akan melihat angka komit digarisbawahi (tautan)
sumber
Sebuah alternatif:
git rev-list master | grep "$(git rev-list HEAD)" | head -1
Dapatkan komit terakhir yang merupakan cabang saya dan
master
(atau cabang apa pun yang ingin Anda tentukan)sumber
Ini tidak bekerja untuk saya ketika saya telah melakukan sesuatu seperti
develop > release-v1.0.0 > feature-foo
, itu akan berjalan jauh ke belakang untuk berkembang, perhatikan ada rebase yang terlibat, tidak yakin apakah itu memperparah masalah saya ...Berikut ini memang memberikan hash komit yang benar untuk saya
sumber