Ketika bekerja dengan git dalam sebuah tim yang menggunakan cabang fitur, saya sering merasa sulit untuk memahami struktur cabang dalam sejarah.
Contoh:
Katakanlah ada fitur cabang fitur / kopi , dan perbaikan bug berlanjut pada master secara paralel dengan cabang fitur.
Sejarah mungkin terlihat seperti ini:
* merge feature/make-coffee
|\
| * small bugfix
| |
* | fix bug #1234
| |
| * add milk and sugar
| |
* | improve comments
| |
* | fix bug #9434
| |
| * make coffe (without milk or sugar)
| |
* | improve comments
|/
*
Masalah
Pada pandangan pertama, saya merasa sulit untuk mengatakan sisi mana yang merupakan cabang fitur. Saya biasanya perlu menelusuri beberapa komentar di kedua sisi untuk mendapatkan ide yang mana. Ini menjadi lebih rumit jika ada beberapa cabang fitur secara paralel (terutama jika mereka untuk fitur terkait erat), atau jika ada penggabungan di kedua arah antara fitur cabang dan master.
Sebagai kontras, dalam Subversion, ini jauh lebih mudah karena nama cabang adalah bagian dari sejarah - jadi saya bisa langsung tahu bahwa komit awalnya dibuat pada "fitur / kopi".
Git dapat membuat ini lebih mudah dengan memasukkan nama cabang saat ini di metadata komit ketika membuat komit (bersama dengan penulis, tanggal dll.). Namun, git tidak melakukan ini.
Adakah alasan mendasar mengapa ini tidak dilakukan? Atau hanya tidak ada yang menginginkan fitur tersebut? Jika yang terakhir, apakah ada cara lain untuk memahami tujuan cabang sejarah tanpa melihat nama?
Jawaban:
Mungkin karena nama cabang hanya bermakna dalam satu repositori. Jika saya berada di
make-coffee
tim dan mengirimkan semua perubahan saya melalui penjaga gerbang,master
cabang saya mungkin akan ditarik kemake-coffee-gui
cabang penjaga gerbang , yang akan ia gabungkan denganmake-coffee-backend
cabangnya, sebelum rebasing kemake-coffee
cabang yang akan bergabung kemaster
cabang pusat .Bahkan dalam satu repositori, nama cabang dapat dan memang berubah seiring alur kerja Anda berkembang.
master
mungkin berubah nanti untuk dipanggildevelopment
, misalnya.Seperti yang disinggung CodeGnome, git memiliki filosofi desain yang kuat untuk tidak memasukkan sesuatu ke dalam data jika itu tidak diperlukan. Pengguna diharapkan untuk menggunakan opsi di
git log
dangit diff
untuk menghasilkan data sesuai dengan keinginan mereka setelah fakta. Saya sarankan mencoba beberapa sampai Anda menemukan format yang berfungsi lebih baik untuk Anda.git log --first-parent
, misalnya, tidak akan menampilkan komit dari cabang yang digabung.sumber
Lacak Sejarah Cabang dengan
--no-ff
Di Git, komit memiliki leluhur, tetapi "cabang" sebenarnya hanyalah kepala dari beberapa lini pembangunan saat ini. Dengan kata lain, komit adalah snapshot dari pohon yang bekerja pada suatu saat, dan dapat menjadi bagian dari sejumlah cabang sekaligus. Ini adalah bagian dari apa yang membuat Git bercabang sangat ringan jika dibandingkan dengan DVCSes lainnya.
Komit Git tidak membawa informasi cabang karena itu tidak diperlukan untuk sejarah Git. Namun, penggabungan yang tidak maju cepat tentu dapat membawa informasi tambahan tentang cabang apa yang digabungkan. Anda dapat memastikan bahwa riwayat Anda berisi informasi ini dengan selalu mengedarkan
--no-ff
bendera ke gabungan Anda. git-merge (1) mengatakan:Ini umumnya akan membuat pesan gabungan yang mirip dengan
Merge branch 'foo'
, jadi Anda biasanya dapat menemukan informasi tentang "cabang leluhur" dengan garis yang mirip dengan berikut:sumber
git log --merges
.Jawaban yang paling sederhana adalah bahwa nama cabang bersifat sementara. Bagaimana jika Anda, misalnya, mengganti nama cabang (
git branch -m <oldname> <newname>
)? Apa yang akan terjadi pada semua komitmen terhadap cabang itu? Atau bagaimana jika dua orang memiliki cabang yang memiliki nama yang sama pada repositori lokal yang berbeda?Satu-satunya hal yang memiliki makna dalam git adalah checksum dari commit itu sendiri. Ini adalah unit dasar pelacakan.
Informasi ada di sana, Anda hanya tidak memintanya, dan tidak persis di sana.
Git menyimpan checksum kepala setiap cabang di
.git/refs/heads
. Sebagai contoh:(ya, saya mengacaukan git checksum saya, itu tidak istimewa, tetapi mereka adalah repositori pribadi yang saya lihat pada saat itu yang tidak perlu ada kebocoran secara tidak sengaja).
Dengan melihat ini dan melacak kembali setiap komit yang memiliki ini sebagai orang tua, atau orang tua orang tua atau orang tua orang tua ... Anda dapat mengetahui apa cabang komit yang diberikan masuk Ini hanya grafik besar untuk membuat.
Menyimpan di mana secara spesifik nama cabang (yang dapat berubah seperti disebutkan di atas) komit ada di komit itu sendiri adalah overhead tambahan pada komit yang tidak membantu itu. Simpan orang tua dari komit dan barangnya.
Anda dapat melihat cabang dengan menjalankan perintah git log dengan flag yang sesuai.
Ada banyak cara berbeda untuk memilih apa yang Anda inginkan - lihat dokumentasi git log -
-all
bagian dan beberapa opsi yang mengikuti.'Tes', 'test1', dan 'test2' adalah cabang-cabang ini berkomitmen untuk.
Perhatikan bahwa dokumentasi git log sangat besar dan sangat mungkin untuk mendapatkan hampir semua yang Anda inginkan.
sumber
Mengapa git commit tidak mengandung nama cabang tempat mereka dibuat?
Hanya keputusan desain. Jika Anda memerlukan informasi itu, Anda dapat menambahkan hook bersiap-komit-komit atau komit-pesan untuk menegakkan itu di repositori tunggal.
Setelah bencana BitKeeper, Linus Torvalds mengembangkan git agar sesuai dengan proses pengembangan kernel Linux. Di sana, sampai tambalan diterima, tambalan itu direvisi, diedit, dipoles beberapa kali (semua melalui Mail), ditandatangani (= mengedit komit), dipetik dengan ceri, mengembara ke cabang-cabang letnan mungkin sering diubah, lebih banyak pengeditan, ceri -picks dan seterusnya sampai mereka akhirnya bergabung dengan Linus.
Dalam alur kerja seperti itu mungkin tidak ada asal spesifik komit, dan seringkali komit baru saja dibuat di beberapa cabang debugging sementara di beberapa repositori acak pribadi yang tidak penting dengan nama cabang lucu, karena git didistribusikan.
Mungkin keputusan desain itu terjadi secara kebetulan saja, tetapi persis sama dengan proses pengembangan kernel Linux.
sumber
Karena dalam Git, komit seperti "membuat kopi" dianggap sebagai bagian dari kedua cabang ketika cabang fitur digabungkan. Bahkan ada perintah untuk memeriksa itu:
Juga, cabang-cabang itu murah, lokal, dan ethereal; mereka dapat dengan mudah ditambahkan, dihapus, diganti namanya, didorong, dan dihapus dari server.
Git mengikuti prinsip bahwa semuanya dapat dilakukan, yang mengapa Anda dapat dengan mudah menghapus cabang dari server jauh, dan Anda dapat dengan mudah menulis ulang sejarah.
Katakanlah saya berada di cabang 'master', dan saya membuat dua komitmen: 'membuat kopi' dan 'menambahkan susu dan gula', lalu saya memutuskan untuk menggunakan cabang baru untuk itu, jadi saya mengatur ulang 'master' kembali ke 'asal /menguasai'. Tidak masalah, semua sejarah masih bersih: 'membuat kopi' dan 'menambahkan susu dan gula' bukan bagian dari master, hanya fitur / make-coffee.
Mercurial adalah kebalikannya; tidak ingin mengubah banyak hal. Cabang bersifat permanen, riwayat penulisan ulang disukai, Anda tidak bisa hanya menghapus cabang dari server.
Singkatnya: Git memungkinkan Anda untuk melakukan segalanya, Mercurial ingin membuat segalanya menjadi mudah (dan membuatnya sangat sulit untuk membiarkan Anda melakukan apa yang Anda inginkan).
sumber