Geçmişi korurken tek bir dizini bir git deposundan yeni bir depoya nasıl taşıyabilirim?


110

Ayrı dizinlerde birden çok proje içeren bir git deposunu devraldım. Depoyu, her proje için bir tane olmak üzere yeni bireysel depolara bölmek ve ardından ana deponun projeleri alt modüller olarak içermesini istiyorum. Tüm bunları mümkünse münferit projelerin revizyon geçmişini korurken yapmak istiyorum.

Her proje için depoyu klonlayabilir ve diğer tüm projeleri her seferinde kaldırabilirim, ancak her yeni proje havuzunda klonlanmış geçmişe sahip olmaktan kaçınmanın daha iyi bir yolu var mı?


2
Git-submodules etiketi eklendi çünkü bu, bir deponun bir bölümünü alt modüle dönüştürmek için çok yararlıdır.
idbrii

Yanıtlar:


99

git filter-branchBir projenin geçmişini yeniden yazmak için kullanabilirsiniz . Belgelerden:

Depoyu, sanki kendi proje kökü olmuş gibi görünecek şekilde yeniden yazmak ve diğer tüm geçmişi atmak için:

git filter-branch --subdirectory-filter foodir -- --all

Deponuzun birkaç kopyasını oluşturun, ayırmak istediğiniz her alt dizin için bunu yapın ve aradığınız şeyi bulmalısınız.


1
Ya foodir'i dışlamak ve geçmişini tamamen kaldırmak istersem?
saeedgnu

1
Not: Birden fazla dizin istiyorsanız, --subdirectory-filterbirden çok kez belirtmeniz gerekecektir . EG git filter-branch --subdirectory-filter foodir --subdirectory-filter bardir, vb. --subdirectoryBirden çok dizin almaz, ancak birden çok kez belirtilebilir.
EnabrenTane

3
@Adam Geçmişini foodirorijinal projede tutmak istiyorsanız, geçmişini yeniden yazmak yerine, sadece git rm -r foodiryeterli olmalıdır (bu, çalışma ağacınızdaki kopyayı da silecektir; istemiyorsanız kullanın --cached). Bunu tarihten tamamen çıkarmak istiyorsanız (ilius'un sorusunu da yanıtlayarak), şöyle bir şey istersinizgit filter-branch --index-filter 'git rm -r --cached --ignore-unmatched foodir' -- --all
Brian Campbell

2
@ilius Üzgünüm daha önce sorunuzu kaçırdım, bir dizinin ve geçmişinin nasıl kaldırılacağına dair bir cevap için yukarıdaki cevabıma bakın.
Brian Campbell

2
@ilius Evet, bu da işe yarıyor. Büyük bir proje için --index-filterçözüm, --tree-filterdosyaları teslim alması gerekmediğinden daha hızlıdır , sadece dizini doğrudan değiştirebilir. --tree-filterBunun yerine endeks manipülasyon operasyonları ile çalışmak zorunda kalmak yerine sıradan filsystem işlemleri gibi kullanabilirsiniz, ancak kullanımı biraz daha kolay olabilir.
Brian Campbell

4

Bir klasörü yeni bir depo olarak dışa aktarmak için ihtiyacınız olan:

  1. Dışa aktarmak istediğiniz klasörün bulunduğu depoyu klonlamak için.
  2. Barındırma sağlayıcınızda GitHub olarak boş bir depo oluşturmak, dışa aktarılan klasörü depolamak için.
  3. Klonlanmış depo klasörünü açın ve şu komutu çalıştırın:

    git subtree push --prefix=YourFolderNameToExport https://github.com/YourUserName/YourNewCleanRepoName master
    

1
git subtreeCygwin paketi olarak mevcut değildir. İhtiyacınız varsa: stackoverflow.com/a/27116828/2484903
Jack Miller

2

Git'in amacı, geçmişin her kayıtta üst commit'i hashing ile somutlaştırmasıdır. İşlemleri (svn-ithalatçının çalışma şekli budur) yeni bir depoda "yeniden oynatabilir" ve yalnızca her bir alt projeyi tutabilirsiniz. Ancak bu, commit karmalarının anlamını yok eder. Eğer bununla bir sorunun yoksa öyle olsun.

Geçmişte onu klonladım ve devam ettim. Bu, işleri büyütür, ancak disk alanı ucuzdur; benim zamanım pahalı.

Ayrıca bir dizini birleştirmek için herhangi bir araç bilmiyorum. Sanırım dizinde git-log ile tüm commit'leri bulabilir ve sonra da commit'leri git-fast-export gibi bir şeyle tekrar oynatabilirsiniz.


Olumsuz olmayı hak etmediği için oy verdim - kesinlikle bu yaklaşımı takip etmezdim ama denediğini görebiliyorum
Alvin
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.