Bir taahhüdün başka bir taahhüdün torunu olup olmadığını nasıl anlarım?


Yanıtlar:


51

Bunu programlı olarak kontrol etmek istiyorsanız (örn. Komut dosyasında), git merge-base A Beşit olup olmadığını git rev-parse --verify A(o zaman A'ya B'den ulaşılabilir mi), yoksa git rev-parse --verify B(B'ye A'dan ulaşılabildiğini) kontrol edebilirsiniz. git rev-parseBurada, taahhüt adından SHA-1 / taahhüt kimliğine dönüştürmek gerekir.

VonC cevabında olduğu git rev-listgibi kullanmak da mümkündür.

Düzenleme: modern Git şeklinde bu sorgu için açık destek vardır git merge-base --is-ancestor.


Eğer sorduğunuz taahhütlerden biri bir şube ipucu ise , o zaman git branch --contains <commit>ya git branch --merged <commit>da daha iyi programatik olmayan bir çözüm olabilir.


1
Muhtemelen en hızlı yol git checkout -b quickcheck <more-recent-commit-ID>ve sonra git branch --contains <older-commit-ID>(ve daha sonra git branch -D quickcheckgeçici daldan kurtulmak) olacaktır.
clee

2
Her ikisi de @ MattR'nin cevabındaki yaklaşımdan çok daha kötü olan iki olası yaklaşım.
jwg

6
@jwg: MattR cevabı daha iyi, ama bu cevap (ve muhtemelen kabul ediliyor) git 1.8.0 ve git merge-base --is-ancestor2 yıl öncesine dayanıyor .
Jakub Narębski

@ JakubNarębski Yeterince adil, özür dilerim.
jwg

2
Büyük bir depo (2000000 kaydedilmesini), ben hızını karşılaştırıldı git branch --contains <commit>ve git merge-base --is-ancestor ...0.14s vs 3m40s:
hagello

259

Git 1.8.0 sürümünden bu seçenek aşağıdakiler için desteklenir merge-base:

git merge-base --is-ancestor <maybe-ancestor-commit> <descendant-commit>

Man sayfasından:

--is-ata

Birincisinin ikincinin atası olup olmadığını kontrol edin ve doğruysa 0 durumuyla veya değilse 1 durumuyla çıkın. Hatalar 1 olmayan sıfırdan farklı bir durumla bildirilir.

Örneğin:

git merge-base --is-ancestor origin/master master; echo $?

4
Güzel! İşte bu cevabı insan tarafından okunabilir çıktıya sahip bir şeyle tamamlayan bir kabuk komut dosyası: gist.github.com/simonwhitaker/6354592
Simon Whitaker

1
Başka bir deyişle: git merge-base THING --is-ancestor OF_THING && echo yes || echo noeg:git merge-base my-feature-branch --is-ancestor master && echo yes || echo no
user1735594

2
@smarber , şu anda oldukça eski olan 2.1.4 (Debian / Devuan 7.10 jessie) ve 1.9.1 (Ubuntu 14.04 güvenilir) git merge-base --is-ancestor -- commit commitile karmalarıma çalışıyor git. Debian için bile işe yarar sudo apt-get install git/wheezy-backports.
Tino

15

Bu tür işlemler SO sorusunda ayrıntılarıyla belirtilen revizyon aralığı fikrine dayanır : " 'git log origin / master' ve 'git log origin / master ..' " arasındaki fark.

git rev-list ulaşılabiliyorsa, bir taahhütten diğerine kadar yürüyebilmelidir.

Bu yüzden denerdim:

git rev-list --boundary 85e54e2408..0815fcf18a
0815fcf18a19441c1c26fc3495c4047cf59a06b9
8a1658147a460a0230fb1990f0bc61130ab624b2
-85e54e240836e6efb46978e4a1780f0b45516b20

(Sınır taahhütlerinin önüne ek gelir -)

Görüntülenen son işlem, komuttaki ilk işlemle aynıysa git rev-list, ikinci işlemden erişilebilen bir işlemdir.

İlk taahhüt ikinciden ulaşılamazsa, git rev-listhiçbir şey döndürmemelidir.

git rev-list --boundary A..B

tarafından bitirmek istiyorum Aeğer Agelen ulaşılabilir B.
Aynı:

git rev-list --boundary B --not A

ile Bbir pozitif referans ve Abir negatif referans .
Şuradan başlar Bve ulaşılabilir bir revizyonla karşılaşıncaya kadar grafikte geriye doğru yürür A.
Ben eğer iddia ediyorum Adoğrudan ulaşılabilir B, bu (çünkü, ve ekran karşılaşacak --boundaryseçeneği) Akendisini.


Bu, git'in tam olarak bunu yapan bir "porselen" komutu yayınlamamasına şaşırdığım yeterince yaygın bir kullanım durumu gibi görünüyor.
Lawrence I.Siden

1
@lsiden: doğru. Yan not: bir şeyi programlı olarak kontrol etmeyi unutmayın, porselen komutunu kullanmamalısınız ( stackoverflow.com/questions/6976473/… ), ancak sıhhi tesisat komutlarını ( stackoverflow.com/questions'da gösterildiği gibi) / 3878624 /… )
VonC

Oh, adamım, geri dönüp Shell kodlama pirzolalarım üzerinde çalışmam gerekiyor gibi görünüyor!
Lawrence I.Siden

1
soru: -85e54e2...Snippet'teki neden eksi var? Ayrıca olası bir yazım hatası: "... ilk taahhüt ile aynı ..."
sdaau

1
@sdaau -bunun bir sınır taahhüdü olduğu anlamına gelir. Cevabı daha net hale getirmenin yanı sıra, doktor bağlantılarını yenilemek ve bu 5 yıllık cevap için yazım hatasını düzeltmek için düzenlemeyi düzenledim.
VonC

11

Başka bir yol kullanmak git logve olacaktır grep.

git log --pretty=format:%H abc123 | grep def456

Bu, kesinleştirme def456, kesinleştirme abc123'ün bir atasıysa veya başka bir çıktı yoksa, bir çıktı satırı üretecektir.

Genellikle --prettyargümanı atlamaktan kurtulabilirsiniz , ancak günlük yorumları vb. İle değil, yalnızca gerçek taahhüt karmaları ile arama yaptığınızdan emin olmak istiyorsanız gereklidir.


Bu çözümün yavaş olmasını bekliyordum, ancak 20k + taahhütlü bir proje için bile oldukça hızlı
Renato Zannon

2
kullanmak yerine--prettygit log --oneline ce2ee3d | grep ec219cc
gens


1

git gösteri-şube şube-sha1 taahhüt-sha1

Nerede:

  • branch-sha1: şubenizdeki kontrol etmek istediğiniz sha1
  • commit-sha1: kontrol etmek istediğiniz taahhüdün sha1'i

0

Kullanıyorsanız git merge-base --is-ancestor, Git 2.28 (Q3 2020) kullandığınızdan emin olun.

Git 2.28 (Q3 2020) ile, " struct commit" içerisindeki her zaman bulunması gerekmeyen birkaç alan, döşeme işlemek için taşınmıştır.

Bkz. C752ad0 , c49c82a , 4844812 , 6da43d9 (17 Haziran 2020), Abhishek Kumar ( abhishekkumar2718) .
(Tarafından Birleştirilmiş Junio C Hamano - gitster- içinde taahhüt d80bea4 , 6 Temmuz 2020)

commit-graph: takdim etmek commit_graph_data_slab

İmzalayan: Abhishek Kumar

Yapı taahhüdü birçok bağlamda kullanılır. Ancak, üyeler generationve graph_possadece kesin grafik ile ilgili işlemler için kullanılır ve aksi takdirde bellek boşa.

Bu israf, mevcut 32 bit yerine 64 bit nesil sayısı kullanan v2 nesil numarasına geçiş yaptığımızda daha belirgin olurdu.

Sıklıkla birlikte eriştikleri için, yapıyı tanıtalım commit_graph_datave bunları bir commit_graph_datalevhaya taşıyalım .

Genel test takımı master(seri: 26m48s master,: 27m34s,% 2.87 daha hızlı) kadar hızlı çalışırken, Szeder Gábor'un keşfettiği gibi bazı komutlar git merge-base --is-ancestor% 40 yavaşladı . Kesim levhası erişimini en aza indirdikten sonra, yavaşlama devam eder, ancak% 20'ye yakındır.

Derrick Stolee yavaşlamanın alt yapı erişiminin yavaşlığından ziyade altta yatan algoritmaya atfedilebileceğine inanıyor ve daha sonraki bir dizide takip edeceğiz.


-1

Depodaki tüm etiketler için bunu yapmanız gerektiğinde, itub'ın cevabına dayanarak:

for i in `git tag` ; do echo -ne $i "\t" ; git log --pretty=format:%H $i | (grep <commit to find> || echo ""); done
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.