Bagaimana Anda mengatur beberapa repositori git, sehingga semuanya dicadangkan bersama?

98

Dengan SVN, saya memiliki satu repositori besar yang saya simpan di server, dan check-out di beberapa mesin. Ini adalah sistem cadangan yang cukup bagus, dan memungkinkan saya bekerja dengan mudah di salah satu mesin. Saya dapat melakukan checkout proyek tertentu, melakukan dan memperbarui proyek 'master', atau saya dapat menyelesaikan semuanya.

Sekarang, saya memiliki banyak repositori git, untuk berbagai proyek, beberapa di antaranya ada di github. Saya juga memiliki repositori SVN yang saya sebutkan, diimpor melalui perintah git-svn ..

Pada dasarnya, saya suka memiliki semua kode saya (bukan hanya proyek, tetapi cuplikan dan skrip acak, beberapa hal seperti CV saya, artikel yang saya tulis, situs web yang saya buat, dan sebagainya) dalam satu repositori besar yang dapat dengan mudah saya klon ke remote mesin, atau memory-sticks / harddisk sebagai cadangan.

Masalahnya adalah, karena ini adalah repositori pribadi, dan git tidak mengizinkan check out dari folder tertentu (yang dapat saya dorong ke github sebagai proyek terpisah, tetapi perubahannya muncul di master-repo, dan sub- repo)

Saya dapat menggunakan sistem submodul git, tetapi tidak berfungsi seperti yang saya inginkan juga (submodul adalah penunjuk ke repositori lain, dan tidak benar-benar berisi kode sebenarnya, jadi tidak berguna untuk cadangan)

Saat ini saya memiliki folder git-repos (misalnya, ~ / code_projects / proj1 / .git / ~ / code_projects / proj2 / .git /), dan setelah melakukan perubahan pada proj1 saya lakukan git push github, kemudian saya menyalin file ke ~ / Dokumen / kode / python / proyek / proj1 / dan lakukan satu komit (alih-alih banyak yang ada di repo individu). Lalu lakukan git push backupdrive1, git push mymemorystickdll

Jadi, pertanyaannya: Bagaimana kode dan proyek pribadi Anda dengan repositori git, dan menjaganya tetap sinkron dan dicadangkan?

dbr
sumber

Jawaban:

74

Saya sangat menyarankan agar tidak meletakkan data yang tidak terkait di repositori Git tertentu. Overhead pembuatan repositori baru cukup rendah, dan itu adalah fitur yang memungkinkan untuk memisahkan garis keturunan yang berbeda sepenuhnya.

Melawan gagasan itu berarti berakhir dengan sejarah yang tidak perlu kusut, yang membuat administrasi lebih sulit dan - yang lebih penting - alat "arkeologi" kurang berguna karena pengenceran yang dihasilkan. Juga, seperti yang Anda sebutkan, Git mengasumsikan bahwa "unit kloning" adalah repositori, dan secara praktis harus melakukannya karena sifatnya yang terdistribusi.

Salah satu solusinya adalah menyimpan setiap proyek / paket / dll. sebagai repositori telanjangnya sendiri (yaitu, tanpa pohon kerja) di bawah hierarki yang diberkati, seperti:

/repos/a.git
/repos/b.git
/repos/c.git

Setelah beberapa konvensi dibuat, penerapan operasi administratif (pencadangan, pengemasan, penerbitan web) ke hierarki lengkap menjadi mudah, yang memiliki peran yang tidak sepenuhnya berbeda dengan repositori SVN "monolitik". Bekerja dengan repositori ini juga menjadi agak mirip dengan alur kerja SVN, dengan tambahan bahwa seseorang dapat menggunakan komit dan cabang lokal:

svn checkout   --> git clone
svn update     --> git pull
svn commit     --> git push

Anda dapat memiliki banyak remote di setiap klon yang berfungsi, untuk kemudahan sinkronisasi antara banyak pihak:

$ cd ~/dev
$ git clone /repos/foo.git       # or the one from github, ...
$ cd foo
$ git remote add github ...
$ git remote add memorystick ...

Anda kemudian dapat mengambil / tarik dari masing-masing "sumber", bekerja dan melakukan secara lokal, dan kemudian mendorong ( "backup") untuk masing-masing remote ini ketika Anda siap dengan sesuatu seperti (catatan bagaimana yang mendorong sama komit dan sejarah untuk masing-masing remote!):

$ for remote in origin github memorystick; do git push $remote; done

Cara termudah untuk mengubah repositori kerja yang ada ~/dev/foo menjadi repositori kosong mungkin adalah:

$ cd ~/dev
$ git clone --bare foo /repos/foo.git
$ mv foo foo.old
$ git clone /repos/foo.git

yang sebagian besar setara dengan svn import--tetapi tidak membuang sejarah "lokal" yang ada.

Catatan: submodul adalah mekanisme untuk menyertakan garis keturunan terkait bersama , jadi saya memang tidak akan menganggapnya sebagai alat yang tepat untuk masalah yang Anda coba selesaikan.

Damien Diederen
sumber
18
Fakta bahwa saya terus berakhir dengan banyak repositori terpisah dan menulis skrip sederhana untuk membantu mengelola semuanya membuat saya merasa ada sesuatu yang hilang di git. Saya tidak bisa memutuskan dengan tepat apa itu atau apa yang harus saya lakukan.
DonGar
Nah, apakah Anda juga mengelola banyak proyek terpisah? Hubungan satu-ke-satu antara proyek dan repositori terasa masuk akal di dunia terdistribusi, tetapi saya masih akan mengatur repositori kosong di pohon direktori umum untuk kemudahan pencadangan dan administrasi. (Dengan kata lain, Git / Hg / Bzr memaksa Anda untuk memisahkan administrasi dari tugas proyek, sementara sebagian besar alur kerja SVN menggabungkan keduanya; sekarang umum untuk melihat orang mendelegasikan bagian administratif ke GitHub atau penyedia serupa lainnya.)
Damien Diederen
2
ide ini hanya masuk akal jika Anda meng-host proyek Anda sendiri dan / atau semuanya open source. Jika tidak, Anda akan memerlukan github, Anda akan memerlukan proyek pribadi tak terbatas yang bisa jadi mahal
dkinzer
2
Alih-alih "untuk remote di memorystick github asal; lakukan git push $ remote; done", Anda juga dapat mengkonfigurasi remote khusus untuk mendorong dengan satu perintah ke banyak remote: stackoverflow.com/questions/36862/… . (Mungkin lebih nyaman dalam beberapa kasus.)
imz - Ivan Zakharyaschev
2
Saya pikir hal yang hilang adalah cara git dapat memisahkan objeknya dengan subpohon sehingga satu "repositori" dapat terdiri dari unit tersinkronisasi terpisah meskipun dapat dipisahkan (diunduh satu per satu tanpa yang lain) sedemikian rupa sehingga orang dapat mengerjakannya secara spesifik subset tanpa mengetahui tentang sisanya.
peterk
28

Saya ingin menambahkan jawaban Damien di mana dia merekomendasikan:

$ for remote in origin github memorystick; do git push $remote; done

Anda dapat mengatur remote khusus untuk mendorong semua remote nyata individu dengan 1 perintah; Saya menemukannya di http://marc.info/?l=git&m=116231242118202&w=2 :

Jadi untuk "git push" (yang masuk akal untuk mendorong cabang yang sama beberapa kali), Anda sebenarnya dapat melakukan apa yang saya lakukan:

  • .git / config berisi:

    [remote "all"]
    url = master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
    url = login.osdl.org:linux-2.6.git
    
  • dan sekarang git push all masterakan mendorong cabang "master" ke kedua
    repositori jarak jauh tersebut.

Anda juga dapat menghemat diri dengan mengetik URL dua kali dengan menggunakan konstruksi:

[url "<actual url base>"]
    insteadOf = <other url base>
imz - Ivan Zakharyaschev
sumber
3

Saya juga ingin tahu tentang cara yang disarankan untuk menangani ini dan akan menjelaskan pengaturan saat ini yang saya gunakan (dengan SVN). Saya pada dasarnya telah membuat repositori yang berisi hierarki sistem file mini termasuk bin dan direktori lib-nya sendiri. Ada skrip di root pohon ini yang akan mengatur lingkungan Anda untuk menambahkan bin, lib, dll ... direktori lain ini ke variabel lingkungan yang sesuai. Jadi direktori root pada dasarnya terlihat seperti:

./bin/            # prepended to $PATH
./lib/            # prepended to $LD_LIBRARY_PATH
./lib/python/     # prepended to $PYTHONPATH
./setup_env.bash  # sets up the environment

Sekarang di dalam / bin dan / lib ada beberapa proyek dan perpustakaannya yang sesuai. Saya tahu ini bukan proyek standar, tetapi sangat mudah bagi orang lain di grup saya untuk memeriksa repo, menjalankan skrip 'setup_env.bash' dan memiliki versi terbaru dari semua proyek secara lokal di dalamnya. Periksa. Mereka tidak perlu khawatir tentang menginstal / memperbarui / usr / bin atau / usr / lib dan membuatnya mudah untuk memiliki banyak pembayaran dan lingkungan yang sangat terlokalisasi per checkout. Seseorang juga dapat meng-rm seluruh repositori dan tidak khawatir tentang menghapus program apa pun.

Ini berfungsi dengan baik untuk kami, dan saya tidak yakin apakah kami akan mengubahnya. Masalahnya adalah ada banyak proyek dalam satu repositori besar ini. Apakah ada cara standar git / Hg / bzr untuk membuat lingkungan seperti ini dan memecah proyek ke dalam repositori mereka sendiri?

Danny G
sumber
3

, Saya belum mencoba menumpuk repositori git karena saya belum mengalami situasi di mana saya perlu melakukannya. Seperti yang saya baca di #git channel, git tampaknya menjadi bingung dengan menyusun repositori, misalnya Anda mencoba git-init di dalam repositori git. Satu-satunya cara untuk mengelola struktur git bersarang adalah dengan menggunakan git-submoduleatau repoutilitas Android .

Adapun tanggung jawab cadangan yang Anda jelaskan, saya katakan mendelegasikannya ... Bagi saya, saya biasanya meletakkan repositori "asal" untuk setiap proyek di drive jaringan di tempat kerja yang didukung secara teratur oleh teknisi IT dengan strategi cadangan mereka pilihan. Ini sederhana dan saya tidak perlu khawatir tentang itu. ;)

Spoike
sumber
2

Bagaimana dengan menggunakan mr untuk mengelola beberapa repo Git Anda sekaligus:

Perintah mr (1) dapat melakukan checkout, memperbarui, atau melakukan tindakan lain pada satu set repositori seolah-olah mereka adalah satu gabungan repositori. Ini mendukung kombinasi subversi, git, cvs, mercurial, bzr, darcs, cvs, vcsh, fosil dan repositori kebenaran, dan dukungan untuk sistem kontrol revisi lainnya dapat dengan mudah ditambahkan. [...]

Ini sangat dapat dikonfigurasi melalui skrip shell sederhana. Beberapa contoh hal yang dapat dilakukannya meliputi:

[...]

  • Saat mengupdate repositori git, tarik dari dua upstream yang berbeda dan gabungkan keduanya.
  • Jalankan beberapa pembaruan repositori secara paralel, sangat mempercepat proses pembaruan.
  • Ingat tindakan yang gagal karena laptop sedang offline, sehingga dapat dicoba lagi saat kembali online.
imz - Ivan Zakharyaschev
sumber
1

Ada metode lain untuk memiliki repo git bersarang, tetapi itu tidak menyelesaikan masalah yang Anda cari. Namun, untuk orang lain yang mencari solusi saya adalah:

Di tingkat atas git repo cukup sembunyikan folder di .gitignore yang berisi repo git bersarang. Ini membuatnya mudah untuk memiliki dua repo git yang terpisah (tapi bersarang!).

arxpoetica.dll
sumber