Belirli bir dosyadaki değişiklikleri içeren bir Git dalı bulun


91

57 yerel şubem var. Birindeki belirli bir dosyada değişiklik yaptığımı biliyorum ama hangisinde olduğundan emin değilim. Hangi dalların belirli bir dosyada değişiklik içerdiğini bulmak için çalıştırabileceğim bir tür komut var mı?

Yanıtlar:


89

FILENAME için değişiklik içeren tüm dalları bulun ((kaydedilmemiş) dallanma noktasından önce olsa bile)

FILENAME="<filename>"
git log --all --format=%H $FILENAME | while read f; do git branch --contains $f; done | sort -u

Manuel olarak inceleyin:

gitk --all --date-order -- $FILENAME

FILENAME dosyasında ana olarak birleştirilmemiş tüm değişiklikleri bulun:

git for-each-ref --format="%(refname:short)" refs/heads | grep -v master | while read br; do git cherry master $br | while read x h; do if [ "`git log -n 1 --format=%H $h -- $FILENAME`" = "$h" ]; then echo $br; fi; done; done | sort -u

Bu komutta FILENAME dışında herhangi bir şeyi değiştirmem gerekir mi? 57 şube adının tümünü döndürür.
Dustin

@Dustin: 57 dalın tümü bu dosya adını içeriyorsa, 57 dalın tümü bu dosya adını içeren bir değişiklik içerir. Siz şubeyi oluşturmadan önce revizyon mevcut olsa bile, şubeler o şubede ulaşılabilen en eski revizyondan başlar (dal bazı açılardan geriye dönük olarak oluşturulmuştur). Sorununuzu daha iyi tanımlamanız gerektiğini düşünüyorum. Değişimin ne olduğunu biliyor musun? git log -Schange …Veya kullanabilir misiniz git log --grep LOGMESSAGE …(... bahsettiğim komutun geri kalanını temsil eder).
Seth Robertson

2
@Dustin: Başka bir seçenek de gitk --all -- filenameo dosyadaki tüm değişiklikleri grafiksel olarak gösterecek olan kullanmaktır . Söz konusu yürütmeyi tanımlayabilirseniz, kaydetmenin git branch --containshangi dallara taşındığını görmek için kullanabilirsiniz. Söz konusu kaydetmenin başlangıçta hangi dalda oluşturulduğunu görmek istiyorsanız , google git-what-branch, ancak hızlı ileri birleştirme işlemlerinin bu bilgileri gizleyebileceğini unutmayın.
Seth Robertson

@Seth: Kaydetme mesajını veya tam kod değişikliğini hatırlayamadım. Sadece genel bir fikrim var. Sorun şu ki, henüz master ile birleştirilmemiş, bu yüzden gitk'i kullanmak için aradığımı bulmak için her şubeyi kontrol etmem gerekiyor. "Git, dallanma noktasından bu yana FILENAME üzerinde değişiklik yapan dalları göster" diyebilseydim iyi olurdu
Dustin

1
İlk satırı daha verimli yazabilirsinizgit log --all --format='--contains %H' "$file" | xargs git branch
kojiro

53

Tum ihtiyacin olan sey

git log --all -- path/to/file/filename

Şubeyi hemen tanımak isterseniz şunları da kullanabilirsiniz:

git log --all --format=%5 -- path/to/file/filename | xargs -I{} -n 1 echo {} found in && git branch --contains {}

Ayrıca, herhangi bir yeniden adınız varsa --follow, Git log komutunu dahil etmek isteyebilirsiniz .


16
Bu, taahhütleri gösterecek, ancak hangi şubeyi sordu. --sourceOraya bir ekle ve altınsın.
Karl Bielefeldt

Teşekkürler, ancak bunun her kayıt için tüm dalları gösterdiğini sanmıyorum. Ama yardımı olur.
Adam Dymitruk

1
Doğru, ama bu özel durumda sadece birini arıyordu.
Karl Bielefeldt

asp.net yolu için btw, AppName / Controllers / XController.cs gibi bir formatta olmalıdır
Ali Karaca

8

Görünüşe göre bu, uygun bir çözümü olmayan bir sorun. Yorum yapacak kadar kredim yok, işte benim küçük katkım.

Seth Robertson'un 1. çözümü benim için işe yaradı, ancak bana yalnızca yerel şubeler verdi, bunların arasında birçok yanlış pozitifin olduğu, muhtemelen istikrarlı şubeden birleşmeler nedeniyle.

Adam Dymitruk'un 2. çözümü benim için hiç işe yaramadı. Yeni başlayanlar için --format =% 5 nedir? Git tarafından tanınmıyor, hakkında hiçbir şey bulamadım ve diğer format seçenekleriyle çalışmasını sağlayamadım.

Ancak ilk çözümü --source seçeneği ve basit bir grep ile birleştirildiğinde yararlı oldu:

git log --all --source -- <filename> | grep -o "refs/.*" | sort -u

Bu bana birkaç uzak etiket ve dal ve dosyada en son değişiklikleri yaptığım bir yerel şube veriyor. Bunun ne kadar eksiksiz olduğundan emin değilim.

@Nealmcb'nin isteğine göre GÜNCELLE , dalları en son değişikliğe göre sıralayın:

İlk olarak, grep'i "refs / Heads /.*" olarak değiştirebilirsiniz, bu size sadece yerel şubeleri verecektir. Yalnızca birkaç şube varsa, her birinin son işlemlerini şu şekilde inceleyebilirsiniz:

git log -1 <branch> -- <filename>

Daha fazla dal varsa ve bunu gerçekten otomatikleştirmek istiyorsanız, iki komutu xargs, git log formatlama ve başka bir sıralama kullanarak bu tek satırda birleştirebilirsiniz:

git log --all --source -- <filename> | grep -o "refs/heads/.*" | sort -u | xargs -I '{}' git log -1 --format=%aI%x20%S '{}' -- <filename> | sort -r

Bu, şöyle bir çıktıyla sonuçlanacaktır:

2020-05-07T15:10:59+02:00 refs/heads/branch1
2020-05-05T16:11:52+02:00 refs/heads/branch3
2020-03-27T11:45:48+00:00 refs/heads/branch2

Harika teşekkür ederim. Şimdi en son değişikliğe göre sıralamaya ne dersiniz?
nealmcb

1

Bu sorunun eski olduğunu biliyorum, ancak kendi çözümümü geliştirmeden önce ona geri dönmeye devam ettim. Bunun daha zarif olduğunu hissediyorum ve istenmeyen dalları dışarıda bırakan birleştirme tabanı filtreleri sayesinde.

#!/bin/bash

file=$1
base=${2:-master}

b=$(tput bold) # Pretty print
n=$(tput sgr0)

echo "Searching for branches with changes to $file related to the $base branch"

# We look through all the local branches using plumbing
for branch in $(git for-each-ref --format='%(refname:short)' refs/heads/); do
  # We're establishing a shared ancestor between base and branch, to only find forward changes.  
  merge_base=$(git merge-base $base $branch)
  # Check if there are any changes in a given path.
  changes=$(git diff $merge_base..$branch --stat -- $file)

  if [[ ! -z $changes ]]; then
    echo "Branch: ${b}$branch${n} | Merge Base: $merge_base"
    # Show change statistics pretty formatted
    git diff $merge_base..$branch --stat -- $file
  fi
done

YOL'a olarak git-find-changes(çalıştırılabilir izinlerle) koyarsanız - daha sonra şu şekilde çağırabilirsiniz:git find-changes /path

Örnek çıktı git find-changes app/models/

Branch: update_callbacks | Merge base: db07d23b5d9600d88ba0864aca8fe79aad14e55b
 app/models/api/callback_config.rb | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
Branch: repackaging | Merge base: 76578b9b7ee373fbe541a9e39cf93cf5ff150c73
 app/models/order.rb                 | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

Çok ilginç bir senaryo. Olumlu oy verildi. Değişiklikleri göster mi yoksa değişiklikleri bul mu?
VonC

@VonC teşekkürler, düzeltilmiş kullanım her yerde bulunmalı
Marcin Raczkowski

0

Aşağıdaki, uygun olmayan bir kaba kuvvet yöntemidir, ancak bunun işe yaramasını bekliyorum. Şu anda hangi şubede olduğunuzu değiştireceğinden, önce taahhüt edilmemiş değişiklikleri sakladığınızdan emin olun.

for branch in $(git for-each-ref --format="%(refname:short)" refs/heads); do
    git checkout $branch && git grep SOMETHING
done

1
Çünkü kullanabileceğiniz değişikliği biliyorsanızgit log -S
Seth Robertson

Hangi kabuğu varsayıyorsun? Bash?
Peter Mortensen

POSIX üzerinde çalışması gereken hiçbir esaret yok. for-each-refYine de bu shortbayrağa saygı duyduğundan emin değilim . Bununla birlikte, cevabımı görmezden gelin; diğer cevaplar daha iyi.
2018 saat
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.