Git ile yeniden adlandırılmış dosyaların günlüklerini GERÇEKTEN nasıl gösterebilirim?


132

Git konusunda nispeten yeniyim, daha önce Subversion kullandım.

Grafiksel git ön uçlarının ve IDE eklentilerinin çoğunun, dosya yeniden adlandırıldıysa bir dosyanın geçmişini görüntüleyemeyeceğini fark ettim. Kullandığım zaman

git log --follow

komut satırında, yeniden adlar arasında günlüğün tamamını görebilirim.

Linus Torvalds'a göre --follow anahtarı "SVN noob" bir zevktir, ciddi git kullanıcıları bunu kullanmaz:

--follow, ebeveynlik veya güzel revizyon grafikleri gibi şeyler hakkında hiçbir şey bilmeyen eski SVN kullanıcılarını tatmin etmeyi amaçlayan tam bir hack'tir.

Bu tamamen temel değil, ancak "--follow" uygulamasının şu anki uygulaması, gerçekten bütünleyici bir şey olmaktan ziyade, revizyon yürüme mantığına bağlanmış gerçekten hızlı bir ön işleme şeyidir.

Kelimenin tam anlamıyla bir "SVN noob" sevinci olarak tasarlandı, "gerçek git işlevselliği" olarak değil. Buradaki fikir, büyük resimde maddeyi yeniden adlandıran (bozuk) düşünme zihniyetinden uzaklaşmanızdı.

Benim Soru : o değiştirildi, nasıl içinizden sert git kullanıcıların bir dosyanın geçmişini alabilirim? Bunu yapmanın 'gerçek' yolu nedir?


17
@ David Hall: git mv oldfile newfileYeniden adlandırma kaydedilmesine neden olmaz hiç - bu sadece bir dosya silme ve başka eklemekle aynı şey. git yalnızca, gerçeğin ardından her işlemede ağacın durumundan yeniden adlandırır ve kopyalar.
Mark Longair

20
@David Hall: Dosyayı git dışında başka bir araçla (örn. /bin/mv oldfile newfile) Yeniden adlandırırsanız , ancak daha sonra yaparsanız git add newfile; git rm oldfile, sonuçtan ayırt edilemez git mv oldfile newfile.
Mark Longair

1
Bir dosyayı yeni bir depoya taşırsanız bu ideoloji parçalanır; bu durumda tüm geçmişini taşıyamama büyük bir sorun olabilir. Elbette karmaşık bir projede bir dosya ile gerçek tarihin ne kadar çok gelebileceğinin sınırları vardır.
Roman Starkov

1
Not: git log --followGit 2.9 ile biraz iyileşir (Haziran 2016): aşağıdaki
cevabıma

1
V2.15'ten itibaren, ne --color-movedzaman kendinizle deneyler yapmak isteyebilirsiniz diff.
Michael

Yanıtlar:


71

Bence Linus noktasının arkasındaki genel itici güç - ve bunu bir tutam tuzla alın - sert git kullanıcıları bir "dosyanın" geçmişini hiç umursamıyorlar. İçeriği bir git deposuna koyarsınız çünkü içeriğin tamamı anlamlı bir geçmişe sahiptir.

Bir dosyanın yeniden adlandırılması, yollar arasında hareket eden "içeriğin" küçük bir özel durumudur. Git kullanıcısının "kazma" ile işlevsel olarak takip edebileceği dosyalar arasında hareket eden bir işleve sahip olabilirsiniz (örn. log -S).

Diğer "yol" değişiklikleri arasında dosyaların birleştirilmesi ve bölünmesi; git, hangi dosyanın yeniden adlandırıldığını ve hangisinin kopyalandığını (veya yeniden adlandırıldığını ve silindiğini) düşündüğünüzle ilgilenmez, yalnızca ağacınızın tüm içeriğini izler.

git, birçok sürüm kontrol sisteminin çok dosya merkezli olduğu yerlerde "bütün ağaç" düşüncesini teşvik eder. Git'in "dosya adları" ndan daha çok "yolları" ifade etmesinin nedeni budur.


Merhaba Charles, Cevabınız için teşekkürler. Görünüşe göre git'i SVN'yi kullandığım gibi kullanıyorum. Git'in diğer sürüm kontrol sistemlerinden çok farklı olduğunu anlasam da git'teki pek çok kavram bana tuhaf geliyor ... Muhtemelen yeni satın aldığım git kitabını bitirmeliyim.
Mike

24
Linus, "uygun" bir kullanıcı arayüzünün dosyalar arasında kod parçalarını izleyebileceğiydi ve şimdiye kadar bu tür araçlara sahip olacağımızı umuyordu. Ne yazık ki, hala bu lükse sahip değiliz ve --follow hala yararlıdır.
Michael Parker

11
Git aslında bunun dışında size bir çözüm --followsunuyor mu?
Griwes

13
"Bütün ağaç" düşüncesinin --followvarsayılan olarak geliştirildiğini iddia ediyorum . Demek istediğim, bir dosya içindeki kodun geçmişini görmek istediğimde, dosyanın yeniden adlandırılıp adlandırılmadığını gerçekten umursamıyorum, sadece yeniden adlandırmadan bağımsız olarak kodun geçmişini görmek istiyorum. Bu yüzden bence --followvarsayılan olmak mantıklı çünkü tek tek dosyalar umrumda değil; --followgenellikle oldukça önemsiz olan tek tek dosya yeniden adlarını görmezden gelmeme yardımcı oluyor.
17:41 tarihinde

2
Öyleyse ... dosya yerine "içeriği" önemsemeye karar verirsem, şu anda bu dosyada bulunan içerikle ilgili taahhütleri nasıl yazdırabilirim? Git benim için hepsini farklı dosyalarda takip etse ve tüm değişikliklerin günlüğünü raporlasa çok memnun olurum - nasıl elde edeceğimi bilmiyorum.
Ed Avis

36

Karşılaştığınız sorunun aynısı bende var. Size cevap veremeyecek olsam da, Linus'un 2005'te yazdığı bu e-postayı okuyabileceğinize inanıyorum , bu çok alakalı ve size sorunu nasıl çözeceğiniz konusunda bir ipucu verebilir:

… Yeniden adlandırmaları izlemeye çalışan herhangi bir SCM'nin, dahili nedenlerle (yani verimli deltalara izin vermek için) bunu yapmadığı sürece temelde bozulduğunu iddia ediyorum, çünkü yeniden adlar önemli değildir. Size yardımcı olmuyorlar ve zaten ilgilendiğiniz şeyler değiller .

Önemli olan "bunun nereden geldiğini" bulmak ve git mimarisi bunu gerçekten çok iyi yapıyor - oradaki her şeyden çok daha iyi. ...

Bu blog yazısında referans verildiğini buldum , bu da sizin için uygun bir çözüm bulmanız için yararlı olabilir:

Mesajda Linus, ideal bir içerik izleme sisteminin bir kod bloğunun mevcut şekle nasıl girdiğini bulmanızı nasıl sağlayabileceğini özetledi. Bir dosyadaki mevcut kod bloğundan başlar, dosyayı değiştiren kaydetmeyi bulmak için geçmişe geri dönersiniz. Ardından, ilgilendiğiniz kod bloğunun kendisi tarafından değiştirilip değiştirilmediğini görmek için kaydetme değişikliğini incelersiniz, çünkü dosyayı değiştiren bir kayıt ilgilendiğiniz kod bloğuna dokunmayabilir, ancak yalnızca diğer bazı bölümlerine dokunabilir. dosya.

Kaydetmeden önce kod bloğunun dosyada olmadığını fark ettiğinizde, işlemi daha derinlemesine incelersiniz. Aşağıdakiler dahil birçok olası durumdan biri olduğunu görebilirsiniz:

  1. Commit gerçekten kod bloğunu tanıttı. İşlemin yazarı, kaynağını araştırdığınız harika özelliğin (veya hatayı ortaya çıkaran suçlu tarafın) mucidiydi; veya
  2. Dosyada kod bloğu yoktu, ancak bunun beş özdeş kopyası farklı dosyalarda mevcuttu ve bunların tümü işlemden sonra kayboldu. Kaydetme işleminin yazarı, tek bir yardımcı işlev ekleyerek yinelenen kodu yeniden düzenledi; veya
  3. (özel bir durum olarak) İşlemden önce, ilgilendiğiniz kodun bloğunu içeren dosya mevcut değildi, ancak neredeyse aynı içeriğe sahip başka bir dosya vardı ve ilgilendiğiniz kod bloğu, o zaman dosyadaki diğer tüm içeriklerle birlikte, o dosyada mevcuttu. Taahhütten sonra gitti. İşlemenin yazarı, küçük bir değişiklik yaparken dosyayı yeniden adlandırdı.

Git'te, Linus'un nihai içerik izleme aracı henüz tam otomatik bir şekilde mevcut değil. Ancak önemli bileşenlerin çoğu zaten mevcuttur.

Lütfen bu konudaki ilerlemeniz hakkında bizi haberdar edin.


Bu makaleleri gönderdiğiniz için teşekkürler. İçerik tarihi fikrini tam olarak kavradığımı okuyana kadar! Bunu yanlış bir şekilde düşünüyordum!
DavidG

Linus'tan gelen bu e-posta harika, bunu yayınladığınız için teşekkürler.
mik01aj

Eğlenceli gerçek, Git v2.15--color-moved bu "ideal izleme sistemine" doğru bir hareket ekler . Bir dosya içinde hareket eden satırları izlediğini görmek için onunla oynuyordum, ancak yanlışlıkla tüm farktaki
Michael

2
Linus karmaşık bir durumu açıklıyor. Ancak burada basit bir durumumuz var: bir dosya yeni adlandırıldı (veya başka bir dizine taşındı). Dolayısıyla basit bir çözüm olmalı. Sorunun Subversion'ın aksine olgudan kaynaklandığını düşünüyorum, kullanıcı Git'e bir dosyanın nereden geldiğini kaydetme zamanında talimat --followveremez ve bu yanlış olabilir (örneğin, 2 dosya aynı içeriğe sahipse veya bir değişiklik varsa) dosya taşıma işlemine ek olarak).
vinc17

13

Grafiksel git ön uçlarının ve IDE eklentilerinin çoğunun, dosya yeniden adlandırıldıysa bir dosyanın geçmişini görüntüleyemeyeceğini fark ettim.

Bazı popüler Git UI araçlarının artık bunu desteklediğini bilmekten mutluluk duyacaksınız. Kullanılabilir düzinelerce Git UI aracı var, bu yüzden hepsini listelemeyeceğim, ancak örneğin:

  • SourceTree, bir dosya günlüğünü görüntülerken, sol altta "Yeniden adlandırılmış dosyaları izle" onay kutusuna sahiptir.
  • TortoiseGit, sol alttaki günlük penceresinde "yeniden adları takip et" onay kutusuna sahiptir.

Git UI araçları hakkında daha fazla bilgi:


Kaynak, bir kez yeniden adlandırırken harika çalışıyor, iki kez yeniden adlandırırken, yeniden adlandırmadan önce değişiklik ayrıntılarını kaydetme için kullanılamıyor. Hatayı
Intel

gitk, bir dosya geçmişte iki kez yeniden adlandırıldığında bile harika çalışır. Komut şu "gitk
Intel

6

Not: Git 2.9 (June2016), aşağıdakilerin "hatalı" yapısını oldukça geliştirecek git log --follow:

Bkz. Commit ca4e3ca (30 Mart 2016), SZEDER Gábor ( szeder) .
(Göre Birleştirilmiş - Junio Cı Hamano gitster- içinde 26effb8 tamamlama 2016, 13 May)

diffcore: yeniden adlandırma tespiti sırasında aynı dosyaların yineleme sırasını düzelt

İki yol ' dir/A/file' ve ' dir/B/file' aynı içeriğe sahipse ve ana dizin yeniden adlandırılmışsa, örneğin ' git mv dir other-dir', diffcoreaşağıdaki tam yeniden adları bildirir:

renamed:    dir/B/file -> other-dir/A/file
renamed:    dir/A/file -> other-dir/B/file

(burada ters çevirmeye dikkat edin: B/file -> A/fileve A/file -> B/file)

Teknik olarak yanlış olmasa da, bu sadece kullanıcı için değil, aynı zamanda yeniden adlandırma bilgisine dayalı kararlar veren git komutları için de kafa karıştırıcıdır, örneğin, yeniden adlandırmadan sonra ' git log --follow other-dir/A/file' izler ' dir/B/file'.

Bu davranış, commit v2.0.0-rc4 ~ 8 ^ 2 ~ 14'ün bir yan etkisidir ( diffcore-rename.c: tam yeniden adlar bulmayı basitleştirin, 2013-11-14): hashmap, kaynakları depolayan aynı gruptan, yani geçerli hedefle eşleşen kaynaklardan girişler döndürür LIFO sırasına göre.
Böylece yineleme önce other-dir/A/file"ve" dir/B/file'yi inceler ve aynı içerik ve temel adı bulduktan sonra tam bir yeniden ad bildirir.


2

Linux'ta, SmartGit ve GitEye'nin belirli bir dosyanın geçmişini takip ederken yeniden adlar izleyebildiğini doğruladım. Bununla birlikte, gitk ve GitEye'den farklı olarak, SmartGit ayrı bir dosya görünümü ve depo görünümü gösterir (dizin yapısını içerir ancak içinde bulunan dosyaların listesini içermez)

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.