Belirli bir taahhüdü içeren birleştirme taahhüdü bulun


183

Aşağıdaki geçmişi düşünün:

       c---e---g--- feature
      /         \
-a---b---d---f---h--- master

"C" komutu master ile birleştirildiğinde nasıl bulabilirim (örneğin, birleştirme komutu "h")?

Yanıtlar:


158

Örneğiniz şubenin featurehala kullanılabilir olduğunu göstermektedir .

Bu durumda haşağıdakilerin son sonucu:

git log master ^feature --ancestry-path

Şube featureartık mevcut değilse, birleştirme işlemlerini geçmiş satırında cve arasında gösterebilirsiniz master:

git log <SHA-1_for_c>..master --ancestry-path --merges

Bu ancak aynı zamanda sonra oldu tüm birleştirmeleri gösterecektir hve aralarında eve güzerinde feature.


Aşağıdaki komutların sonucunun karşılaştırılması:

git rev-list <SHA-1_for_c>..master --ancestry-path

git rev-list <SHA-1_for_c>..master --first-parent

size hortak son satır olarak SHA-1'i verecektir .

Elinizde varsa comm -1 -2, bu sonuçlarda kullanabilirsiniz . Msysgit kullanıyorsanız, karşılaştırmak için aşağıdaki perl kodunu kullanabilirsiniz:

perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/'  file1 file2

( http://www.cyberciti.biz/faq/command-to-display-lines-common-in-files/ adresinden "comp.unix.shell haber grubundaki birinden" alan perl kodu ).

Tek astar yapmak istiyorsanız işlem ikamesine bakın .


4
Comm'nuz olsa bile, "git rev-list" komutunun çıktısı sözlükbilimsel olarak sıralanmadığından kullanamazsınız. Elbette, ortak satırları aramadan önce her komutun çıktısını sıralayabilirsiniz, ancak daha sonra istenen taahhüt mutlaka son komut değildir. Bu yüzden perl komutu (belirsiz olsa da) gibi bir şeyin gerekli olduğunu düşünüyorum.
mhagger

12
Sadece bu öneriyi uygulayan git-when-merged komut dosyasını yazdım (birkaç başka özellik ile). Bkz. Github.com/mhagger/git-when-merged
mhagger

2
Bir noktada varsayalım masterile birleştirildi feature, daha sonra hemen featurebirleştirilir masterhızlı ileri alma (ucu gibi featureyerine geçer master). --first-parentYanlış ebeveynin geri dönmesine neden olur mu?
Kelvin

4
Denedim comm -1 -2ama işe yaramadı. commyalnızca sıralı satırlarda çalışır. (Perl tek astar çalışır, ben okuyamıyordum.)
Domon

2
Bu biraz geç ama insanların yerel olarak bunu sağlamadığı için insanlar yararlı bulabilirsiniz. Bu cevabın işe yaramadığını düşündüğüm bazı köşe vakaları var ( çoğu köşe vakasını ele alan stackoverflow.com/a/43716029/58678 aşağıya bakın ). Köşe vakalar şunlardır: git find-merge h master(hiçbir şey döndürmez ancak h döndürmelidir), git find-merge d master(f döndürür ancak d döndürmelidir), git find-merge c feature(e döndürür ancak g döndürmelidir).
hIpPy

133

Bunu şu adrese ekleyin ~/.gitconfig:

[alias]
    find-merge = "!sh -c 'commit=$0 && branch=${1:-HEAD} && (git rev-list $commit..$branch --ancestry-path | cat -n; git rev-list $commit..$branch --first-parent | cat -n) | sort -k2 -s | uniq -f1 -d | sort -n | tail -1 | cut -f2'"
    show-merge = "!sh -c 'merge=$(git find-merge $0 $1) && [ -n \"$merge\" ] && git show $merge'"

Sonra diğer adları şöyle kullanabilirsiniz:

# current branch
git find-merge <SHA-1>
# specify master
git find-merge <SHA-1> master

Birleştirme işleminin iletisini ve diğer ayrıntılarını görmek için git show-mergeaynı argümanlarla kullanın .

( Gauthier'in cevabına göre . Rosen Matev ve javabrett'e bir sorunu düzelttiği için teşekkür ederiz sort.)


6
Güzel! Bu en iyi bırakma çözümüdür.
N Jones

1
sort -k2 | uniq -f1 -d | sort -n | tail -1 | cut -f2Ortak son satırı doğru bulmadığına dikkat edin . İşte başarısız olduğu bir örnek.
Rosen Matev

1
@RosenMatev 16db9fef5c581ab0c56137d04ef08ef1bf82b0b7Yapıştırınızda çalıştırdığımda burada bulur , bu beklenmiyor mu? Hangi işletim sistemindesiniz?
robinst

1
@robinst, seninki doğru. "(GNU coreutils) 8.4" var ve benim için bulur29c40c3a3b33196d4e79793bd8e503a03753bad1
Rosen Matev

2
@powlo: Hiçbir şey, kolaylık sağlamak için iki yerine sadece bir komut.
robinst

28

git-get-merge , aradığınız birleştirme taahhüdünü bulur ve gösterir:

pip install git-get-merge
git get-merge <SHA-1>

Komutu bir birleştirme kadar verilen çocukları işlemek aşağıdaki içine başka dalı (muhtemelen usta) bulunur.


22

Yani, Gauthier'in gönderisini özetlemek gerekirse:

perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' <(git rev-list --ancestry-path <SHA-1_for_c>..master) <(git rev-list --first-parent <SHA-1_for_c>..master) | tail -n 1

EDIT: Bu işlem yerine " <()" kullandığından POSIX uyumlu değildir ve kabuğunuzla çalışmayabilir. İle bashya da zsholsa çalışır .


4
İnternetten kodu sık sık kopyalamıyorum / yapıştırmıyorum, ancak yaptığımda mükemmel çalışıyor! Düşünmeme izin verdiğin için teşekkürler Totor.
Ben

2
@ TheodoreR.Smalesef sözdizimi <()POSIX uyumlu değil. Sen kullanmak gerekir bash, zshya da bir kabuk destekleyen süreç ikame . Cevabımı buna göre düzenledim.
Ağustos'ta Totor

Benim için çalışmadı. Bence özellik branşım ustalaşmadan önce başka bir dala birleştirildi. Bu, komutlarınızın neden "Şubeyi birleştir 'feature_branch'" yerine "şubeyi birleştir" release_branch "ile sonuçlandığını açıklayabilir.
Tim Kuipers

14

Bunu yapmam gerekiyordu ve bir şekilde buldum git-when-merged(ki bu gerçekten SO sorusuna atıfta bulunuyor, ancak Michael Haggerty burada çok güzel Python betiğine bir referans eklemedi). Şimdi yaptım.


Aslında bu soruya sayfasından geldim.
Flavius

12

Gauthier'in harika cevabına dayanarak comm, listeleri karşılaştırmak için kullanmamız gerekmez . Biz son sonuca arıyorsanız bu yana --ancestry-pathda olduğu --first-parent, biz sadece eski çıkışında ikincisi için yazılması edebilirsiniz:

git rev-list <SHA>..master --ancestry-path | grep -f <(git rev-list <SHA>..master --first-parent) | tail -1

Veya çabuk ve yeniden kullanılabilir bir şey için, işte burada bir fonksiyon .bashrc:

function git-find-merge() {
  git rev-list $1..master --ancestry-path | grep -f <(git rev-list $1..master --first-parent) | tail -1
}

Bu benim için çalıştı. commgirişler sıralanmadığında çalışmadı.
hIpPy

4

Ruby kalabalığı için git-whence var . Çok kolay.

$ gem install git-whence
$ git whence 1234567
234557 Merge pull request #203 from branch/pathway

4

Yolda yerleştirdiğim bash betiğinin altında kullanıyorum ~/bin/git-find-merge. Bu dayanıyor Gauthier'in cevap ve evilstreak cevabı köşe davalarına bakacak birkaç tweaks. commgirişler sıralanmadığında atar. grep -fMükemmel çalışıyor.

Köşe dolapları:

  • Taahhüt, dalın ilk ana yolundaki birleştirme taahhüdü ise, geri gönderme taahhüdü.
  • Taahhüt, dalın ilk üst yolunda bir birleşik OLMAYAN taahhüdü ise, dalı döndürün. Bu bir ff birleşmesi veya taahhüdü sadece daldadır ve doğru taahhüdü anlamanın iyi bir yolu yoktur.
  • Taahhüt ve şube aynı ise, iade taahhüdü.

~/bin/git-find-merge senaryo:

#!/bin/bash

commit=$1
if [ -z $commit ]; then
    echo 1>&2 "fatal: commit is required"
    exit 1
fi
commit=$(git rev-parse $commit)
branch=${2-@}

# if branch points to commit (both are same), then return commit
if [ $commit == $(git rev-parse $branch) ]; then
    git log -1 $commit
    exit
fi

# if commit is a merge commit on first-parent path of branch,
# then return commit
# if commit is a NON-merge commit on first-parent path of branch,
# then return branch as it's either a ff merge or commit is only on branch
# and there is not a good way to figure out the right commit
if [[ $(git log --first-parent --pretty='%P' $commit..$branch | \
    cut -d' ' -f1 | \
    grep $commit | wc -l) -eq 1 ]]; then
    if [ $(git show -s --format="%P" $commit | wc -w) -gt 1 ]; then
        # if commit is a merge commit
        git log -1 $commit
    else
        # if commit is a NON-merge commit
        echo 1>&2 ""
        echo 1>&2 "error: returning the branch commit (ff merge or commit only on branch)"
        echo 1>&2 ""
        git log -1 $branch
    fi
    exit
fi

# 1st common commit from bottom of first-parent and ancestry-path
merge=$(grep -f \
    <(git rev-list --first-parent  $commit..$branch) \
    <(git rev-list --ancestry-path $commit..$branch) \
        | tail -1)
if [ ! -z $merge ]; then
    git log -1 $merge
    exit
fi

# merge commit not found
echo 1>&2 "fatal: no merge commit found"
exit 1

Bunu yapmama izin veren:

(master)
$ git find-merge <commit>    # to find when commit merged to current branch
$ git find-merge <branch>    # to find when branch merged to current branch
$ git find-merge <commit> pu # to find when commit merged to pu branch

Bu komut dosyası github'ımda da mevcut .


2
git log --topo-order

Ardından, taahhütten önceki ilk birleşmeyi arayın.


1

@ Robinst'in fikrinin yakut versiyonum, iki kez daha hızlı çalışır (çok eski bir taahhüt ararken önemlidir).

find-commit.rb

commit = ARGV[0]
master = ARGV[1] || 'origin/master'

unless commit
  puts "Usage: find-commit.rb commit [master-branch]"
  puts "Will show commit that merged <commit> into <master-branch>"
  exit 1
end

parents = `git rev-list #{commit}..#{master} --reverse --first-parent --merges`.split("\n")
ancestry = `git rev-list #{commit}..#{master} --reverse --ancestry-path --merges`.split("\n")
merge = (parents & ancestry)[0]

if merge
  system "git show #{merge}"
else
  puts "#{master} doesn't include #{commit}"
  exit 2
end

Sadece şu şekilde kullanabilirsiniz:

ruby find-commit.rb SHA master

0

Böyle bir şey deneyebilirsiniz. Fikir tüm birleştirme işlemlerini yinelemek ve "c" işlemine bunlardan birinden erişilip erişilemeyeceğini görmek:

$ git log --merges --format='%h' master | while read mergecommit; do
  if git log --format='%h' $mergecommit|grep -q $c; then
    echo $mergecommit;
    break
  fi
done

Bu aynı:git rev-list <SHA-1_for_c>..master --ancestry-path --merges
Eugen Konkov

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.