Git ile bir şube noktası mı arıyorsunuz?


455

Şube yöneticisi ve A ile ikisi arasında çok sayıda birleştirme etkinliğine sahip bir havuzum var. A dalı master'a göre oluşturulduğunda depodaki taahhüdü nasıl bulabilirim?

Depom temel olarak şöyle görünüyor:

-- X -- A -- B -- C -- D -- F  (master) 
          \     /   \     /
           \   /     \   /
             G -- H -- I -- J  (branch A)

A revizyonunu arıyorum, bu da bulamayan şey değil git merge-base (--all).


Yanıtlar:


499

Aynı şeyi arıyordum ve bu soruyu buldum. Sorduğun için teşekkürler!

Ancak, Burada görmediğim cevaplar görünmüyor bulundu oldukça sizin için (ya da ben aradığını) sordu cevap vermek - verdikleri gibi Gyerine, taahhüt Aişlemek.

Bu nedenle, aşağıdaki ağacı (kronolojik sırada atanan harfler) oluşturdum, böylece işleri test edebilirim:

A - B - D - F - G   <- "master" branch (at G)
     \   \     /
      C - E --'     <- "topic" branch (still at E)

Bu sizinkinden biraz farklı görünüyor, çünkü B'ye sahip olduğumdan emin olmak istedim (sizin değil, bu grafiğe atıfta bulunarak), A değil (D veya E değil). İşte (benim Repo klonlanmış olabilir mesajlar SHA öneklerine ekli harfler ve taahhüt burada o kimseye ilginç eğer):

G: a9546a2 merge from topic back to master
F: e7c863d commit on master after master was merged to topic
E: 648ca35 merging master onto topic
D: 37ad159 post-branch commit on master
C: 132ee2a first commit on topic branch
B: 6aafd7f second commit on master before branching
A: 4112403 initial commit on master

Yani amaç: B'yi bulun . İşte biraz müdahaleden sonra bulduğum üç yol:


1. görsel olarak, gitk ile:

Görsel olarak böyle bir ağaç görmelisiniz (ustadan göründüğü gibi):

master gitk ekran yakalama

veya burada (konudan görüldüğü gibi):

konudan gitk ekran yakalama

her iki durumda da, Bgrafiğimdeki taahhüdü seçtim. Üzerine tıkladığınızda, tam SHA'sı grafiğin hemen altındaki bir metin giriş alanında sunulur.


2. görsel olarak, ancak terminalden:

git log --graph --oneline --all

(Düzenleme / yan not: ekleme --decoratede ilginç olabilir; şube adları, etiketler vb. İle ilgili bir gösterge ekler.

gösteren (varsayarak git config --global color.ui auto):

git log çıktısı --graph --oneline --all

Veya düz metin olarak:

* a9546a2 konudan master'a birleştirme
| \  
| * 648ca35 master'ı konuya birleştiriyor
| | \  
| * | 132ee2a konu dalında ilk taahhüt
* | | Master konu ile birleştirildikten sonra e7c863d master üzerinde taahhüt
| | /  
| / |   
* | 37ad159 şube sonrası yüksek lisans taahhüdü
| /  
* 6aafd7f dallanmadan önce master konusunda ikinci taahhüt
* 4112403 master'a ilk taahhüt

her iki durumda da, 6aafd7f komutunu en düşük ortak nokta olarak görüyoruz, yani Bgrafiğimde veya Asizinkinde.


3. kabuk sihirli Ile:

Sorunuzda yukarıdaki gibi bir şey mi, yoksa sadece bir revizyonu alacak olan tek bir komut mu yoksa başka bir şey mi istediğinizi belirtmezsiniz. İşte ikincisi:

diff -u <(git rev-list --first-parent topic) \
             <(git rev-list --first-parent master) | \
     sed -ne 's/^ //p' | head -1
6aafd7ff98017c816033df18395c5c1e7829960d

Hangi ~ / .gitconfig içine de koyabilirsiniz (not: sondaki çizgi önemlidir; buna dikkat çektiğiniz için teşekkürler Brian ) :

[alias]
    oldest-ancestor = !zsh -c 'diff -u <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | sed -ne \"s/^ //p\" | head -1' -

Bu, aşağıdaki (tırnak işareti ile kıvrık) komut satırı ile yapılabilir:

git config --global alias.oldest-ancestor '!zsh -c '\''diff -u <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | sed -ne "s/^ //p" | head -1'\'' -'

Not: zshaynı kolaylıkla olabilirdi bashama shwill not iş - <()sözdizimi vanilya mevcut değildir sh. (Bu sayfadaki başka bir cevabın yorumunda beni haberdar ettiğin için tekrar teşekkürler, @conny!)

Not: Yukarıdakilerin alternatif versiyonu:

Teşekkür etmek Liori için işaret yani (özdeş dalları karşılaştırırken yukarıda aşağı düşebilir ve karışımdan sed formu kaldırır alternatif bir fark formu ile geliyor ve bu "güvenli" (yani bir sonuç döndürür yapar en son taahhüt) ustayı ustayla karşılaştırsanız bile):

Bir .git-config satırı olarak:

[alias]
    oldest-ancestor = !zsh -c 'diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | head -1' -

Kabuktan:

git config --global alias.oldest-ancestor '!zsh -c '\''diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "${1:-master}") <(git rev-list --first-parent "${2:-HEAD}") | head -1'\'' -'

Bu yüzden, test ağacımda (bir süre kullanılamaz, üzgünüm; geri döndü), şimdi hem master hem de konu üzerinde çalışıyor (sırasıyla G ve B taahhütlerini veriyor). Alternatif form için tekrar teşekkürler liori.


Böylece, ben [ve liori] buldum. Benim için çalışıyor gibi görünüyor. Ayrıca, kullanışlı olabilecek ek bir takma ad çiftine izin verir:

git config --global alias.branchdiff '!sh -c "git diff `git oldest-ancestor`.."'
git config --global alias.branchlog '!sh -c "git log `git oldest-ancestor`.."'

Mutlu git-ing!


5
Teşekkürler lindes, kabuk seçeneği, uzun süren bir bakım dalının dal noktasını bulmak istediğiniz durumlar için mükemmeldir. Geçmişte bin taahhütte olabilecek bir revizyon arıyorsanız, görsel seçenekler gerçekten onu kesmeyecek. * 8 ')
Mark Booth

4
Üçüncü yönteminizde, bağlamın ilk değiştirilmemiş satırı göstereceğine güvenirsiniz. Bu, bazı kenar durumlarda olmaz veya biraz farklı gereksinimlere sahip olursanız (örneğin, geçmişlerden sadece birine ihtiyacım var - ilk-ebeveyn olmalı ve bu yöntemi bazen aynı olan bir komut dosyasında kullanıyorum her iki tarafta dalları). diff'Eğer if-then-else modunu kullanmanın daha güvenli olduğunu ve değiştirilen / silinen satırları, yeterince büyük içeriğe güvenmek yerine çıktısından sildiğimi gördüm diff --old-line-format='' --new-line-format='' <(git rev-list …) <(git rev-list …)|head -1.
liori

3
git log -n1 --format=format:%H $(git log --reverse --format=format:%H master..topic | head -1)~Bence de işe yarayacak
Tobias Schulte

4
@ JakubNarębski: Bu ağaç için git merge-base --fork-point ...B taahhüdü vermenin bir yolu var 6aafd7fmı? Bunu yayınladığınızda diğer şeylerle meşguldüm ve kulağa hoş geldi, ama sonunda denedim ve işe yaramıyorum ... Daha yeni bir şey ya da sessiz bir hata alıyorum (hata yok) mesajı ancak çıkış durumu 1), gibi argümanları çalışırken git co master; git merge-base --fork-point topic, git co topic; git merge-base --fork-point master, git merge-base --fork-point topic masterya ödeme için (), vb orada bir şey yanlış yapıyor ya da eksik mi?
22'de lindes

25
@ JakubNarębski @lindes reflog'a --fork-pointdayanır, bu nedenle yalnızca yerel olarak değişiklik yaptıysanız çalışır. O zaman bile, reflog girişlerinin süresi dolmuş olabilir. Yararlı ama hiç güvenilir değil.
Daniel Lubarov

131

Şunu arıyorsunuz git merge-base:

git merge-base , üç yollu birleştirme işleminde kullanmak için iki işlem arasındaki en iyi ortakları bulur. Bir ortak ata, bir diğerinin atası ise diğer ortak atadan daha iyidir. Daha iyi bir ortak ataya sahip olmayan ortak bir ata en iyi ortak atadır , yani bir birleştirme tabanıdır . Bir çift işlem için birden fazla birleştirme tabanı olabileceğini unutmayın.


10
Not --all" git merge-base" seçeneği
Jakub Narębski

10
Bu orijinal soruyu cevaplamıyor, ancak çoğu insan bunun cevabı olduğu çok daha basit bir soru soruyor :)
FelipeC

6
git merge-base'in sonucunu almadığını söyledi
Tom Tanner

9
@TomTanner: Soru geçmişine yeni baktım ve orijinal soru, git merge-basecevabımın gönderilmesinden yaklaşık beş saat sonra (muhtemelen cevabımın cevabına göre) bu notu içerecek şekilde düzenlendi . Yine de, bu cevabı olduğu gibi bırakacağım, çünkü bu soruyu arama yoluyla bulan başka biri için hala yararlı olabilir.
Greg Hewgill

Listeden en eski ortak atayı bulmak için merge-base --all'ın sonuçlarını kullanabileceğinizi ve sonra merge-base --is-ator kullanarak geri dönüşlerin listesini gözden geçirebileceğinizi düşünüyorum, ancak bu en basit yol değil .
Matt_G

42

git rev-listBu tür şeyler için kullandım . Örneğin, ( 3 noktayı not edin )

$ git rev-list --boundary branch-a...master | grep "^-" | cut -c2-

şube noktasını tükürecek. Şimdi, mükemmel değil; master'ı birkaç kez A dalına birleştirdiğinizden, bu birkaç olası dallanma noktasını böler (temel olarak orijinal dallanma noktası ve daha sonra master'ı A dalına birleştirdiğiniz her nokta). Ancak, en azından olasılıkları daraltmalıdır.

Bu komutu diğer adlarıma şöyle ekledim ~/.gitconfig:

[alias]
    diverges = !sh -c 'git rev-list --boundary $1...$2 | grep "^-" | cut -c2-'

böylece şöyle diyebilirim:

$ git diverges branch-a master

Not: Bu, ortak atadan ziyade dalda ilk taahhüdü veriyor gibi görünüyor. (yani o verir Gyerine Aorijinal Söz konusu grafiğin başına.) Ben alır bir cevabım var Aben halen gönderme olacak ki.
Lindes

@ lindes: Denediğim her durumda ortak ata verir. Burada olmayan bir örneğiniz var mı?
mipadi

Evet. In my cevap (klonlamak bir repoya bir bağlantı vardır; git checkout topicve daha sonra bu çalıştırmak topicyerine branch-a), bu listeleri 648ca357b946939654da12aaf2dc072763f3caeeve37ad15952db5c065679d7fc31838369712f0b338 - her ikisi 37ad159ve 648ca35(ikincisi geçerli BAŞ olmanın akım dalların Ancestory içindedir topic), fakat dallanmadan önceki nokta da değildir. Farklı bir şey mi alıyorsunuz?
Lindes

@ lindes: Repoyu klonlayamadım (muhtemelen bir izin sorunu?).
mipadi

Ayy üzgünüm! Bana bildirdiğiniz için teşekkür ederim. Git update-server-info komutunu çalıştırmayı unuttum. Şimdi gitmek iyi olmalı. :)
28'de lindes

31

Kısa komutları seviyorsanız,

git rev-list $ (git rev-list --first-parent ^ branch_name master | kuyruk -n1) ^^! 

İşte bir açıklama.

Aşağıdaki komut, şube_adı oluşturulduktan sonra gerçekleşen master'daki tüm taahhütlerin listesini verir.

git rev-list - ilk-ana ^ şube_adı yöneticisi 

Bu taahhütlerin en erkenini önemsediğiniz için, çıktının son satırını istersiniz:

git rev-list ^ şube_adı - ilk-ana master | kuyruk -n1

En erken ebeveyni o "branch_name" bir atası değil, tanımı gereği taahhüt de bunun içinde bir şeyin bir atası beri "branch_name" ve "usta" olduğunu "usta". Yani her iki dalda da en erken taahhüt var.

Komuta

git rev-list taahhüt ^ ^!

yalnızca üst öğe taahhüt referansını göstermenin bir yoludur. Kullanabilirsin

git log -1 taahhüt ^

ya da her neyse.

PS: Ata düzeninin alakasız olduğu iddiasına katılmıyorum. Ne istediğine bağlı. Örneğin, bu durumda

_C1___C2_______ master
  \ \ _XXXXX_ A dalı (X'ler, ana ve A arasındaki rastgele geçişleri belirtir)
   \ _____ / şube B

"dallanma" taahhüdü olarak C2 çıktısı almak mükemmeldir. Bu, geliştiricinin "master" dan ayrıldığı zamandır. Dallandığında, dal "B" dalında bile birleştirilmedi! Bu yazıdaki çözüm budur.

İstediğiniz son nokta C, başlangıç ​​noktasından "A" dalındaki son işleme kadar olan tüm yolların C üzerinden geçeceği şekilde varsa, o zaman ataların sırasını yoksaymak istersiniz. Bu tamamen topolojiktir ve aynı anda kodun iki versiyonuna sahip olduğunuzdan beri size bir fikir verir. İşte o zaman birleştirme tabanlı yaklaşımlarla devam edersiniz, ve benim örneğimde C1'i döndürecektir.


3
Bu en temiz cevap, hadi bu oyu en üste çıkaralım. Önerilen bir düzenleme: git rev-list commit^^!basitleştirilebilirgit rev-parse commit^
Russell Davis

Cevap bu olmalı!
trinth

2
Bu cevap, sadece güzel değiştirilir git rev-list --first-parent ^branch_name masterile git rev-list --first-parent branch_name ^masterana dal 0 kaydedilmesini öncesinde diğer dalı (buna hızlı yönlendirilebilen) arasında, hiçbir çıkış yaratabileceği çünkü eğer. Benim çözümümle, master kesinlikle önde ise (yani şube tamamen birleştirildiyse) hiçbir çıktı oluşturulmaz, bu da istediğim şey.
Michael Schmeißer

3
Tamamen bir şey eksik olmadıkça bu işe yaramaz. Örnek dallarda her iki yönde birleşmeler vardır. Bunu dikkate almaya çalıştığınız anlaşılıyor, ancak bunun cevabınızın başarısız olmasına neden olacağına inanıyorum. git rev-list --first-parent ^topic masteryalnızca ilk son birleştirme işlemi sonrasında taahhüt geri alacak masteriçine topic(bile varsa).
jerry

1
@jerry Doğru, bu cevap çöp; örneğin, bir backmerge yeni gerçekleşmişse (master'ı konuya birleştirdiyse) ve master'ın bundan sonra yeni bir taahhüdü yoksa, ilk git rev-list --first-parent komutu hiçbir şey çıkarmaz.
TamaMcGlinn

19

Bu konudaki cevapların birçoğunun sorunun sorduğu cevabı vermediği göz önüne alındığında, burada her bir çözümün sonuçlarının bir özeti ve soruda verilen depoyu çoğaltmak için kullandığım komut dosyası var.

Günlük

Verilen yapı ile bir havuz yaratarak, git logunu aldık:

$ git --no-pager log --graph --oneline --all --decorate
* b80b645 (HEAD, branch_A) J - Work in branch_A branch
| *   3bd4054 (master) F - Merge branch_A into branch master
| |\  
| |/  
|/|   
* |   a06711b I - Merge master into branch_A
|\ \  
* | | bcad6a3 H - Work in branch_A
| | * b46632a D - Work in branch master
| |/  
| *   413851d C - Merge branch_A into branch master
| |\  
| |/  
|/|   
* | 6e343aa G - Work in branch_A
| * 89655bb B - Work in branch master
|/  
* 74c6405 (tag: branch_A_tag) A - Work in branch master
* 7a1c939 X - Work in branch master

Tek eklemem, şubeyi yarattığımız nokta ve böylece bulmak istediğimiz taahhüt hakkında onu açık hale getiren etiket.

Çalışan çözüm

Çalışan tek çözüm sağladığı biridir Lindes doğru getiri A:

$ diff -u <(git rev-list --first-parent branch_A) \
          <(git rev-list --first-parent master) | \
      sed -ne 's/^ //p' | head -1
74c6405d17e319bd0c07c690ed876d65d89618d5

As Charles Bailey olsa işaret, bu çözüm çok kırılgandır.

Eğer varsa branch_Aiçine masterve sonra birleştirme masteriçine branch_Akaydedilmesini müdahale etmeden sonra Lindes' çözüm sadece verir en son ilk Diverjans .

Bu, iş akışım için, uzun süren dalların dallanma noktasını etiketlemekle uğraşmam gerektiğini düşünüyorum, çünkü daha sonra güvenilir bir şekilde bulunabileceklerini garanti edemiyorum.

Bu gerçekten tüm aşağı kaynar gitler ne yoksun hgçağrıları adlı dalları . Blogcu JHW bu çağrıları soylar vs aileleri yazısında Neden Daha Git Daha ben gibi Mercurial ve onun takip makalesinde Git vs Daha Mercurial Açık (Grafikleri ile!) . İnsanların bazı cıva dönüştürür olmamasından özledim nedenini görmek için onları okumak öneriyoruz adlı dalları içindegit .

İşe yaramayan çözümler

Mipadi tarafından sağlanan çözüm iki cevap döndürür Ive C:

$ git rev-list --boundary branch_A...master | grep ^- | cut -c2-
a06711b55cf7275e8c3c843748daaa0aa75aef54
413851dfecab2718a3692a4bba13b50b81e36afc

Greg Hewgill tarafından sağlanan çözüm geri döndüI

$ git merge-base master branch_A
a06711b55cf7275e8c3c843748daaa0aa75aef54
$ git merge-base --all master branch_A
a06711b55cf7275e8c3c843748daaa0aa75aef54

Tarafından sağlanan çözüm Karl geri dönüş X:

$ diff -u <(git log --pretty=oneline branch_A) \
          <(git log --pretty=oneline master) | \
       tail -1 | cut -c 2-42
7a1c939ec325515acfccb79040b2e4e1c3e7bbe5

Senaryo

mkdir $1
cd $1
git init
git commit --allow-empty -m "X - Work in branch master"
git commit --allow-empty -m "A - Work in branch master"
git branch branch_A
git tag branch_A_tag     -m "Tag branch point of branch_A"
git commit --allow-empty -m "B - Work in branch master"
git checkout branch_A
git commit --allow-empty -m "G - Work in branch_A"
git checkout master
git merge branch_A       -m "C - Merge branch_A into branch master"
git checkout branch_A
git commit --allow-empty -m "H - Work in branch_A"
git merge master         -m "I - Merge master into branch_A"
git checkout master
git commit --allow-empty -m "D - Work in branch master"
git merge branch_A       -m "F - Merge branch_A into branch master"
git checkout branch_A
git commit --allow-empty -m "J - Work in branch_A branch"

Git sürümü bu konuda çok fark yapar, ancak:

$ git --version
git version 1.7.1

Bana örnek havuzu yazmanın daha kompakt bir yolunu gösterdiği için Charles Bailey'ye teşekkürler .


2
Karl çözüm düzeltme kolaydır: diff -u <(git rev-list branch_A) <(git rev-list master) | tail -2 | head -1. Repo oluşturmak için talimat verdiğiniz için teşekkür ederiz :)
FelipeC 23:12

Sanırım "Karl tarafından sağlanan çözümün temizlenmiş varyasyonu X döndürüyor" demek istiyorsun. Orijinal iyi çalıştı sadece çirkin :-)
Karl

Hayır, orijinaliniz iyi çalışmıyor. Kabul edilirse, varyasyon daha da kötü çalışır. Ancak --topo-order seçeneğini eklemek sürümünüzü işler hale getirir :)
FelipeC

@felipec - Charles Bailey'nin cevabı hakkındaki son yorumuma bakın . Ne yazık ki sohbetimiz (ve dolayısıyla eski yorumların tümü) artık silindi. Zamanı aldığımda cevabımı güncellemeye çalışacağım.
Mark Booth

İlginç. Bir nevi varsayılan olarak topolojik olduğunu varsaymıştım. Aptal beni :-)
Karl

10

Genel olarak, bu mümkün değildir. Bir şube geçmişinde, adlandırılmış bir dalın dallanmasından önceki bir dal ve birleştirme ve adlandırılmış iki dalın bir ara dalı aynı görünür.

Git'te dallar, tarihin bölümlerinin ipuçlarının sadece geçerli adlarıdır. Gerçekten güçlü bir kimlikleri yok.

İki komisyonun birleşme üssü (Greg Hewgill'in cevabına bakınız) genellikle çok daha yararlı olduğundan, iki şubenin paylaştığı en son taahhüdü verir.

Bir taahhüdün ebeveynlerinin sırasına dayanan bir çözüm, bir dalın dalın tarihinin bir noktasında tam olarak entegre olduğu durumlarda işe yaramaz.

git commit --allow-empty -m root # actual branch commit
git checkout -b branch_A
git commit --allow-empty -m  "branch_A commit"
git checkout master
git commit --allow-empty -m "More work on master"
git merge -m "Merge branch_A into master" branch_A # identified as branch point
git checkout branch_A
git merge --ff-only master
git commit --allow-empty -m "More work on branch_A"
git checkout master
git commit --allow-empty -m "More work on master"

Bu teknik ayrıca, ebeveynler ters çevrilmiş olarak bir entegrasyon birleştirmesi yapıldıysa da düşer (örn., Master'a test birleştirmesi gerçekleştirmek için geçici bir dal kullanıldı ve daha sonra geliştirmek için özellik dalına hızlı bir şekilde iletildi).

git commit --allow-empty -m root # actual branch point
git checkout -b branch_A
git commit --allow-empty -m  "branch_A commit"
git checkout master
git commit --allow-empty -m "More work on master"
git merge -m "Merge branch_A into master" branch_A # identified as branch point
git checkout branch_A
git commit --allow-empty -m "More work on branch_A"

git checkout -b tmp-branch master
git merge -m "Merge branch_A into tmp-branch (master copy)" branch_A
git checkout branch_A
git merge --ff-only tmp-branch
git branch -d tmp-branch

git checkout master
git commit --allow-empty -m "More work on master"


3
Teşekkürler Charles, beni ikna ettiniz, eğer şubenin başlangıçta saptığı noktayı bilmek istersem , onu etiketlemem gerekecek. Keşke adlandırılmış şubelere giteşdeğer olmasını diliyorum, hguzun ömürlü bakım branşlarını yönetmeyi çok daha kolay hale getirir .
Mark Booth

1
"Git'te, dallar sadece tarih bölümlerinin ipuçlarının şu andaki isimleri. Gerçekten güçlü bir kimliğe sahip değiller" Bu korkunç bir şey ve Git dallarını daha iyi anlamam gerektiğine ikna etti - teşekkürler (+ 1)
Dumbledad

Bir dal geçmişinde, adlandırılmış bir dalın dallanmasından önceki bir dal ve birleştirme ve adlandırılmış iki dalın bir ara dalı aynı görünür. Evet. +1.
user1071847

5

Gibi bir şeye ne dersin

git log --pretty=oneline master > 1
git log --pretty=oneline branch_A > 2

git rev-parse `diff 1 2 | tail -1 | cut -c 3-42`^

Bu çalışıyor. Bu gerçekten hantal ama aslında bu işi yapıyor gibi görünen tek şey.
GaryO

1
Git takma adı eşdeğeri: diverges = !bash -c 'git rev-parse $(diff <(git log --pretty=oneline ${1}) <(git log --pretty=oneline ${2}) | tail -1 | cut -c 3-42)^'(geçici dosya olmadan)
conny

@conny: Oh, vay - <(foo) sözdizimini hiç görmemiştim ... bu inanılmaz faydalı, teşekkürler! (
Zsh'da

bu bana ortak atadan ziyade dalda ilk taahhüdü veriyor gibi görünüyor. (yani orijinal sorudaki grafik Gyerine, verir A.) Sanırım şu anda göndereceğim bir cevap buldum.
Lindes

'Git log --pretty = oneline' yerine sadece 'git rev-list' yapabilirsiniz, o zaman kesimi de atlayabilirsiniz, üstelik bu, ebeveynin ıraksama noktasının taahhütünü verir, sadece kuyruk -2 | kafa 1. Yani:diff -u <(git rev-list branch_A) <(git rev-list master) | tail -2 | head -1
FelipeC

5

Tabii ki bir şey eksik, ama IMO, yukarıdaki tüm sorunlara neden oluyor çünkü biz her zaman geçmişte geri gidiş şube noktasını bulmaya çalışıyoruz ve bu mevcut birleştirme kombinasyonları nedeniyle her türlü soruna neden oluyor.

Bunun yerine, her iki dalın da çok fazla tarihi paylaştığı gerçeğine dayanarak farklı bir yaklaşım izledim, dallanma öncesi tam olarak tüm tarih% 100 aynı, bu yüzden geri dönmek yerine teklifim ilerlemekle ilgili (1'den taahhüt), her iki dalda da ilk farkı arıyor. Dallanma noktası, basitçe, bulunan ilk farkın üstü olacaktır.

Uygulamada:

#!/bin/bash
diff <( git rev-list "${1:-master}" --reverse --topo-order ) \
     <( git rev-list "${2:-HEAD}" --reverse --topo-order) \
--unified=1 | sed -ne 's/^ //p' | head -1

Ve tüm olağan davalarımı çözüyor. Tabii ki sınırlanmamış olanlar var ama ... ciao :-)


diff <(git rev-list "$ {1: -master}" --first-parent) <(git rev-list "$ {2: -HEAD}" --first-parent) -U1 | kuyruk -1
Alexander Bird

daha hızlı buldum (2-100x):comm --nocheck-order -1 -2 <(git rev-list --reverse --topo-order topic) <(git rev-list --reverse --topo-order master) | head -1
Andrei Neculau


4

Birçok araştırma ve tartışmadan sonra, her durumda işe yarayacak sihirli bir kurşun olmadığı, en azından Git'in mevcut sürümünde olmadığı açıktır.

Bu yüzden taildal kavramını ekleyen birkaç yama yazdım . Bir dal her oluşturulduğunda, orijinal noktaya bir işaretçi de oluşturulur, tailref. Bu referans, şubenin her basışında güncellenir.

Devel şubesinin dallanma noktasını bulmak için tek yapmanız gereken kullanmaktır devel@{tail}, hepsi bu.

https://github.com/felipec/git/commits/fc/tail


1
Tek kararlı çözüm olabilir. Bunun git'e girip giremeyeceğini gördün mü? Çekme isteği görmedim.
Alexander Klimetschek

@AlexanderKlimetschek Yamaları göndermedim ve bunların kabul edileceğini sanmıyorum. Ancak, farklı bir yöntem denedim: çok benzer bir şey yapan bir "güncelleme-şube" kanca. Bu şekilde Git varsayılan olarak hiçbir şey yapmaz, ancak çağrının kuyruk dalını güncellemesini sağlayabilirsiniz. Yine de devel @ {tail} 'e sahip olmazsınız, ancak bunun yerine kuyruk / devel kullanmak o kadar da kötü olmaz.
FelipeC

3

İşte önceki cevabımın önceki cevabının geliştirilmiş bir versiyonu . Şubenin ilk nerede yaratıldığını bulmak için birleştirmelerden alınan taahhüt mesajlarına dayanır.

Burada bahsedilen tüm depolar üzerinde çalışıyor ve hatta posta listesinde ortaya çıkan bazı zor olanları ele aldım . Bunun için testler de yazdım .

find_merge ()
{
    local selection extra
    test "$2" && extra=" into $2"
    git rev-list --min-parents=2 --grep="Merge branch '$1'$extra" --topo-order ${3:---all} | tail -1
}

branch_point ()
{
    local first_merge second_merge merge
    first_merge=$(find_merge $1 "" "$1 $2")
    second_merge=$(find_merge $2 $1 $first_merge)
    merge=${second_merge:-$first_merge}

    if [ "$merge" ]; then
        git merge-base $merge^1 $merge^2
    else
        git merge-base $1 $2
    fi
}

3

Aşağıdaki komut, A Komitesinin SHA1'ini gösterecektir.

git merge-base --fork-point A


Ebeveyn ve çocuk şubeleri arasında ara birleşme varsa bu alışkanlık olmaz.
nawfal

2

İle biraz neşe duyuyorum

git rev-list branch...master

Aldığınız son satır daldaki ilk taahhüttür, bu yüzden bunun üstünü almak meselesidir. Yani

git rev-list -1 `git rev-list branch...master | tail -1`^

Benim için çalışıyor gibi görünüyor ve diffs ve benzeri gerekmez (bu diff sürümüne sahip olmadığımız için yararlıdır)

Düzeltme: Ana daldaysanız bu işe yaramaz, ancak bunu bir komut dosyasında yapıyorum, bu yüzden daha az sorun var


2

Dallanma noktasından taahhütleri bulmak için bunu kullanabilirsiniz.

git log --ancestry-path master..topicbranch

Bu komut verilen örnekte benim için çalışmıyor. Lütfen taahhüt aralığı için parametre olarak ne sağlarsınız?
Jesper Rønn-Jensen

2

Bazen etkili bir şekilde imkansızdır (ek veriye sahip olmak için şanslı olabileceğiniz bazı istisnalar hariç) ve buradaki çözümler işe yaramaz.

Git ref geçmişini (şubeleri içeren) korumaz. Sadece her dal için geçerli pozisyonu (kafa) saklar. Bu, git'te zaman içinde bazı şube geçmişini kaybedebileceğiniz anlamına gelir. Örneğin, ne zaman dallıyorsanız, hangi dalın orijinal olduğu hemen kaybolur. Bir dalın yaptığı tek şey:

git checkout branch1    # refs/branch1 -> commit1
git checkout -b branch2 # branch2 -> commit1

İlk taahhüdün şube olduğunu varsayabilirsiniz. Durum böyle olma eğilimindedir, ancak her zaman böyle değildir. Yukarıdaki operasyondan sonra ilk olarak her iki şubeye geçmenizi engelleyen hiçbir şey yoktur. Ayrıca, git zaman damgalarının güvenilir olduğu garanti edilmez. Her ikisine de, yapısal olarak gerçekten dal haline gelene kadar değil.

Diyagramlarda sayıları kavramsal olarak taahhüt etme eğilimindeyken, git işlenen ağaç dalları olduğunda git'in gerçek kararlı bir sekans kavramı yoktur. Bu durumda sayıların (sıralama sırasını) zaman damgası ile belirlendiğini varsayabilirsiniz (tüm zaman damgalarını aynı olarak ayarladığınızda bir git kullanıcı arabiriminin işleri nasıl ele aldığını görmek eğlenceli olabilir).

İnsan kavramsal olarak şunu bekler:

After branch:
       C1 (B1)
      /
    -
      \
       C1 (B2)
After first commit:
       C1 (B1)
      /
    - 
      \
       C1 - C2 (B2)

Aslında elde ettiğiniz budur:

After branch:
    - C1 (B1) (B2)
After first commit (human):
    - C1 (B1)
        \
         C2 (B2)
After first commit (real):
    - C1 (B1) - C2 (B2)

B1'in orijinal dal olduğunu varsayarsınız, ancak bu sadece ölü bir dal olabilir (birisi ödeme yaptı -b ama asla taahhütte bulunmadı). Git içinde meşru bir şube yapısı elde etmeyi taahhüt edene kadar:

Either:
      / - C2 (B1)
    -- C1
      \ - C3 (B2)
Or:
      / - C3 (B1)
    -- C1
      \ - C2 (B2)

C1'in C2 ve C3'ten önce geldiğini her zaman bilirsiniz, ancak C2'nin C3 veya C3'ün C2'den önce gelip gelmediğini asla güvenilir bir şekilde bilemezsiniz (çünkü iş istasyonunuzdaki zamanı örneğin herhangi bir şeye ayarlayabilirsiniz). B1 ve B2 de yanıltıcıdır, çünkü hangi şubenin ilk geldiğini bilemezsiniz. Birçok durumda çok iyi ve genellikle doğru bir tahmin yapabilirsiniz. Biraz yarış pisti gibi. Genelde arabalarla eşit olan her şey, o zaman arkadan bir kucağa gelen bir arabanın arkadan bir tur başlattığını varsayabilirsiniz. Ayrıca çok güvenilir sözleşmelerimiz var, örneğin usta, neredeyse her zaman en uzun yaşam dallarını temsil edecek, ancak ne yazık ki bunun bile olmadığı durumlar gördüm.

Burada verilen örnek, tarihi koruyan bir örnektir:

Human:
    - X - A - B - C - D - F (B1)
           \     / \     /
            G - H ----- I - J (B2)
Real:
            B ----- C - D - F (B1)
           /       / \     /
    - X - A       /   \   /
           \     /     \ /
            G - H ----- I - J (B2)

Burada gerçek de yanıltıcıdır çünkü insanlar olarak onu soldan sağa, kökten yaprağa okuruz (ref). Git bunu yapmaz. Yaptığımız (A-> B) başımızdaki git git (A <-B veya B-> A). Ref'den köke doğru okur. Referanslar herhangi bir yerde olabilir, ancak en azından aktif dallar için yaprak olma eğilimindedir. Ref, bir taahhüdü işaret eder ve taahhütler, çocuklarına değil, ebeveynlerine / çocuklarına benzer bir şey içerir. Bir taahhüt bir birleştirme taahhüdü olduğunda birden fazla ebeveyni olacaktır. İlk ebeveyn her zaman birleştirilen orijinal taahhüttür. Diğer ebeveynler her zaman orijinal taahhütte birleştirilen taahhütlerdir.

Paths:
    F->(D->(C->(B->(A->X)),(H->(G->(A->X))))),(I->(H->(G->(A->X))),(C->(B->(A->X)),(H->(G->(A->X)))))
    J->(I->(H->(G->(A->X))),(C->(B->(A->X)),(H->(G->(A->X)))))

Bu çok etkili bir gösterim değil, git'in her ref'den (B1 ve B2) alabileceği tüm yolların bir ifadesidir.

Git'in dahili depolama birimi daha çok benzer (bir ebeveyn olarak A iki kez görünmez):

    F->D,I | D->C | C->B,H | B->A | A->X | J->I | I->H,C | H->G | G->A

Bir ham git komutunu dökerseniz, sıfır veya daha fazla üst alan görürsünüz. Sıfır varsa, bu hiçbir üst öğe ve kesinleştirme bir kök demektir (aslında birden fazla kökünüz olabilir). Bir tane varsa, bu bir birleşme olmadığı anlamına gelir ve bu bir kök taahhüdü değildir. Birden fazla olması, taahhüdün bir birleştirmenin sonucu olduğu ve ilkinden sonraki tüm ebeveynlerin birleştirme taahhütleri olduğu anlamına gelir.

Paths simplified:
    F->(D->C),I | J->I | I->H,C | C->(B->A),H | H->(G->A) | A->X
Paths first parents only:
    F->(D->(C->(B->(A->X)))) | F->D->C->B->A->X
    J->(I->(H->(G->(A->X))) | J->I->H->G->A->X
Or:
    F->D->C | J->I | I->H | C->B->A | H->G->A | A->X
Paths first parents only simplified:
    F->D->C->B->A | J->I->->G->A | A->X
Topological:
    - X - A - B - C - D - F (B1)
           \
            G - H - I - J (B2)

Her ikisi de A'ya çarptığında, zincirleri aynı olacaktır, bundan önce zincirleri tamamen farklı olacaktır. Diğer iki taahhüdün ortak ilk taahhüdü ortak atadır ve oradan ayrılırlar. Burada taahhüt, şube ve ref terimleri arasında bazı karışıklıklar olabilir. Aslında bir taahhüdü birleştirebilirsiniz. Birleşmenin gerçekten yaptığı budur. Bir ref sadece bir noktaya işaret eder ve bir şube .git / refs / heads klasöründeki bir ref'den başka bir şey değildir, klasör konumu, ref'nin etiket gibi başka bir şeyden ziyade bir dal olduğunu belirleyen şeydir.

Tarihi kaybettiğiniz yer, birleşmenin koşullara bağlı olarak iki şeyden birini yapmasıdır.

Düşünmek:

      / - B (B1)
    - A
      \ - C (B2)

Bu durumda, her iki yönde birleştirme, mevcut teslim alınan dal tarafından işaret edilen taahhüt ve ikinci ebeveyn ile mevcut dalınıza birleştirdiğiniz dalın ucundaki taahhüt olarak yeni ana taahhüt oluşturacaktır. Ortak atalarından bu yana birleştirilmesi gereken her iki dalda da değişiklikler olduğu için yeni bir taahhüt yaratmalıdır.

      / - B - D (B1)
    - A      /
      \ --- C (B2)

Bu noktada D (B1) artık her iki daldan da (kendisi ve B2) her iki değişiklik kümesine sahiptir. Ancak ikinci dalın B1'den değişikliği yok. B1'den B2'ye değişiklikleri senkronize olacak şekilde birleştirirseniz, şuna benzer bir şey bekleyebilirsiniz (git birleştirme işlemini ancak --no-ff ile böyle yapmaya zorlayabilirsiniz):

Expected:
      / - B - D (B1)
    - A      / \
      \ --- C - E (B2)
Reality:
      / - B - D (B1) (B2)
    - A      /
      \ --- C

B1'in ek taahhütleri olsa bile bunu elde edersiniz. B2'de B1'in sahip olmadığı değişiklikler olmadığı sürece, iki şube birleştirilecek. Sadece bir dalın bir değişiklik setine sahip olduğu bir rebazın aksine, bir daldan diğerinin üzerine bir daldan bir değişiklik kümesi uygulamak zorunda olmadığı bir rebase (rebases yemek veya doğrusallaştırma geçmişi) gibi bir hızlı ileri yapar.

From:
      / - B - D - E (B1)
    - A      /
      \ --- C (B2)
To:
      / - B - D - E (B1) (B2)
    - A      /
      \ --- C

B1 üzerinde çalışmayı durdurursanız, uzun vadede tarihi korumak için işler büyük ölçüde iyidir. Sadece B1 (master olabilir) tipik olarak ilerler, böylece B2'nin B2'nin tarihindeki B2 konumu, B1 ile birleştirildiği noktayı başarıyla temsil eder. Git'in B'den dalına gitmenizi beklediği şey budur, o zaman A'yı B birikiminde istediğiniz kadar biriktirebilirsiniz, ancak B'yi tekrar A ile birleştirdiğinizde, B ve daha fazla çalışmanız beklenmez. . Çalıştığınız şubeye hızlıca bir araya getirdikten sonra şubeniz üzerinde çalışmaya devam ediyorsanız, her seferinde B'nin önceki geçmişini silersiniz. Kaynağa hızlı bir şekilde ilerledikten sonra şubeye taahhüt edildikten sonra her seferinde gerçekten yeni bir şube oluşturuyorsunuz.

         0   1   2   3   4 (B1)
        /-\ /-\ /-\ /-\ /
    ----   -   -   -   -
        \-/ \-/ \-/ \-/ \
         5   6   7   8   9 (B2)

1 ila 3 ve 5 ila 8, ya 4 ya da 9 tarihini takip ederseniz ortaya çıkan yapısal dallardır. Git'te bu adlandırılmamış ve referanslandırılmamış yapısal dallardan hangisinin adı verilen ve referans dallara ait olduğunu bilmenin bir yolu yoktur. yapının sonu. Bu çizimden 0 ila 4'ün B1'e ve 4 ila 9'un B2'ye ait olduğunu, ancak 4 ve 9'un dışında hangi dalın hangi dala ait olduğunu bilemediğini varsayabilirsiniz, bunu sadece yanılsaması. 0, B2'ye ve 5, B1'e ait olabilir. Bu durumda, yapısal dalların her birine ait dal adı verilen 16 farklı olasılık vardır.

Bu soruna geçici bir çözüm bulmak için birkaç git stratejileri vardır. Git birleştirmeyi hiçbir zaman hızlı ileri sarmaya zorlamayabilir ve her zaman bir birleştirme dalı oluşturabilirsiniz. Şube geçmişini korumanın korkunç bir yolu, seçtiğiniz bazı kurallara göre etiketler ve / veya şubelerdir (etiketler gerçekten önerilir). Gerçekten bir araya geldiğiniz şubede boş bir işlem önermem. Çok yaygın bir kural, şubenizi gerçekten kapatmak istediğinize kadar bir entegrasyon dalıyla birleşmektir. Bu, insanların şube sahibi olma noktasında çalıştığınız gibi uymaya çalışmaları gereken bir uygulamadır. Ancak gerçek dünyada ideal her zaman pratik değildir, yani doğru olanı yapmak her durum için uygun değildir. Eğer sen


"Git ref geçmişini korumuyor" Var, ancak varsayılan olarak değil geniş bir süre için değil. Bakınız man git-reflogve tarihlerle ilgili bölüm: "master@{one.week.ago}," kaptanın bu yerel depoda bir hafta öncesine işaret ettiği "anlamına gelir". Veya üzerine tartışma <refname>@{<date>}içinde man gitrevisions. Ve core.reflogExpireiçeri man git-config.
Patrick Mevzek

2

Sorunun tam bir çözümü değil, ancak uzun ömürlü bir şubem olduğunda kullandığım yaklaşımı belirtmeye değer olduğunu düşündüm:

Aynı zamanda şubeyi oluşturduğumda, aynı adda ancak sonekle birlikte bir etiket oluşturuyorum -init, örneğin feature-branchve feature-branch-init.

(Bunun cevaplanması çok zor bir soru!)


1
Ne zaman ve nerede yaratıldığı nosyonu olmadan bir "şube" konsepti tasarlamanın akıllara durgunluk veren aptallığı göz önüne alındığında ... artı önerilen diğer çözümlerin muazzam komplikasyonları - bu kadar akıllıca daha akıllıca çalışmaya çalışan insanlar tarafından Bence çözümünüzü tercih ederim. Sadece bir şube oluşturduğunuzda bunu yapmak için UNUTMAYIN gereksinimini karşılar - git kullanıcılarının çok sık yaptığı bir şey. Buna ek olarak - bir yerde 'etiketin' ağır 'olma cezası olduğunu okudum. Yine de sanırım yapacağımı düşünüyorum.
Motti Shneor

1

Sadece dallanma noktasını görmeyi kolaylaştırmanın basit bir yolu git log --graphseçeneği kullanmaktır --first-parent.

Örneğin, almak repo dan kabul cevap :

$ git log --all --oneline --decorate --graph

*   a9546a2 (HEAD -> master, origin/master, origin/HEAD) merge from topic back to master
|\  
| *   648ca35 (origin/topic) merging master onto topic
| |\  
| * | 132ee2a first commit on topic branch
* | | e7c863d commit on master after master was merged to topic
| |/  
|/|   
* | 37ad159 post-branch commit on master
|/  
* 6aafd7f second commit on master before branching
* 4112403 initial commit on master

Şimdi ekle --first-parent:

$ git log --all --oneline --decorate --graph --first-parent

* a9546a2 (HEAD -> master, origin/master, origin/HEAD) merge from topic back to master
| * 648ca35 (origin/topic) merging master onto topic
| * 132ee2a first commit on topic branch
* | e7c863d commit on master after master was merged to topic
* | 37ad159 post-branch commit on master
|/  
* 6aafd7f second commit on master before branching
* 4112403 initial commit on master

Bu daha kolay!

Reponun çok fazla şubesi varsa, karşılaştırmak yerine karşılaştırdığınız 2 dalı belirtmek isteyeceğinizi unutmayın --all:

$ git log --decorate --oneline --graph --first-parent master origin/topic

0

Sorun , bir taraftaki her iki dal ile en erken arasındaki en yeni, tek taahhütlü kesimi bulmak gibi görünüyor ortak ata (muhtemelen repo'nun ilk taahhüdü) . Bu, "dallanma" noktasının ne olduğuyla ilgili sezgilerimle eşleşiyor.

Bunu akılda tutarak, normal git kabuk komutlarıyla hesaplamak hiç de kolay değildir, çünkü git rev-list- en güçlü aracımız - bir taahhüdün ulaşıldığı yolu kısıtlamamıza izin vermez . En yakın git rev-list --boundary, bize "yolumuzu engelledi" tüm taahhütlerin bir dizi verebilir. (Not:git rev-list --ancestry-path ilginç ama burada nasıl kullanışlı hale getireceğimi bilmiyorum.)

İşte komut dosyası: https://gist.github.com/abortz/d464c88923c520b79e3d . Nispeten basittir, ancak bir döngü nedeniyle bir özü garanti etmek için yeterince karmaşıktır.

Burada önerilen diğer birçok çözümün basit bir nedenden ötürü her durumda çalışamayacağını unutmayın: git rev-list --first-parent tarihin doğrusallaştırılmasında güvenilir değildir, çünkü her iki sıralamayla da birleşmeler olabilir.

git rev-list --topo-orderÖte yandan, topografik sırayla yürüyüş taahhütleri için çok yararlıdır , ancak diffs yapmak kırılgandır: belirli bir grafik için birden fazla olası topografik sıralama vardır, bu nedenle siparişlerin belirli bir kararlılığına bağlısınız. Bununla birlikte, strongk7'nin çözümü muhtemelen çoğu zaman iyi çalışıyor. Ancak, repo tarihinin tamamını yürümek zorunda kalmanın sonucu olarak benimki daha yavaş ... iki kez. :-)


0

Aşağıdaki kopya svn log eşdeğerlerini uygular - kopya üzerinde dur ve dalın kökenini bulmak için de kullanılabilir.

Yaklaşmak

  1. Tüm şubelere yönelin
  2. hedef şube için mergeBase toplamak
  3. git.log ve yineleme
  4. MergeBase listesinde görünen ilk işlemde dur

Bütün nehirler denize koşar gibi, tüm dallar ustalaşır ve bu nedenle görünüşte ilgisiz dallar arasında birleştirme tabanı buluruz. Şube başlığından atalardan geri adım attığımızda, ilk potansiyel birleştirme tabanında durabiliriz, çünkü teoride bu dalın başlangıç ​​noktası olmalıdır.

notlar

  • Kardeş ve kuzen dallarının birbirleriyle birleştiği bu yaklaşımı denemedim.
  • Daha iyi bir çözüm olması gerektiğini biliyorum.

ayrıntılar: https://stackoverflow.com/a/35353202/9950


-1

Master'dan erişilemeyen branch_a içindeki en eski komutu döndürmek için aşağıdaki komutu kullanabilirsiniz:

git rev-list branch_a ^master | tail -1

Belki ek bir sağlamlık denetimi ile bu ana taahhüt olduğunu olduğunu ustadan aslında ulaşılabilir ...


1
Bu işe yaramıyor. Branch_a bir kez master ile birleştirilir ve sonra devam ederse, bu birleştirme işlemindeki taahhütler master'ın bir parçası olarak kabul edilir, bu nedenle ^ master'da görünmezler.
FelipeC

-2

Hangi dalın oluşturulduğunu ve dalın tam olarak hangi dalın işaret ettiğini tam olarak saptamak için A dalının yeniden düzenlenmesini inceleyebilirsiniz. Refloglar hazır .git/logs.


2
Bunun genel olarak işe yaradığını düşünmüyorum çünkü reflog budanabilir. Ve (?) Reflekslerinin de itildiğini sanmıyorum, bu yüzden bu sadece tek bir repo durumunda işe yarayacaktı.
GaryO

-2

Burada bahsettiğim tüm köşe vakalarıyla ilgilenen bir yol bulduğuma inanıyorum:

branch=branch_A
merge=$(git rev-list --min-parents=2 --grep="Merge.*$branch" --all | tail -1)
git merge-base $merge^1 $merge^2

Charles Bailey, ataların sırasına dayanan çözümlerin sadece sınırlı bir değere sahip olması konusunda oldukça haklıdır; günün sonunda "bu taahhüt X dalından geldi" nin bir tür kaydına ihtiyacınız var, ancak bu kayıt zaten var; varsayılan olarak 'git merge', 'branch_A' dalını master'a birleştir 'gibi bir tamamlama mesajı kullanır. "master" olan üst öğe (taahhüt ^ 1).

Bu bilgilerle donanarak, 'branch_A' nın ilk birleşimini ('branch_A' gerçekten ortaya çıktığında) bulabilir ve şube noktası olan birleştirme tabanını bulabilirsiniz :)

Mark Booth ve Charles Bailey depolarıyla denedim ve çözüm çalışmaları; nasıl yapamadı? Bunun işe yaramayacağı tek yol, şube bilgilerinin gerçekten kaybolması için birleştirme için varsayılan tamamlama iletisini el ile değiştirmiş olmanızdır.

Yararlılık için:

[alias]
    branch-point = !sh -c 'merge=$(git rev-list --min-parents=2 --grep="Merge.*$1" --all | tail -1) && git merge-base $merge^1 $merge^2'

O zaman yapabilirsiniz ' git branch-point branch_A'.

Zevk almak ;)


4
Birleştirme iletilerine güvenmek, ana düzen hakkındaki varsayımlardan daha kırılgandır. Bu sadece varsayımsal bir durum değil; Sık sık kullanmak git merge -mdemek neyi Daha doğrusu bir potentionally geçici şube adına daha birleştirildi ettik (örneğin "özelliği xyz Refactor içine birleştirme ana hat değişiklikleri"). Örneğimde daha az yardımcı olduğumu varsayalım -m? Sorun genel olarak çözülemez, çünkü aynı geçmişi bir veya iki geçici dalla yapabilirim ve farkı anlatmanın bir yolu yoktur.
CB Bailey

1
@CharlesBailey Bu senin sorunun. Bu satırları kayıt mesajından kaldırmamalısınız, mesajın geri kalanını orijinal mesajın altına eklemelisiniz . Günümüzde 'git merge' istediğinizi eklemeniz için otomatik olarak bir editör açar ve git'in eski sürümlerinde 'git merge --edit' yapabilirsiniz. Her iki durumda da, gerçekten istediğin buysa, her bir işleme bir "Taahhüt üzerinde 'foo'" eklemek için bir taahhüt kancası kullanabilirsiniz. Ancak, bu çözüm çoğu insan için işe yarar .
FelipeC

2
Benim için çalışmadı. Branch_A zaten çok sayıda birleşimi olan efendiden çatallandı. Bu mantık, branch_A'nın oluşturulduğu kesin kesin karmayı vermedi.
Venkat Kotra
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.