Katakanlah saya punya setup yang terlihat seperti
phd/code/
phd/figures/
phd/thesis/
Untuk alasan historis, ini semua memiliki repositori git mereka sendiri. Tapi saya ingin menggabungkan mereka menjadi satu untuk menyederhanakan banyak hal. Misalnya, saat ini saya mungkin membuat dua set perubahan dan harus melakukan sesuatu seperti
cd phd/code
git commit
cd ../figures
git commit
Akan (sekarang) menyenangkan hanya untuk tampil
cd phd
git commit
Tampaknya ada beberapa cara untuk melakukan ini menggunakan submodula atau menarik dari sub-repositori saya, tapi itu sedikit lebih kompleks daripada yang saya cari. Paling tidak, aku akan senang
cd phd
git init
git add [[everything that's already in my other repositories]]
tapi itu tidak tampak seperti satu kalimat. Apakah ada sesuatu git
yang bisa membantu saya keluar?
Jawaban:
Inilah solusi yang saya berikan di sini :
Pertama-tama lakukan pencadangan lengkap terhadap direktori phd Anda: Saya tidak ingin dianggap bertanggung jawab atas kehilangan tahun kerja keras Anda! ;-)
Pindahkan konten
phd/code
kephd/code/code
, dan perbaiki histori sehingga sepertinya selalu ada (ini menggunakan perintah cabang-filter git ):Sama untuk konten
phd/figures
danphd/thesis
(hanya ganticode
denganfigures
danthesis
).Sekarang struktur direktori Anda akan terlihat seperti ini:
Kemudian buat repositori git di direktori root, tarik semuanya ke dalamnya dan hapus repositori lama:
Akhirnya, Anda sekarang harus memiliki apa yang Anda inginkan:
Satu sisi bagus dari prosedur ini adalah ia akan meninggalkan file dan direktori yang tidak berversi di tempatnya.
Semoga ini membantu.
Hanya satu kata peringatan: jika
code
direktori Anda sudah memilikicode
subdirektori atau file, ada yang salah (sama untukfigures
danthesis
tentu saja). Jika itu masalahnya, cukup ganti nama direktori atau file tersebut sebelum menjalani seluruh prosedur ini:Dan ketika prosedur selesai, tambahkan langkah terakhir ini:
Tentu saja, jika
code
subdirektori atau file tidak diversi, gunakan sajamv
alih-alihgit mv
, dan lupakangit commit
s.sumber
mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
dan kemudian bekerja dengan baik!sumber
Mungkin, secara sederhana (mirip dengan jawaban sebelumnya, tetapi menggunakan perintah yang lebih sederhana) membuat di masing-masing repositori lama yang terpisah komit yang memindahkan konten ke subdirektori yang sesuai, misalnya:
dan kemudian menggabungkan ketiga repo yang terpisah menjadi satu yang baru, dengan melakukan sesuatu seperti:
Maka Anda akan menyimpan riwayat Anda, tetapi akan melanjutkan dengan satu repo.
sumber
Anda bisa mencoba strategi menggabungkan subtree . Ini akan memungkinkan Anda menggabungkan repo B menjadi repo A. Keuntungan lebih dari
git-filter-branch
itu adalah tidak mengharuskan Anda untuk menulis ulang riwayat repo A Anda (melanggar jumlah SHA1).sumber
Solusi git-filter-branch berfungsi dengan baik, tetapi perhatikan bahwa jika repo git Anda berasal dari impor SVN mungkin gagal dengan pesan seperti:
Dalam hal ini Anda perlu mengecualikan revisi awal dari cabang-filter - yaitu mengubah
HEAD
di akhir menjadi[SHA of 2nd revision]..HEAD
- lihat:http://www.git.code-experiments.com/blog/2010/03/merging-git-repositories.html
sumber
Solusi @MiniQuark banyak membantu saya, tapi sayangnya itu tidak memperhitungkan tag akun yang ada di repositori sumber (Setidaknya dalam kasus saya). Di bawah ini adalah peningkatan saya untuk jawaban @MiniQuark.
Pertama buat direktori yang akan berisi repo yang dibuat dan repo yang digabungkan, buat direktori untuk masing-masing satu yang digabungkan.
Lakukan penarikan setiap repositori dan ambil semua tag. (Menyajikan instruksi hanya untuk
code
sub-direktori)(Ini adalah peningkatan ke poin 2 dalam jawaban MiniQuark) Pindahkan konten
new_phd/code
kenew_phd/code/code
dan tambahkancode_
prefeix sebelum setiap tagSetelah melakukannya, akan ada tag dua kali lebih banyak daripada sebelum melakukan cabang-filter. Tag lama tetap dalam repo dan tag baru dengan
code_
awalan ditambahkan.Hapus tag lama secara manual:
Ulangi poin 2,3,4 untuk subdirektori lainnya
Sekarang kita memiliki struktur direktori seperti di @MiniQuark anwser point 3.
Lakukan seperti pada poin 4 dari MiniQuark anwser, tetapi setelah melakukan tarikan dan sebelum menghapus
.git
dir, ambil tag:Terus..
Ini hanyalah solusi lain. Semoga ini bisa membantu seseorang, itu membantu saya :)
sumber
git-stitch-repo dari jawaban Aristoteles Pagaltzis hanya berfungsi untuk repositori dengan sejarah linier yang sederhana.
Jawaban MiniQuark bekerja untuk semua repositori, tetapi tidak menangani tag dan cabang.
Saya membuat sebuah program yang bekerja dengan cara yang sama seperti yang dijelaskan oleh MiniQuark, tetapi ia menggunakan satu komit gabungan (dengan N orang tua) dan juga membuat ulang semua tag dan cabang untuk menunjukkan komit gabungan tersebut.
Lihat repositori git-merge-repos untuk contoh bagaimana menggunakannya.
sumber
Saya telah membuat alat yang membuat tugas ini. Metode yang digunakan mirip (secara internal membuat beberapa hal seperti --filter-branch) tetapi lebih ramah. Apakah GPL 2.0
http://github.com/geppo12/GitCombineRepo
sumber
Sebenarnya, git-stitch-repo sekarang mendukung cabang dan tag, termasuk tag beranotasi (saya menemukan ada bug yang saya laporkan, dan diperbaiki). Apa yang saya temukan berguna adalah dengan tag. Karena tag dilampirkan pada komit, dan beberapa solusi (seperti pendekatan Eric Lee) gagal menangani tag. Anda mencoba untuk membuat cabang dari tag yang diimpor, dan itu akan membatalkan git gabungan / bergerak dan mengirim Anda kembali seperti repositori terkonsolidasi yang hampir identik dengan repositori yang berasal dari tag. Juga, ada masalah jika Anda menggunakan tag yang sama di beberapa repositori yang Anda 'gabungkan / konsolidasi'. Misalnya, jika Anda memiliki repo A ad B, keduanya memiliki tag rel_1.0. Anda menggabungkan repo A dan repo B ke repo AB. Karena tag rel_1.0 ada di dua komit yang berbeda (satu untuk A dan satu untuk B), tag mana yang akan terlihat di AB? Entah tag dari repo A yang diimpor atau dari repo B yang diimpor, tetapi tidak keduanya.
git-stitch-repo membantu mengatasi masalah itu dengan membuat tag rel_1.0-A dan rel_1.0-B. Anda mungkin tidak dapat checkout tag rel_1.0 dan mengharapkan keduanya, tetapi setidaknya Anda dapat melihat keduanya, dan secara teoritis, Anda dapat menggabungkan mereka ke cabang lokal umum kemudian membuat tag rel_1.0 pada cabang gabungan (dengan asumsi Anda baru saja bergabung dan tidak mengubah kode sumber). Lebih baik bekerja dengan cabang, karena Anda dapat menggabungkan seperti cabang dari setiap repo ke cabang lokal. (dev-a dan dev-b dapat digabung menjadi cabang dev lokal yang kemudian dapat didorong ke asalnya).
sumber
Urutan yang Anda sarankan
akan bekerja, tetapi Anda akan kehilangan riwayat komit Anda.
sumber
Untuk menggabungkan Proyek kedua dalam Proyek utama:
A) Dalam Proyek kedua
B) Dalam Proyek utama:
Di cabang ini lakukan semua transformasi besar yang perlu Anda lakukan dan lakukan mereka.
C) Kemudian kembali ke master dan penggabungan klasik antara dua cabang:
sumber
Saya akan melemparkan solusi saya di sini juga. Ini pada dasarnya pembungkus skrip bash yang cukup sederhana
git filter-branch
. Seperti solusi lain, hanya memigrasikan cabang utama dan tidak memigrasikan tag. Tetapi histori master penuh komit dimigrasikan dan itu adalah skrip bash pendek sehingga seharusnya relatif mudah bagi pengguna untuk meninjau atau mengubah.https://github.com/Oakleon/git-join-repos
sumber
Skrip bash ini berfungsi di sekitar masalah karakter tab sed (di MacOS misalnya) dan masalah file yang hilang.
Ini adalah kombinasi dari posting miniquark , marius-butuc dan ryan . Cheers untuk mereka!
sumber