Motivasi saya untuk mencoba git-svn adalah penggabungan dan percabangan yang mudah. Kemudian saya perhatikan bahwa pria git-svn (1) mengatakan:
Menjalankan git-merge atau git-pull TIDAK disarankan pada cabang yang Anda rencanakan untuk dikecewakan. Subversi tidak mewakili penggabungan dengan cara yang masuk akal atau berguna; jadi pengguna yang menggunakan Subversion tidak dapat melihat penggabungan yang Anda buat. Selain itu, jika Anda menggabungkan atau menarik dari cabang git yang merupakan cermin dari cabang SVN, dcommit dapat melakukan ke cabang yang salah.
Apakah ini berarti saya tidak dapat membuat cabang lokal dari svn / trunk (atau cabang), meretas, menggabungkan kembali ke svn / trunk, lalu dcommit? Saya mengerti bahwa pengguna svn akan melihat kekacauan yang sama dengan penggabungan svn pra 1.5.x selalu, tetapi apakah ada kelemahan lain? Kalimat terakhir itu juga membuatku khawatir. Apakah orang secara rutin melakukan hal-hal seperti ini?
--mergeinfo=<mergeinfo>
opsi yang dapat meneruskan info penggabungan ke SVN. Tidak yakin bagaimana itu harus digunakan.Jawaban:
Sebenarnya, saya menemukan cara yang lebih baik dengan
--no-ff
opsi pada git merge. Semua teknik squash yang saya gunakan sebelumnya tidak lagi diperlukan.Alur kerja baru saya sekarang adalah sebagai berikut:
Saya memiliki "master" cabang yang merupakan satu-satunya cabang yang saya dcommit dari dan clone bahwa repositori SVN (
-s
menganggap Anda memiliki tata letak SVN standar dalam repositoritrunk/
,branches/
dantags/
):Saya mengerjakan "kantor" cabang lokal (
-b
membuat cabang "kantor")komit secara lokal ke cabang "work" (
-s
untuk menandatangani pesan komit Anda). Dalam sekuelnya, saya anggap Anda membuat 3 commit lokalSekarang Anda ingin komit ke server SVN
[Akhirnya] menyimpan modifikasi yang tidak ingin Anda lihat dilakukan pada server SVN (sering Anda berkomentar beberapa kode dalam file utama hanya karena Anda ingin mempercepat kompilasi dan fokus pada fitur yang diberikan)
rebase cabang master dengan repositori SVN (untuk memperbarui dari server SVN)
kembali ke cabang kerja dan rebase dengan master
Pastikan semuanya baik-baik saja, misalnya:
Sekarang saatnya untuk menggabungkan ketiga commit dari cabang "work" menjadi "master" menggunakan
--no-ff
opsi yang luar biasa iniAnda dapat melihat status log:
Sekarang Anda mungkin ingin mengedit (
amend
) komit terakhir untuk dudes SVN Anda (jika tidak, mereka hanya akan melihat satu komit dengan pesan "Gabung cabang 'pekerjaan'"Akhirnya komit di server SVN
Kembali bekerja dan akhirnya pulihkan file simpanan Anda:
sumber
--no-ff
opsi, Anda secara eksplisit membuat komit gabungan (komit dengan dua orang tua) alih-alih fast-forward. Untuk memastikan semua komit di cabang svn-tracking adalah komit induk tunggal, semua penggabungan harus maju cepat (--ff-only
dapat membantu dengan ini) atau, jika trunk telah berubah di belakang Anda, a--squash
, kan?git svn dcommit
menulis ulang komit git yang Anda berikan. Ini berarti Anda kehilangan orang tua yang lain, dan sekarang repositori git Anda tidak memiliki catatan bahwa Anda pernah menggabungkan cabang tersebutmaster
. Ini juga dapat meninggalkan direktori kerja Anda dalam keadaan tidak konsisten.git merge --no-ff work -m "commit message"
alih-alih memilikigit commit --amend
langkah ekstraMembuat cabang lokal pasti dimungkinkan dengan git-svn. Selama Anda hanya menggunakan cabang lokal untuk diri Anda sendiri, dan tidak mencoba menggunakan git untuk menggabungkan antara cabang svn hulu, Anda harus baik-baik saja.
Saya memiliki cabang "master" yang saya gunakan untuk melacak server svn. Ini adalah satu-satunya cabang yang saya pilih. Jika saya melakukan beberapa pekerjaan, saya membuat cabang topik dan mengerjakannya. Ketika saya ingin mengkomitnya, saya melakukan hal berikut:
Saya juga memiliki situasi lain di mana saya perlu mempertahankan beberapa perubahan lokal (untuk debugging) yang tidak boleh didorong ke svn. Untuk itu, saya memiliki cabang master di atas tetapi juga cabang yang disebut "bekerja" di mana saya biasanya bekerja. Cabang-cabang topik bercabang dari pekerjaan. Ketika saya ingin melakukan pekerjaan di sana, saya checkout master dan menggunakan cherry-pick untuk memilih commit dari cabang kerja yang ingin saya komit ke svn. Ini karena saya ingin menghindari melakukan tiga komitmen perubahan lokal. Kemudian, saya hengkang dari cabang utama dan rebase segalanya.
Penting untuk dijalankan
git svn dcommit -n
terlebih dahulu untuk memastikan bahwa Anda akan melakukan apa yang ingin Anda lakukan. Tidak seperti git, menulis ulang sejarah di svn itu sulit!Saya merasa bahwa harus ada cara yang lebih baik untuk menggabungkan perubahan pada cabang topik sambil melewatkan perubahan lokal yang dilakukan daripada menggunakan cherry-pick, jadi jika ada yang punya ide mereka akan diterima.
sumber
Solusi sederhana: Hapus cabang 'kerja' setelah penggabungan
Jawaban singkat: Anda dapat menggunakan git sesuka Anda (lihat di bawah untuk alur kerja sederhana), termasuk penggabungan. Pastikan saja mengikuti setiap ' git merge work ' dengan ' git branch -d work ' untuk menghapus cabang kerja sementara.
Penjelasan latar belakang: Masalah penggabungan / dcommit adalah bahwa setiap kali Anda 'git svn dcommit' cabang, riwayat gabungan cabang itu 'diratakan': git lupa tentang semua operasi penggabungan yang masuk ke cabang ini: Hanya isi file dipertahankan, tetapi fakta bahwa konten ini (sebagian) berasal dari cabang lain yang spesifik hilang. Lihat: Mengapa git svn dcommit kehilangan riwayat komit gabungan untuk cabang lokal?
(Catatan: Tidak banyak yang bisa dilakukan git-svn tentang hal itu: svn sama sekali tidak memahami penggabungan git yang jauh lebih kuat. Jadi, di dalam repositori svn, informasi penggabungan ini tidak dapat direpresentasikan dengan cara apa pun.)
Tapi ini adalah seluruh masalah. Jika Anda menghapus cabang 'work' setelah digabungkan ke dalam 'cabang master' maka repositori git Anda 100% bersih dan terlihat persis seperti repositori svn Anda.
Alur kerja saya: Tentu saja, saya pertama kali mengkloning repositori svn remote ke repositori git lokal (ini mungkin membutuhkan waktu):
Semua pekerjaan kemudian terjadi di dalam "direktori-lokal". Setiap kali saya perlu mendapatkan pembaruan dari server (seperti 'pembaruan svn'), saya lakukan:
Saya melakukan semua pekerjaan pengembangan saya di 'pekerjaan' cabang terpisah yang dibuat seperti ini:
Tentu saja, Anda dapat membuat cabang sebanyak mungkin untuk pekerjaan Anda dan menggabungkan serta menyusun ulang di antara mereka sebanyak yang Anda inginkan (hapus saja ketika Anda selesai melakukannya --- seperti yang dibahas di bawah). Dalam pekerjaan normal saya, saya sangat sering melakukan:
Langkah selanjutnya (git rebase -i) adalah opsional --- itu hanya membersihkan sejarah sebelum mengarsipkannya di svn: Setelah saya mencapai batu stabil mil yang ingin saya bagikan dengan orang lain, saya menulis ulang sejarah 'pekerjaan' ini cabang dan bersihkan pesan komit (pengembang lain tidak perlu melihat semua langkah kecil dan kesalahan yang saya buat di jalan --- hanya hasilnya). Untuk ini, saya lakukan
dan salin hash sha-1 dari commit terakhir yang aktif di repositori svn (seperti yang ditunjukkan oleh git-svn-id). Lalu aku menelepon
Cukup tempel sha-1 hash svn commit terakhir kami alih-alih milikku. Anda mungkin ingin membaca dokumentasi dengan 'git help rebase' untuk detailnya. Singkatnya: perintah ini pertama kali membuka editor yang menyajikan komit Anda ---- cukup ubah 'pilih' menjadi 'squash' untuk semua komit yang ingin Anda hancurkan dengan komit sebelumnya. Tentu saja, baris pertama harus tetap sebagai 'pick'. Dengan cara ini, Anda dapat menyingkat banyak komitmen kecil Anda menjadi satu atau lebih unit yang berarti. Simpan dan keluar dari editor. Anda akan mendapatkan editor lain yang meminta Anda untuk menulis ulang pesan log komit.
Singkatnya: Setelah saya menyelesaikan 'peretasan kode', saya memijat cabang 'pekerjaan' saya sampai terlihat bagaimana saya ingin mempresentasikannya kepada programmer lain (atau bagaimana saya ingin melihat pekerjaan dalam waktu beberapa minggu ketika saya menelusuri sejarah) .
Untuk mendorong perubahan ke repositori svn, saya lakukan:
Sekarang kita kembali ke cabang 'master' lama yang diperbarui dengan semua perubahan yang terjadi pada waktu yang bersamaan di repositori svn (perubahan baru Anda disembunyikan di cabang 'kerja').
Jika ada perubahan yang mungkin berbenturan dengan perubahan 'pekerjaan' baru Anda, Anda harus menyelesaikannya secara lokal sebelum Anda mendorong pekerjaan baru Anda (lihat detail lebih lanjut di bawah). Kemudian, kita bisa mendorong perubahan kita ke svn:
Catatan 1: Perintah 'git branch -d work' cukup aman: Perintah ini hanya memungkinkan Anda untuk menghapus cabang yang tidak Anda perlukan lagi (karena mereka sudah bergabung ke cabang Anda saat ini). Jika Anda mengeksekusi perintah ini secara tidak sengaja sebelum menggabungkan pekerjaan Anda dengan cabang 'master', Anda mendapatkan pesan kesalahan.
Catatan 2: Pastikan untuk menghapus cabang Anda dengan 'git branch -d work' antara penggabungan dan dcommit: Jika Anda mencoba untuk menghapus cabang setelah dcommit, Anda mendapatkan pesan kesalahan: Ketika Anda melakukan 'git svn dcommit', git lupa bahwa cabang Anda telah digabung dengan 'master'. Anda harus menghapusnya dengan 'git branch -D work' yang tidak melakukan pemeriksaan keamanan.
Sekarang, saya segera membuat cabang 'pekerjaan' baru untuk menghindari peretasan di cabang 'master' secara tidak sengaja:
Mengintegrasikan 'pekerjaan' Anda dengan perubahan pada svn: Inilah yang saya lakukan ketika 'git svn rebase' mengungkapkan bahwa orang lain mengubah repositori svn ketika saya sedang mengerjakan cabang 'work' saya:
Ada solusi yang lebih kuat: Alur kerja yang disajikan sederhana: Menggunakan kekuatan git hanya dalam setiap putaran 'update / hack / dcommit' --- tetapi meninggalkan sejarah proyek jangka panjang sama linearnya dengan repositori svn. Ini tidak apa-apa jika Anda hanya ingin mulai menggunakan git merge dalam langkah pertama kecil dalam proyek svn lawas.
Ketika Anda menjadi lebih akrab dengan git gabung, silakan menjelajahi alur kerja lainnya: Jika Anda tahu apa yang Anda lakukan, Anda dapat mencampur git gabung dengan svn merge ( Menggunakan git-svn (atau serupa) hanya untuk membantu penggabungan svn? )
sumber
git merge --squash work
, mengapa tidak melakukan ini? Saya dapat melihat melakukan squash commit di cabang sebelum bergabung jika Anda membuat lebih dari satu 'pick' (katakanlah Anda memiliki 8 commit dan Anda mengubah masing-masing 4 commit menjadi 1, dan menggabungkan 2 commit untuk dikuasai). Juga ketika memperbarui cabang 'kantor' saya, saya lakukanrebase
, itu lebih sederhana daripada membuat cabang lain untuk cabang saya dan melakukan penggabungan ...Jawaban Greg Hewgill di atas tidak aman! Jika ada komit baru muncul di trunk antara dua "git svn rebase", penggabungan tidak akan maju cepat.
Ini dapat dipastikan dengan menggunakan flag "--ff-only" ke git-merge, tapi saya biasanya tidak menjalankan "git svn rebase" di cabang, hanya "git rebase master" di atasnya (dengan asumsi itu hanya lokal cabang). Kemudian setelah itu "git merge thebranch" dijamin akan maju cepat.
sumber
Cara aman untuk menggabungkan cabang svn di git adalah dengan menggunakan git merge --squash. Ini akan membuat satu komit dan berhenti bagi Anda untuk menambahkan pesan.
Katakanlah Anda memiliki cabang topik svn, yang disebut cabang svn.
pada titik ini Anda memiliki semua perubahan dari svn-cabang tergencet menjadi satu komit menunggu dalam indeks
sumber
Rebase cabang git lokal ke cabang master git lalu dcommit dan dengan cara itu Anda melakukan semua yang dilakukan secara berurutan sehingga orang-orang dapat melihatnya secara linear seperti yang biasa mereka lakukan. Jadi anggap Anda memiliki cabang lokal bernama topik yang bisa Anda lakukan
yang kemudian akan memainkan komit Anda di cabang master yang siap untuk Anda lakukan
sumber