Benim durumumda, bir my-plugindepom ve bir main-projectdepom my-pluginvardı ve her zaman için pluginsalt dizininde geliştirilmiş gibi davranmak istedim main-project.
Temel olarak, my-plugindeponun tarihini yeniden yazdım, böylece tüm gelişme plugins/my-pluginalt dizinde gerçekleşti. Sonra, geliştirilmesi öyküsü eklendi my-pluginiçine main-projecttarih ve birlikte iki ağaç birleşti. plugins/my-pluginHavuzda zaten bir dizin bulunmadığından main-project, bu önemsiz bir çatışmasız birleşmeydi. Ortaya çıkan depo, her iki orijinal projeden tüm geçmişi içeriyordu ve iki kökü vardı.
TL; DR
$ cp -R my-plugin my-plugin-dirty
$ cd my-plugin-dirty
$ git filter-branch -f --tree-filter "zsh -c 'setopt extended_glob && setopt glob_dots && mkdir -p plugins/my-plugin && (mv ^(.git|plugins) plugins/my-plugin || true)'" -- --all
$ cd ../main-project
$ git checkout master
$ git remote add --fetch my-plugin ../my-plugin-dirty
$ git merge my-plugin/master --allow-unrelated-histories
$ cd ..
$ rm -rf my-plugin-dirty
Uzun versiyon
İlk olarak, my-plugindeponun bir kopyasını oluşturun , çünkü bu deponun tarihini yeniden yazacağız.
Şimdi, my-plugindeponun kök dizinine gidin , ana dalınızı kontrol edin (muhtemelen master) ve aşağıdaki komutu çalıştırın. Tabii ki, gerçek isimlerinizin yerine my-pluginve pluginsne olursa olsun.
$ git filter-branch -f --tree-filter "zsh -c 'setopt extended_glob && setopt glob_dots && mkdir -p plugins/my-plugin && (mv ^(.git|plugins) plugins/my-plugin || true)'" -- --all
Şimdi bir açıklama için. komutu, ulaşılabilir her komutta git filter-branch --tree-filter (...) HEADçalıştırır . Bunun doğrudan her bir taahhüt için depolanan veriler üzerinde çalıştığına dikkat edin, bu nedenle "çalışma dizini", "dizin", "aşamalandırma" ve benzeri kavramlar hakkında endişelenmemize gerek yoktur.(...)HEAD
filter-branchBaşarısız olan bir komut çalıştırırsanız , .gitdizindeki bazı dosyaların arkasında kalır ve bir daha denediğinizde filter-branch, -fseçeneği sağlamadığınız sürece bu durumdan şikayet eder filter-branch.
Gerçek komutu gelince, ben alıyorum çok şans yoktu bashne istediğini yapmak için, bunun yerine kullandığım zsh -cyapmak için zshbir komut çalıştırmak. İlk önce komutta sözdizimini extended_globsağlayan seçeneği ve bir glob ( ) ile nokta dosyalarını (örneğin ) seçmeme izin veren seçeneği ayarladım .^(...)mvglob_dots.gitignore^(...)
Sonra, kullandığım mkdir -pher iki oluşturmak için komut pluginsve plugins/my-pluginaynı anda.
Son olarak, deponun kök dizinindeki ve yeni oluşturulan klasör dışındaki tüm dosyaları eşleştirmek için zsh"negatif glob" özelliğini ^(.git|plugins)kullanıyorum . (Burada hariç tutmak gerekli olmayabilir, ancak bir dizini kendi içine taşımaya çalışmak bir hatadır.).gitmy-plugin.git
Depomda, ilk işlem herhangi bir dosya içermediğinden, ilk işlemde mvkomut bir hata döndürdü (taşınacak hiçbir şey olmadığından). Bu nedenle, bir katma || trueböylece git filter-branchdeğil iptal olur.
--allSeçenek söyler filter-branchiçin tarihi yeniden yazmaya tüm depo şubeleri ve ekstra --söylemek gerekir gityerine bir seçenek olarak, yeniden yazma için dalları için seçenek listesinin bir parçası olarak yorumlamak filter-branchkendisi.
Şimdi main-projectdeponuza gidin ve birleştirmek istediğiniz dalı kontrol edin. Deponun yerel kopyasını my-plugin(geçmişi değiştirilmiş olarak) aşağıdakilerle bir uzaktan kumanda olarak ekleyin main-project:
$ git remote add --fetch my-plugin $PATH_TO_MY_PLUGIN_REPOSITORY
Artık işlem geçmişinizde, kullanarak güzel bir şekilde görselleştirebileceğiniz iki alakasız ağacınız olacak:
$ git log --color --graph --decorate --all
Bunları birleştirmek için şunu kullanın:
$ git merge my-plugin/master --allow-unrelated-histories
2.9.0 Git'ten önce --allow-unrelated-historiesseçeneğin mevcut olmadığını unutmayın. Bu sürümlerden birini kullanıyorsanız, seçeneği atlamanız yeterlidir: --allow-unrelated-historiesönleyen hata mesajı 2.9.0'da da eklenmiştir.
Herhangi bir birleştirme çatışması olmamalıdır. Bunu yaparsanız, muhtemelen filter-branchkomutun düzgün çalışmadığı veya zaten bir plugins/my-plugindizin olduğu anlamına gelir main-project.
Gelecekteki katkıda bulunanlar için, iki köklü bir depo yapmak için neler olduğunu merak eden açıklayıcı bir taahhüt mesajı girdiğinizden emin olun.
Yukarıdaki git logkomutu kullanarak, iki kök işleme sahip olması gereken yeni tamamlama grafiğini görselleştirebilirsiniz . O Not sadece masterdal birleştirilecektir . Bu my-plugin, main-projectağaca birleştirmek istediğiniz diğer dallar üzerinde önemli çalışmalarınız my-pluginvarsa, bu birleştirmeleri yapana kadar uzaktan kumandayı silmekten kaçınmanız gerektiği anlamına gelir . Bunu yapmazsanız, bu şubelerden gelen taahhütler yine de main-projectdepoda olacaktır, ancak bazılarına ulaşılamayacak ve nihai çöp toplamaya duyarlı olacaktır. (Ayrıca, uzaktan kumandanın silinmesi uzaktan izleme dallarını kaldırdığından onlara SHA tarafından başvurmanız gerekecektir.)
İsteğe bağlı olarak, saklamak istediğiniz her şeyi birleştirdikten sonra uzaktan kumandayı aşağıdakileri kullanarak my-pluginkaldırabilirsiniz my-plugin:
$ git remote remove my-plugin
Artık my-plugingeçmişini değiştirdiğiniz deponun kopyasını güvenle silebilirsiniz . Benim durumumda, my-pluginbirleştirme işlemi tamamlandıktan ve itildikten sonra gerçek depoya bir kullanımdan kaldırma bildirimi ekledim .
Mac OS X El Capitan üzerinde git --version 2.9.0ve ile test edilmiştir zsh --version 5.2. Kilometreniz değişebilir.
Referanslar: