2010-10-28 21 views
50

git altında bir projem var. Bir gün tüm proje dosyalarını geçerli dizinden proje kapsamında foo/bar/'a taşıdım. git mv kullanarak yaptım. Daha sonra bazı dosyalar ekledim ve halihazırda var olan dosyalarda bazı değişiklikler yaptım.Geçmişi nasıl yeniden yazabilirim, böylece zaten taşıdığımlar dışındaki tüm dosyalar bir alt dizinde mi?

Sonuç olarak, şimdi foo/bar/file.c geçmişine baktığımda, yalnızca dosyayı taşıdıktan sonra yaptığım değişiklikleri görebilirim.

Çeşitli yollarla (altdizin filtresiyle, vb. filter-branch) düzeltmeye çalıştım ama hiçbir şey yardımcı olmadı, bu yüzden burada oldukça yığılmışım. Bana verebileceğin herhangi bir yardımı takdir edeceğim. Teşekkürler! dosyalarla tarihi yeniden yazmak için

cevap

85

taşındı:

tüm dosyaları her zaman dizine foo/bar olmuştur gerçi, o zaman biraz ameliyatı yapmak gerekir olarak projenin geçmişi görünmek istiyorsanız. yerde foo/bar yok ki kaydedilmesini yeniden yazmak için "ağaç filtresi" ile git filter-branch kullanın, yarattığı tüm dosyalar kendisine taşınır:

tüm dosyalar sanki
git filter-branch --prune-empty --tree-filter ' 
if [ ! -e foo/bar ]; then 
    mkdir -p foo/bar 
    git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files foo/bar 
fi' 

Şimdi geçmişi kaydedilmez her zamanfoo/bar adresinde bulunmaktadır. Sadece taşınmış ya geçmişte bir noktada yeniden adlandırıldı bir dosyanın geçmişini görmek istiyorsanız

, ardından özet için --follow seçeneğini kullanın:

bir hareket dosyanın geçmişini görmek için git log:

git log --follow foo/bar/file.c 
+1

@Alexander: Bir tek çizgiyi (tek tırnaktaki her şey) gerçek bir komut dosyasında, bir bash shebang çizgisiyle koymayı deneyebilirsiniz. Sanırım “filtre-şubesi” muhtemelen bunu “sh” değil, “bash” olarak çalıştırmaya çalışıyor. – Cascabel

+0

Bazı ilerlemeler kaydettim. If ifadesinde çift parantez bu hataya neden görünüyor. Tek parantez daha iyi çalışır, yine de işe yaramıyor. Sorun şu ki, her şeyi foo/bar/dizinine taşımadan önce projede bazı içeriğe sahip foo adında bir dizinim vardı. Yani şimdi "foo'yu kendi başına bir alt dizine," foo/bar/foo "'ya taşıyamaz. –

+0

@Alexander: Senaryoyu buna göre ayarlaman gerekecek. Bir şey gibi: Eğer [[! -e foo/bar]]; daha sonra mkdir -p foo/bar; git ls-tree - sadece isim $ GIT_COMMIT | grep -v^foo $ | xargs -I dosyaları mv dosyaları foo/bar; fi' Hareket ettirilecek dosyalar listesinden 'foo 'filtrelemek için grep kullanır. Altında her şeyi taşıyana kadar "bar" alt dizininin hiç bulunmadığını farz ediyorum. Eğer durum böyle değilse, o zaman senaryonun içinde de bunu hesaba katmanız gerekecek. –

6

İşleri sarmak için yaptığımın kısa bir özetini burada bulabilirsiniz. benim için çalıştı komut oldu:

if [ ! -e foo/bar ]; then mkdir -p foo/bar; git ls-tree --name-only $GIT_COMMIT | grep -v ^foo$ | xargs -I files mv files foo/bar || echo ""; fi 

Sonunda eklenen yankı komut mv kesintisi durumunda bile tüm komut yayınlanmaya devam edecektir sağladı. Foo/bar/foo'nun içeriğini oynatmadı, ama bununla yaşayabilirim.

Yardım için Dan Moulding (!!!) ve Jefromi'ye çok teşekkürler.

İlgili konular