Untuk apa saya menggunakan git-worktree?

211

Saya membaca posting Github di git-worktree . Mereka menulis:

Misalkan Anda bekerja di repositori Git pada cabang yang dipanggil feature, ketika pengguna melaporkan bug dengan urgensi tinggi master. Pertama Anda membuat pohon kerja tertaut dengan cabang baru hotfix,, diperiksa relatif terhadap master [...] Anda dapat memperbaiki bug, mendorong perbaikan terbaru, dan membuat permintaan tarik.

Ketika saya sedang mengerjakan fitur cabang yang disebut dan beberapa bug dengan tingkat urgensi tinggi dilaporkan, saya biasanya menyembunyikan apa pun yang sedang saya kerjakan dan membuat cabang baru. Setelah selesai, saya bisa terus bekerja. Ini adalah model yang sangat sederhana, saya telah bekerja seperti itu selama bertahun-tahun.

Di sisi lain, menggunakan git-worktree memiliki keterbatasannya sendiri:

Misalnya, cabang yang sama tidak boleh diperiksa di dua pohon yang terhubung secara bersamaan, karena itu akan memungkinkan perubahan yang dilakukan dalam satu pohon yang bekerja untuk membawa yang lainnya tidak sinkron.

Mengapa saya memilih alur kerja yang lebih rumit untuk masalah yang sudah diselesaikan?

Adakah sesuatu tentang git-worktreehal itu yang tidak dapat dilakukan sebelumnya dan yang membenarkan fitur baru yang kompleks ini?

terpesona
sumber
12
Satu hal yang Anda tidak dapat simpanan adalah jalur tanpa pencemaran, setelah bergabung atau rebase dengan konflik.
chirlu
11
Jika Anda bekerja dengan bahasa yang dikompilasi, menyimpan berarti Anda harus mengkompilasi ulang semuanya ketika Anda melepas.
mb14
Kami memiliki beberapa produk berbeda berdasarkan kode sumber yang sama (300 MB), dan saya berencana untuk menggabungkan semuanya menjadi satu repo besar dan menggunakan worktree untuk menjaga setiap produk diperiksa di folder yang berbeda, daripada memiliki banyak sekali klon yang tidak tetap sinkron
endolith

Jawaban:

197

Bagi saya, git worktree adalah peningkatan terbesar sejak lama. Saya bekerja dalam pengembangan perangkat lunak perusahaan. Di sana, sangat umum bahwa Anda harus mempertahankan versi lama seperti yang Anda rilis 3 tahun lalu. Tentu saja Anda memiliki cabang untuk setiap versi sehingga Anda dapat dengan mudah beralih ke sana dan memperbaiki bug. Namun, beralih itu mahal, karena sementara itu Anda sepenuhnya merestrukturisasi repositori dan mungkin membangun sistem. Jika Anda beralih, IDE Anda akan menjadi gila mencoba menyesuaikan pengaturan proyek.

Dengan worktree, Anda dapat menghindari konfigurasi ulang yang konstan itu. Periksa cabang-cabang tua itu di folder terpisah menggunakan worktree. Untuk setiap cabang, Anda mendapat proyek IDE independen.

Tentu saja ini bisa dilakukan di masa lalu dengan mengkloning repo beberapa kali dan ini adalah pendekatan saya sejauh ini. Namun, itu juga berarti membuang-buang ruang hardrive dan lebih buruk perlu mengambil perubahan yang sama dari repo beberapa kali.

Sebi
sumber
4
Anda tidak harus mengambil perubahan yang sama dari repo beberapa kali. Anda bisa saja menyalin direktori .git dari klon pertama.
misiu_mp
1
@ jdk1.0 maaf atas kebingungan, komentar diarahkan ke misiu_mp
mxttie
2
Sebagai seseorang yang telah menggunakan 2-3 repo yang sangat direplikasi sehingga saya dapat membangun satu cabang fitur sementara mengembangkan yang lain, saya memiliki masing-masing repo lokal sebagai remote dari yang lain dan saya setuju sepenuhnya dengan karakterisasi Sebi dari sisi buruknya (banyak mengambil dan mendorong! ) Juga, begitu saya beralih ke worktree, saya mengumpulkan bahwa saya tidak perlu lagi khawatir tentang cabang lokal yang bernama sama (yang terjadi kira-kira setiap 6-10 bulan karena saya terganggu beberapa kali selama periode hari dan berakhir mengerjakan fitur cabang yang sama dari beberapa repo, tetapi lupa untuk menyinkronkannya kembali ...)
sage
3
@iheanyi - (1). Lebih cepat jika IDE menyimpan file data eksternal (seperti basis data pengindeksan) yang terkait dengan direktori yang diberikan. Jika Anda menekan konten dalam direktori yang sama , itu biasanya akan membatalkan cache data IDE, dan harus diindeks ulang.
Steve Hollasch
5
@iheanyi - (2) Seiring waktu, sejarah segalanya akan tumbuh jauh lebih besar daripada file pohon yang berfungsi pada titik tertentu. Sejarah segalanya == .gitdirektori. Dengan banyak klon lokal dari hulu, Anda memiliki banyak salinan lokal dari basis data yang sama, karena masing-masing klon memiliki .gitbasis datanya sendiri . Dengan banyak pohon kerja lokal, setiap pohon menggunakan .gitdatabase yang sama . Ya, jika Anda memiliki klon lokal dari worktree lokal Anda, Git akan menautkan banyak konten .git, tetapi tidak pada Windows.
Steve Hollasch
71

Saya dapat melihat beberapa kegunaan untuk ini.

Jika Anda memiliki rangkaian uji yang berjalan untuk waktu yang lama, bayangkan berjam-jam, dan Anda memulainya secara efektif memblokir copy pekerjaan sampai tes selesai. Berpindah cabang selama tes-tes itu akan mematahkannya dengan cara yang sulit dimengerti.

Maka dengan itu git-worktreesaya dapat memiliki ide kedua diluncurkan untuk cabang lain melakukan pekerjaan di sana.

Juga, ketika saya beralih ke beberapa cabang lain untuk melakukan penyelidikan cepat, IDE saya berpikir banyak file tiba-tiba berubah dan akan mengindeks semua perubahan itu, hanya harus mengindeks ulang mereka ketika saya beralih kembali.

Kasus penggunaan ketiga adalah melakukan perbandingan file menggunakan alat lain selain git-diff, seperti biasa diff, antara dua direktori, bukan jika dua cabang.

Andreas Wederbrand
sumber
6
Tidak akan git clonebekerja dengan baik untuk semua ini?
jthill
12
Akan tetapi kloning repositori besar dari jarak jauh bisa memakan waktu lama. Saya sedang bekerja melawan satu repositori yang membutuhkan beberapa menit untuk mengkloning. Saya kira Anda bisa melakukannya dengan git clone --reference. Juga, pengelolaan semua cabang lainnya akan dilakukan hanya sekali, bukan sekali per direktori kerja.
Andreas Wederbrand
6
Jangan mengkloning dari jarak jauh, mengkloning dari remote Anda. Saya tidak mengerti masalah manajemen cabang, bisakah Anda mengklarifikasi?
jthill
14
Saya mencoba menggunakan klon, dan memang ada masalah manajemen. Alih-alih satu set cabang saya memiliki satu set klon, yang saya tidak bisa melihat bersama-sama dalam satu UI. Jika saya perlu memilih beberapa perubahan, saya harus mengambil atau mendorongnya. Itu menambahkan langkah-langkah tambahan untuk semua tindakan. Semuanya bisa dilakukan, tetapi selalu ada beberapa gesekan.
maks 630
2
Dan ketika mengatur cadangan, repositori tunggal jauh lebih mudah.
maks 630
64

Satu penggunaan yang jelas adalah untuk secara bersamaan membandingkan perilaku (bukan sumber) versi yang berbeda - misalnya versi yang berbeda dari situs web atau hanya halaman web.

Saya mencoba ini secara lokal.

  • buat direktori page1.

  • di dalam buat direktori srcdan git inititu.

  • di srcbuat page1.htmldengan sedikit konten dan komit.

  • $ git branch ver0

  • $ git worktree add ../V0 ver0

  • di srcmaster tambahkan lebih banyak teks ke page1.htmldan komit.

  • $ git branch sty1

  • edit page1.htmldi sty1cabang (tambahkan beberapa gaya CSS khas) dan tambahkan komit.

  • $ git worktree add ../S1 sty1

Anda sekarang dapat menggunakan browser web untuk membuka dan melihat 3 versi ini secara bersamaan:

  • ..\page1\src\page1.html // apa pun yang dimiliki git sebagai arus

  • ..\page1\V0\page1.html // versi awal

  • ..\page1\S1\page1.html // versi gaya percobaan

RodMcGuire
sumber
2
Saya tidak melihat bagaimana ini menjelaskan manfaat menggunakan worktree untuk tujuan ini di atas klon.
iheanyi
@iheanyi Anda bisa mengatakan hal yang sama tentang branch; jawabannya juga sama: bobotnya lebih ringan, dan dibuat untuk pekerjaan itu.
OJFord
1
@ OJFord, itulah intinya. Jawaban ini tidak menjelaskan kepada saya apa yang dilakukan oleh meja kerja yang berbeda. Ini jelas bukan alias untuk cabang atau klon tetapi efek yang saya lihat di sini tampaknya sama. Saya tidak melihat bagaimana ini lebih ringan daripada hanya menggunakan cabang atau klon.
iheanyi
@iheanyi Ini berbeda dari menggunakan cabang - Anda tidak dapat menggunakan cabang sendirian untuk mendapatkan beberapa status worktree sekaligus - dan bobot yang lebih ringan daripada klon kedua (..., n). Yang saya maksudkan adalah Anda dapat mengatakan juga tentang cabang 'mengapa tidak hanya mengkloning dan membuat perubahan Anda', tetapi beberapa cabang dalam satu repo adalah bobot yang lebih ringan dan lebih mudah dikelola untuk mendapatkan perilaku itu.
OJFord
@ OJFord Saya tidak berpikir ini menyelesaikan kebingungan saya dengan worktree. Biarkan saya begini, apakah Anda menggunakan cabang atau klon atau sesuatu yang lain, tujuan akhir dari proses yang dijelaskan di sini adalah untuk membandingkan tiga versi berbeda dari sesuatu secara bersamaan. Berdasarkan apa yang ada di jawaban, saya tidak mengerti mengapa saya akan menggunakan worktree atas beberapa alternatif. Jawabannya tidak menjelaskan apa yang dilakukan oleh worktree dan bukan alternatifnya. Anda membuat klaim tentang sesuatu yang ringan (atau bobot lebih ringan) tapi saya tidak melihat bagaimana worktree membuat cabang kurang "berbobot".
iheanyi
29
  1. Ada alasan sah mengapa Anda ingin / membutuhkan banyak worktrees di sistem file sekaligus.

    • memanipulasi file yang diperiksa sementara perlu membuat perubahan di tempat lain (mis. kompilasi / pengujian)

    • diffing file melalui alat diff normal

    • selama menggabungkan konflik, saya sering ingin menavigasi melalui kode sumber karena ada di sisi sumber saat menyelesaikan konflik dalam file.

    • Jika Anda harus sering bolak-balik, ada waktu yang terbuang untuk keluar dan memeriksa ulang yang tidak perlu Anda lakukan dengan beberapa worktrees.

    • biaya mental dari perubahan konteks mental antar cabang melalui penyimpanan git tidak benar-benar dapat diukur. Beberapa orang menemukan bahwa ada biaya mental untuk menyimpan yang tidak ada di sana hanya dengan membuka file dari direktori yang berbeda.

  2. Beberapa orang bertanya "mengapa tidak melakukan banyak klon lokal". Memang benar bahwa dengan flag "--local" Anda tidak perlu khawatir tentang penggunaan ruang disk tambahan. Ini (atau gagasan serupa) adalah apa yang telah saya lakukan hingga saat ini. Keuntungan fungsional untuk tabel kerja terkait dari klon lokal adalah:

    1. Dengan klon lokal, meja kerja tambahan Anda (yang berada di klon lokal) tidak memiliki akses ke cabang asal atau hulu. 'Asal' di klon tidak akan sama dengan 'asal' di klon pertama.

      • Berlari git log @{u}..atau git diff origin/feature/other-featurebisa sangat membantu dan ini tidak mungkin lagi atau lebih sulit. Ide-ide ini secara teknis dimungkinkan dengan klon lokal melalui bermacam-macam workarouns, tetapi setiap solusi yang dapat Anda lakukan dilakukan lebih baik dan / atau lebih sederhana melalui worktrees terkait.
    2. Anda dapat membagikan referensi di antara meja kerja. Jika Anda ingin membandingkan atau meminjam perubahan dari cabang lokal lain, sekarang Anda bisa.

Alexander Bird
sumber
11
Anda juga dapat membuat daftar semua tabel kerja dengan satu perintah, dengan klon Anda perlu melacaknya sendiri.
Ian Ringrose
hmm Pada git 2.7.0 yang tampaknya menjadi kasusnya. Bagus untuk mengetahui.
Alexander Bird
9

tl; dr: Kapan pun Anda ingin memeriksa dua pohon kerja pada saat yang sama karena alasan apa pun, git-worktreeadalah cara yang cepat dan hemat ruang untuk melakukannya.

Jika Anda membuat lembar kerja lain, sebagian besar repo (yaitu .git) akan dibagikan, artinya jika Anda membuat cabang atau mengambil data saat Anda berada di satu pohon kerja, itu juga akan dapat diakses dari pohon kerja lain yang Anda miliki. Katakanlah Anda ingin menjalankan test suite Anda di branch foo tanpa harus mendorongnya ke suatu tempat untuk mengkloningnya, dan Anda ingin menghindari kerumitan mengkloning repo Anda secara lokal, menggunakan git-worktreeadalah cara yang bagus untuk membuat checkout baru dari beberapa keadaan dalam suatu tempat terpisah, baik sementara atau permanen. Sama seperti dengan klon, yang perlu Anda lakukan setelah selesai adalah menghapusnya, dan referensi untuk itu akan menjadi sampah yang dikumpulkan setelah beberapa waktu.

jsageryd
sumber
2
Documents mengatakan Anda tidak dapat memiliki cabang yang sama di kedua salinan yang berfungsi, yang merupakan batasan serius. Dengan Mercurial, itu hanya bekerja dengan masalah kecil.
hypersw
Tentu kamu bisa. Halaman manual mengatakan bagaimana; mencari --force. Tapi itu merepotkan jika Anda memperbarui cabang di satu tempat dan berharap untuk bekerja di tempat lain, karena meja kerja tidak diperbarui.
jsageryd
Yap, cabang di Mercurial adalah konsep yang lebih transparan dalam aspek ini. Bagaimana cabang dari satu worktree muncul di yang lain? Cara yang sama dengan banyak uplink? Eksperimen pertama saya dengan worktrees, dengan menjalankan fetch di keduanya, berakhir dengan dua (!) Pointer yang berbeda (!) origin/master.
hypersw
Sebuah worktree adalah (seperti namanya) hanya worktree, dengan beberapa fitur tambahan; repositori dibagi di antara semua meja kerja. Satu-satunya perbedaan antara dua worktrees adalah bahwa cabang check-out dapat (dan untuk alur kerja yang waras, adalah) berbeda. Dimungkinkan untuk melakukan dalam sebuah worktree yang terpisah, sehingga ia juga memiliki indeks sendiri (alias area pementasan) untuk membuatnya bekerja. The .gitfile dalam worktree terpisah adalah file teks yang berisi path ke konfigurasi, yang berada di repositori asli.
jsageryd
2
@WilsonF: git checkout --ignore-other-worktrees <branch> git-scm.com/docs/git-checkout/…
jsageryd
7

Saya awalnya tersandung pada pertanyaan ini setelah bertanya-tanya untuk apa meja kerja mewah ini dapat digunakan. Sejak itu saya telah mengintegrasikan mereka ke dalam alur kerja saya dan terlepas dari skeptisisme awal saya, saya datang untuk menemukan mereka cukup berguna.

Saya bekerja pada basis kode yang agak besar, yang membutuhkan waktu cukup lama untuk dikompilasi. Saya biasanya memiliki cabang pengembangan saat ini di mesin saya bersama dengan cabang fitur yang saat ini saya kerjakan ditambah cabang utama, yang mewakili keadaan saat ini dari sistem live.

Salah satu manfaat terbesar bagi saya adalah jelas bahwa saya tidak perlu mengkompilasi ulang seluruh hal setiap kali saya beralih cabang (yaitu, worktrees). Efek samping yang bagus adalah saya bisa pergi ke worktree pengembangan, melakukan hal-hal di sana, mengubah direktori ke worktree untuk cabang fitur saya saat ini dan kemudian rebase tanpa harus menarik terlebih dahulu.

rehabilitasi
sumber
4

Saya punya yang agak tidak biasa: Saya melakukan pengembangan Windows dan Linux pada mesin yang sama . Saya memiliki VirtualBox yang menjalankan Linux di dalam kotak Windows saya. VirtualBox memasang beberapa direktori Windows dan menggunakannya langsung di dalam mesin Linux. Ini memungkinkan saya menggunakan Windows untuk mengelola file tetapi membangun di Linux. Ini adalah proyek lintas-platform, jadi ini dibangun di atas Windows dan Linux dari struktur direktori yang sama.

Masalahnya adalah bahwa sistem pembangunan Linux dan Windows saling menabrak ketika digunakan dalam direktori yang sama; ada beberapa langkah membangun yang rumit untuk mengunduh pustaka, dll., yang menggunakan nama direktori yang sama. Versi Windows dari sistem build mengunduh perpustakaan khusus Windows, dan versi Linux dari sistem build mengunduh perpustakaan khusus Linux.

Di dunia yang ideal, sistem build akan dimodifikasi sehingga Windows & Linux dapat hidup berdampingan dalam direktori, tetapi untuk saat ini, masalahnya sedang ditangani dengan worktrees. Folder "Linux" dapat menghasilkan artefak build khusus Linux, dan folder "Windows" dapat menghasilkan artefak build spesifik Windows. Meskipun ini bukan solusi yang ideal, itu membuat sementara waktu yang bagus sambil menunggu bug sistem build ditangani.

Harus diakui, meja kerja tidak dirancang untuk ini; Saya harus menyimpan versi Windows dan versi Linux di cabang terpisah, walaupun saya lebih suka mereka berada di cabang yang sama. Tetap saja, ia melakukan pekerjaannya, dan merupakan kasus kerja yang agak tidak konvensional, menghemat hari.

Letakkan
sumber
+1 Ini sepertinya solusi yang sangat efektif untuk Make tidak melakukan direktori output build per-konfigurasi secara native. Saya memiliki setup VMware Workstation yang serupa dengan tamu Ubuntu dan macOS.
Tanz87
1

Dalam proyek baru untuk saya, saya telah membuat fitur. Tetapi beberapa spesifikasi gagal. Untuk membandingkan hasil dengan mastersaya membuat work-treerepo. Saya membandingkan hasil langkah demi langkah dalam menjalankan kode, sampai mengerti apa yang salah.

itsnikolay
sumber
Namun, bagaimana sebuah worktree membuat ini lebih mudah daripada sebuah kloning? Pertanyaannya bukan menanyakan preferensi pribadi, tetapi perbedaan nyata.
IInspectable
1

Saya menggunakan git worktreeuntuk pengembangan pembelajaran mesin.

Saya memiliki kode fungsional utama dan kemudian saya ingin membagi cabang percobaan yang berbeda (algoritma berbeda dan hyperparameter berbeda). git worktreememungkinkan saya untuk mengintegrasikan dvc bersama berbagai versi kode saya yang dikhususkan untuk algoritma yang berbeda. Setelah menjalankan semua pekerjaan pelatihan, saya mengevaluasi metrik akhir dan bergabung untuk menguasai cabang / model terbaik.

Ricardo MS
sumber