Panduan Git Bagian nomor 2: aturan emas dan dasar-dasar rebase lainnya

Mari kita lihat apa yang terjadi ketika Anda menjalankan git rebase dan mengapa Anda harus berhati-hati. 

Ini adalah bagian kedua dan ketiga dari panduan Git dari blog Pierre de Wulf yang diterjemahkan oleh tim Cloud Solutions . Bagian pertama bisa dibaca di sini .

Inti dari rebase


Bagaimana tepatnya rebase terjadi:


Anda dapat mengatakan bahwa rebase adalah untuk mencopot pemasangan cabang yang ingin Anda pindahkan dan menghubungkannya ke cabang lain. Definisi ini benar, tetapi cobalah untuk melihat sedikit lebih dalam. Jika Anda melihat dokumentasi , inilah yang dikatakan tentang rebase: "Terapkan komit ke cabang lain (Terapkan ulang di atas ujung pangkalan lain)".

Kata utama di sini adalah untuk diterapkan, karena rebase bukan hanya menyalin-menempel cabang ke cabang lain. Rebase secara berurutan mengambil semua komit dari cabang yang dipilih dan menerapkannya ke cabang baru.

Perilaku ini mengarah ke dua poin:

  1. Dengan menerapkan kembali komit, Git membuat komit baru. Bahkan jika mereka mengandung perubahan yang sama, maka Git dianggap sebagai komitmen baru dan independen.
  2. Git rebase menimpa komit dan tidak menghapus yang lama. Ini berarti bahwa setelah rebase selesai, komit lama Anda akan terus disimpan dalam subfolder / gjects dari folder .git. Jika Anda tidak sepenuhnya memahami bagaimana Git menyimpan dan mempertimbangkan komitmen, baca bagian pertama dari artikel ini.

Berikut ini adalah interpretasi yang lebih benar tentang apa yang terjadi selama rebase:


Seperti yang Anda lihat, cabang fitur berisi komit yang sama sekali baru. Seperti disebutkan sebelumnya, set perubahan yang sama, tetapi objek yang sama sekali baru dari sudut pandang Git. 

Ini juga berarti bahwa komitmen lama tidak dihancurkan. Mereka menjadi tidak bisa diakses secara langsung. Jika Anda ingat, cabang hanyalah tautan ke komit. Jadi, jika cabang atau tag tidak mengacu pada komit, itu tidak dapat diakses menggunakan Git, meskipun terus ada pada disk.

Sekarang mari kita bahas Aturan Emas.

Aturan rebase emas


Aturan emas rebase adalah: β€œ JANGAN PERNAH rebase cabang bersama! ". Cabang bersama mengacu pada cabang yang ada di repositori jaringan dan yang dapat digunakan oleh orang lain kecuali Anda.

Seringkali aturan ini diterapkan tanpa pemahaman yang tepat, oleh karena itu, kami akan menganalisis mengapa itu muncul, terutama karena itu akan membantu untuk lebih memahami pekerjaan Git.

Mari kita lihat situasi di mana pengembang melanggar aturan emas, dan apa yang terjadi dalam kasus ini.

Misalkan Bob dan Anna bekerja bersama dalam sebuah proyek. Di bawah ini adalah bagaimana repositori Bob dan Anna dan repositori asli di GitHub terlihat seperti:


Semua pengguna memiliki repositori yang disinkronkan dengan GitHub.

Sekarang Bob, melanggar aturan emas, melakukan rebase, dan pada saat yang sama, Anna, yang bekerja di cabang fitur, menciptakan komit baru:


Apakah Anda melihat apa yang akan terjadi?

Bob mencoba untuk melakukan komit push, ia mendapat penolakan seperti ini:


Git tidak berhasil karena Git tidak tahu bagaimana menggabungkan cabang fitur Bob dengan cabang fitur GitHub.

Satu-satunya solusi yang memungkinkan Bob untuk mendorong adalah dengan menggunakan tombol paksa, yang memberitahu repositori GitHub untuk menghapus cabang fitur dan menerima salah satu yang mendorong Bob untuk cabang ini. Setelah itu kita mendapatkan situasi berikut:


Sekarang Anna ingin meluncurkan perubahannya, dan inilah yang akan terjadi:


Ini normal, Git memberi tahu Anna bahwa dia tidak memiliki versi yang disinkronkan dari cabang fitur, yaitu versinya tentang cabang dan versi cabang di GitHub berbeda. Anna harus menyelesaikan tarikannya. Dengan cara yang sama ketika Git menggabungkan cabang lokal dengan cabang di repositori saat Anda mendorong, Git mencoba untuk menggabungkan cabang di repositori dengan cabang lokal saat Anda menarik.

Sebelum melakukan tarik komitmen di cabang lokal dan GitHub terlihat seperti ini:

A--B--C--D'   origin/feature // GitHub
A--B--D--E    feature        // Anna

Saat Anda menarik, Git bergabung untuk menghilangkan perbedaan dalam repositori. Jadi, apa yang menyebabkan hal ini:


Komit M adalah gabungan komit. Akhirnya, cabang fitur Anna dan GitHub sepenuhnya digabungkan. Anna menghela nafas lega, semua konflik terselesaikan, dia bisa melakukan dorongan. 

Bob menarik, sekarang semuanya sinkron:


Melihat kekacauan yang dihasilkan, Anda harus memastikan pentingnya aturan emas. Juga perlu diingat bahwa kekacauan seperti itu dibuat oleh hanya satu pengembang dan pada cabang yang dibagi antara hanya dua orang. Bayangkan berada dalam tim yang terdiri dari sepuluh orang. 

Salah satu dari banyak manfaat Git adalah Anda dapat kembali tanpa masalah kapan pun. Tetapi semakin banyak kesalahan dibuat, seperti dijelaskan, semakin sulit untuk melakukannya.

Juga catat bahwa duplikat komit muncul di repositori jaringan. Dalam kasus kami, D dan D ', berisi data yang sama. Faktanya, jumlah komit duplikat bisa sama besar dengan jumlah komit di cabang rebased Anda.

Jika Anda masih belum yakin, mari kenalkan Emma, ​​pengembang ketiga. Dia bekerja di cabang fitur sebelum Bob membuat kesalahan dan saat ini ingin mendorong. Misalkan pada saat dia mendorong skrip kecil kita sebelumnya telah selesai. Inilah yang keluar:


Oh, Bob itu !!!!

Teks ini mungkin membuat Anda berpikir bahwa rebase hanya digunakan untuk memindahkan satu cabang ke atas cabang lainnya. Ini opsional - Anda dapat rebase di cabang yang sama.

Kecantikan menarik rebase


Seperti yang Anda lihat di atas, masalah Anna bisa dihindari jika dia menggunakan pull rebase. Mari kita bahas pertanyaan ini lebih detail.

Katakanlah Bob bekerja di cabang yang menyimpang dari tuan, maka ceritanya mungkin terlihat seperti ini:




Bob memutuskan bahwa inilah saatnya untuk menarik, yang, seperti yang sudah Anda pahami, akan menimbulkan kebingungan. Karena repositori Bob pindah dari GitHub, Git akan bertanya apakah penggabungan dilakukan, dan hasilnya akan seperti ini:


Solusi ini berfungsi dan berfungsi dengan baik, namun mungkin bermanfaat bagi Anda untuk mengetahui bahwa ada solusi lain untuk masalah tersebut. Salah satunya adalah pull-rebase.

Ketika Anda melakukan pull-rebase, Git mencoba mencari tahu komit mana yang hanya ada di cabang Anda dan yang ada di repositori jaringan. Git kemudian menggabungkan komit dari repositori jaringan dengan hadiah komit terbaru di repositori lokal dan jaringan. Kemudian rebase komitmen lokal Anda ke ujung cabang. 

Kedengarannya rumit, jadi kami ilustrasikan:

  1. Git hanya memperhatikan komit yang ada di repositori Anda dan jaringan:

    Sepertinya klon lokal dari repositori GitHub.
  2. Git rebase commit lokal:


Seperti yang Anda ingat, ketika rebit Git berlaku komit satu per satu, yaitu, dalam hal ini berlaku master commit E, lalu F. ke ujung cabang. Hasilnya adalah rebase ke dirinya sendiri. Kelihatannya bagus, tetapi muncul pertanyaan - mengapa ini dilakukan?

Menurut pendapat saya, masalah terbesar dengan menggabungkan cabang adalah bahwa sejarah komit terpolusi. Karena itu, pull-rebase adalah solusi yang lebih elegan. Saya bahkan akan melangkah lebih jauh dan mengatakan bahwa ketika Anda perlu mengunduh perubahan terbaru ke cabang Anda, Anda harus selalu menggunakan pull-rebase. Tetapi Anda harus ingat: karena rebase menerapkan semua commit secara bergantian, ketika Anda rebase 20 commit, Anda mungkin harus menyelesaikan 20 konflik satu demi satu. 

Biasanya, Anda dapat menggunakan pendekatan berikut: satu perubahan besar yang dibuat di masa lalu adalah penggabungan, dua perubahan kecil yang dilakukan baru-baru ini merupakan pull-rebase.

Kekuatan rebase ke


Misalkan riwayat komit Anda terlihat seperti ini:




Jadi, Anda ingin rebase fitur 2 cabang ke cabang master. Jika Anda melakukan rebase reguler pada cabang master, dapatkan ini:


Tidak masuk akal bahwa komit D ada di kedua cabang: di fitur 1 dan fitur 2. Jika Anda memindahkan cabang fitur 1 ke ujung cabang master, ternyata komit D akan diterapkan dua kali.

Misalkan Anda perlu mendapatkan hasil yang berbeda:


Untuk mengimplementasikan skenario seperti itu, git rebase adalah apa yang dimaksudkan.

Pertama, baca dokumentasinya:

SYNOPSIS
       git rebase [-i | --interactive] [<options>] [--exec <cmd>]
               [--onto <newbase> | --keep-base] [<upstream> [<branch>]]
       git rebase [-i | --interactive] [<options>] [--exec <cmd>] 
[--onto <newbase>]
               --root [<branch>]
       git rebase (--continue | --skip | --abort | --quit | --edit-todo 
| --show-current-patch)


Kami tertarik pada ini:

OPTIONS
       --onto <newbase>
          Starting point at which to create the new commits. If the 
--onto option is not specified, the starting point is <upstream>. May be 
any valid commit, and not just an existing branch name.


Gunakan opsi ini untuk menunjukkan pada titik mana untuk membuat komit baru.

Jika opsi ini tidak ditentukan, maka hulu akan menjadi titik awal.

Untuk pemahaman, saya akan memberikan satu gambar lagi:

A--B--C        master
    \
     D--E      feature1
         \
          F--G feature2

Here we want to rebase feature2 to master beginning from feature1
                           |                                |
                        newbase                         upstream


Yaitu, cabang utama adalah basis baru, dan cabang fitur 1 adalah hulu.

Jadi, jika Anda ingin mendapatkan hasilnya seperti pada gambar terakhir, Anda harus menjalankan git rebase --untuk master feature1 di cabang feature2.

Semoga berhasil

Diterjemahkan dengan dukungan dari Mail.ru Cloud Solutions .

Apa lagi yang harus dibaca pada topik :

  1. Bagian pertama dari panduan Git.
  2. Tahun kedua saya sebagai pengembang independen .
  3. Saluran telegram kami tentang transformasi digital


All Articles