Bagaimana dan mengapa mencuri pohon di git

pohon


Pada artikel ini saya akan berbicara tentang satu trik yang bermanfaat, tetapi sedikit diketahui untuk bekerja dengan git - cara mudah membuat komit menggunakan pohon dari komit lain. Sederhananya, cara mendapatkan status proyek yang diinginkan di cabang mana pun, jika status ini sudah ada di suatu tempat dan di suatu tempat di repositori sebelumnya. Beberapa contoh akan diberikan tentang bagaimana ini memungkinkan untuk menyelesaikan beberapa masalah praktis secara elegan. Dan khususnya, saya akan berbicara tentang metode yang saya temukan, yang dapat sangat menyederhanakan koreksi beberapa konflik selama rebase. Selain itu, artikel ini adalah cara yang bagus untuk memahami dalam praktik apa yang merupakan komitmen dalam git.


Isi


Bagian teoretis. Tentang komit dan pepohonan
git commit-tree
Bagian praktis
1. Sinkronisasi dengan cabang lain
2. Perbandingan dua cabang
3. Pembalikan Cabang
4. Kebalikan sebagian
5. Penggabungan buatan
6a. Metode rebase melalui penggabungan - deskripsi
6b. Metode rebase melalui skrip gabungan
7. Alias
Kesimpulan



Bagian teoretis. Tentang komit dan pepohonan


Berkomitmen mungkin adalah konsep paling dasar di git, mari kita lihat apa itu terdiri. Setiap komit memiliki pengenal uniknya sendiri dalam bentuk hash, misalnya 5e45ecb . Dan dengan perintah berikut, mengetahui hash, kita bisa melihat isinya.


git cat-file -p 5e45ecb 

 tree 8640790949c12690fc71f9abadd7b57ec0539376 parent 930741d1f5fd2a78258aa1999bb4be897ba3d015 author Mark Tareshawty <tareby...@github.com> 1542718283 -0500 committer Mark Tareshawty <tareby...@github.com> 1542718283 -0500 gpgsig -----BEGIN PGP SIGNATURE----- ... -----END PGP SIGNATURE----- Fix scoping so that we don't break the naming convention 

Beberapa baris ini adalah seluruh isi dari commit:


  • tree - tautan ke status proyek tertentu
  • parent - tautan ke commit orang tua
  • penulis - penulis dari komit asli + tanggal
  • committer - pencipta tanggal komit + ini
  • gpgsig - tanda tangan digital (jika tersedia)
  • pesan - komit teks

Biarkan saya mengingatkan Anda bahwa komit di git (tidak seperti VCS lainnya) tidak menjelaskan perubahan yang dilakukan. Sebaliknya: setiap komit menggambarkan keadaan spesifik proyek secara keseluruhan, dan apa yang kita lihat sebagai perubahan yang dibuat sebenarnya merupakan perbedaan yang dihitung secara dinamis dibandingkan dengan keadaan sebelumnya. Perlu juga dicatat bahwa semua commit tidak dapat diubah (immutable), yaitu, misalnya, dengan rebase / cherry-pick / amend, komitmen yang benar-benar baru dibuat.


tree (tree) - pada kenyataannya, itu hanya folder dengan konten abadi yang spesifik. Objek jenis pohon berisi daftar file dengan konten spesifik (gumpalan) dan subfolder (pohon). Dan pohon yang masing-masing komit menunjuk adalah folder root dari proyek, atau lebih tepatnya keadaan spesifiknya.


lihat isi pohon

Ini dapat dilakukan dengan cara yang persis sama untuk objek lain (komit / pohon / gumpalan), dan cukup untuk mengambil beberapa karakter hash unik pertama: 8640790949c12690fc71f9abadd7b57ec0539376 -> 8640790.


 git cat-file -p 8640790 

 100644 blob 7ab08294a46f158c51460be3e7df6a190e15023b .env.example 100644 blob 0a1a4d1ad9ff3f35b67678ca893811e91b423af5 .gemset 040000 tree 033aa38ce0eab11fe229067c14ccce95e2b8b601 .github 100644 blob ca49bb7ffa6273b0be4ce7ba1accba456032fb11 .gitignore 100644 blob c99d2e7396e14ac072c63ec8419d9b8fede28d86 .rspec 100644 blob 65e77a2f59f635a8f24eb4714e8e43745c5c0eb9 .rubocop.yml 100644 blob 8e8299dcc068356889b365e23c948b92c6dfcd78 .ruby-version 100644 blob 19028f9885948aca2ba61f9d062e9dc21c21ad03 .stylelintrc.json 100644 blob 2f7a032fbc3f4f7195bfd91cb33889a684b572b9 .travis.yml 100644 blob 121615722a6c206a9fe24b9a1c9b647662a460d2 ARCHITECTURE.md 100644 blob 898195daeea0bbf8c5930deeaf1020ba8abab34a Gemfile 100644 blob de7ca707f9fe9172db941b65cdacaba7e024fc06 Gemfile.lock 100644 blob e6ff62fefd071b1a8ca279bae94ddbc4dd17b7a3 Gruntfile.js 100644 blob 0cac5b30fb32d36cce2aeb7d936be7b6207d68c7 MIT-LICENSE.txt 100644 blob c2c566e8cc3d440d3ee8041b79cded416db28136 Procfile 100644 blob d1fb2f575380e1e093a4d82e3f19e51f0b99a0a1 Procfile.dev 100644 blob 3a88e138f10fa65bd2cfe1a1d3292348205508b5 README.md 100644 blob 5366e6e073cc426518894cc379d3a07cf3c9cfb3 Rakefile 100644 blob e6d3d2d3e9d5122c5f75bbeee8ed0917ad38c131 app.json 040000 tree 94f83cf03bd6f1cf14672034877b14604744b7a2 app 040000 tree d4d859e82564250b4c4f2047de21e089e7555475 bin 100644 blob 1f71007621f17334fd6f2dd71c87b7a16867119c config.ru 040000 tree 9e8e4bf5ec44541aefff544672b94ca8a9d07bbf config 040000 tree 31b8d0e1fa2bb789dbd6319e04fc9f115952cf2a db 040000 tree 38e7a13e0e772c2a13e46d2007e239f679045bee doc 040000 tree a6e35ded8b35837660cf786e637912377f845515 lib 040000 tree d564d0bc3dd917926892c55e3706cc116d5b165e log 100644 blob 843523565ddee5e00f580d9c4e37fc2478fdaecc package-lock.json 100644 blob 791ee833ad316d75b1d2c83a64a3053fc952d254 package.json 040000 tree 4645317c52675d9889f89b26f4dd4d2ae1d8cbad public 040000 tree 31d3f8ae4a4ffe62787134642743ed32a35dbae2 resources 040000 tree 807ffa29868ef9c25ddb4b4126a4bb7f1b041bf0 script 040000 tree 4c3bf9a7f3679ba059b0f1c214a500d197546462 spec 040000 tree 136c8174412345531a9542cafef25ce558d2664f test 040000 tree e6524eafe066819e4181bc56c503320548d8009b vendor 

Ini sebenarnya fitur yang paling penting dari cara kerja git, pengidentifikasi komit benar-benar hash dari isinya. Sama seperti hash benda yang tertanam di dalamnya (pohon, gumpalan).


Sekarang mari kita lihat apa yang terjadi ketika kita melakukannya


 git commit -m "Fixed bug" 

Perintah ini menciptakan komit baru yang menangkap yang berikut ini:


  • status proyek pementasan (disimpan sebagai objek pohon baru dan hashnya diambil)
  • tautan ke komit (orang tua) saat ini
  • penulis + committer + dua tanggal
  • komit teks

Ini semua disimpan, hash, dan objek komit baru diperoleh. Dan tim secara otomatis menaikkan pointer cabang saat ini ke sana.


sedikit tentang terminologi

Seperti yang sudah kita ketahui, pohon adalah objek yang berisi keadaan proyek pada titik tertentu di masa lalu - ketika komit dibuat dengan pohon ini.


Folder kerja disebut working tree / copy pekerjaan / direktori kerja, yang cukup logis.


Kami juga memiliki - staging area / index - area perubahan yang disiapkan. Namun secara logis, ini juga sebuah pohon , atau lebih tepatnya, keadaan yang disimpan ketika melakukan sebagai pohon. Oleh karena itu, menurut saya lebih logis untuk memanggil pohon yang dipentaskan.



git commit-tree


Akhirnya, kita dapat melanjutkan dengan menjelaskan perintah git commit-tree yang kita butuhkan. Secara formal, ini adalah salah satu perintah tingkat rendah, sehingga jarang disebutkan dan digunakan. Kami tidak akan mempertimbangkan perintah tingkat rendah lainnya yang terkait dengannya (seperti pohon git write, git-update-index, mereka juga dikenal sebagai perintah pipa ledeng). Kami hanya tertarik pada satu konsekuensi tertentu: dengan perintah ini kami dapat dengan mudah menyalin (menggunakan kembali) pohon status proyek dari komit lainnya.


Lihatlah tantangannya


 git commit-tree 4c835c2 -m "Fixed bug" -p a8fc5e3 

 d9aded78bf57ca906322e26883644f5f36cfdca5 

Perintah git commit-tree juga melakukan, tetapi dengan cara tingkat rendah. Di sini Anda harus secara eksplisit menentukan pohon yang sudah ada (pohon) 4c835c2 dan tautan ke induk melakukan a8fc5e3. Dan mengembalikan hash dari commit baru d9aded7, dan posisi cabang tidak berubah (oleh karena itu, commit ini tampaknya membeku di udara).



Bagian praktis


Contoh-contoh penggunaan perintah ini ditunjukkan dalam repositori sederhana berikut.



Ini berisi tiga cabang:


master - cabang utama
alpha - cabang tempat kita bekerja dan berada
beta - cabang yang sebelumnya macet di master


Semua tindakan mudah diulang secara lokal, karena ini sudah cukup untuk mengkloning repositori, dapatkan di cabang alpha dan kemudian jalankan perintah dari contoh. Keadaan awal ini umum untuk semua contoh.


 git clone https://github.com/capslocky/git-commit-tree-example.git cd ./git-commit-tree-example/ git checkout alpha 

di bawah jendela

Semua perintah, termasuk skrip, juga berfungsi di bawah windows. Anda hanya perlu membuka terminal bash di folder proyek, misalnya, seperti ini


 "C:\Program Files\Git\git-bash.exe" --cd="D:\path\project" 


1. Sinkronisasi dengan cabang lain


Tantangan:
Sinkronisasi status proyek pada cabang alpha dengan cabang beta . Artinya, Anda perlu membuat komit baru di cabang alpha sehingga keadaan proyek menjadi persis sama dengan di cabang beta .


Secara khusus, tugas seperti itu tidak mungkin pernah muncul, tetapi ini adalah kasus yang paling cocok untuk menunjukkan pendekatan tersebut.


Solusi paling sederhana adalah dengan mengambil pohon yang sudah ada yang ditunjuk oleh cabang beta dan arahkan saja dari komit baru untuk cabang alpha. Karena ini adalah contoh pertama, semua logikanya dipertimbangkan dengan cukup detail.


Pertama, temukan hash komit yang ditunjukkan oleh cabang beta:


 git rev-parse origin/beta 

 280c30ff81a574f8dd41721726cf60b22fb2eced 

280c30f - ambil saja beberapa karakter pertama


Sekarang temukan hash dari tree-nya dengan menampilkan isi dari commit melalui file-git cat:


 git cat-file -p 280c30f 

 tree 3c1afe75f54518dbd82ea7a4e3c4ff50389a573a <--- parent 560b449675513bc8f8f4d6cda56a922d4e36917a author Baur <atanov...@gmail.com> 1540619512 +0600 committer Baur <atanov...@gmail.com> 1540619512 +0600 Added info about windows 

3c1afe7 - ini adalah pohon yang kita butuhkan


Dan sekarang kita akan membuat komit menunjuk ke pohon ini, dan dengan komit induk kita akan menunjukkan komit saat ini:


 git commit-tree 3c1afe7 -m "Synced with branch 'beta'" -p HEAD 

 eb804d403d4ec0dbeee36aa09da706052a7cc687 

Itu saja, komit dibuat, tim mendapat hash-nya. Selain itu, nilai ini akan selalu unik, karena dihitung tidak hanya dari pohon, tetapi juga dari penulis dan waktu. Komit itu sendiri dibekukan di udara, asalkan tidak memasuki cabang mana pun. Cukup bagi kami untuk mengambil beberapa karakter pertama: eb804d4 , nilai ini, unik untuk setiap kasus, saya akan tunjuk sebagai xxxxxxx . Mari kita lihat isinya:


 git cat-file -p xxxxxxx 

 tree 3c1afe75f54518dbd82ea7a4e3c4ff50389a573a <--- parent 64fafc79e8f6d22f5226490daa5023062299fd6c author Peter <peter...@gmail.com> 1545230299 +0600 committer Peter <peter...@gmail.com> 1545230299 +0600 Synced with branch 'beta' 

Hebat, ia memiliki pohon yang sama dengan komit pada cabang asal / beta. Dan karena komit ini adalah turunan langsung dari cabang saat ini, untuk memasukkannya ke dalam cabang, buat penggabungan maju-cepat


 git merge --ff xxxxxxx 

 Updating 64fafc7..xxxxxxx Fast-forward Azure.txt | 3 --- Bill.txt | 6 +----- Linus.txt | 15 +++++++++++++++ 3 files changed, 16 insertions(+), 8 deletions(-) 

Selesai Sekarang keadaan proyek pada cabang alpha persis sama dengan pada cabang beta. [perbarui] Dan jika Anda melihat fakta bahwa komit ini memang berubah, kita akan melihat: ia membalik semua komit alfa cabang (perubahan) dan menambahkan semua komit beta unik (perubahan) ke leluhur komit yang sama.




2. Perbandingan dua cabang


Tantangan:
Bandingkan cabang alpha dengan cabang beta .


Contoh pertama menunjukkan bahwa komit yang dibuat menunjukkan semua perubahan yang merupakan perbedaan aktual antara kedua cabang. Properti ini memudahkan untuk membandingkan satu cabang dengan cabang lainnya. Cukup membuat cabang sementara ketiga dan membuat komit serupa di dalamnya.


Jadi, pertama, kembalikan cabang alpha ke kondisi semula


 git reset --hard origin/alpha 

Mari kita membuat cabang temp pada yang sekarang dan berdiri di atasnya


 git checkout -b temp 

Dan kita dibiarkan melakukan hal yang sama seperti pada contoh sebelumnya. Tapi kali ini kita akan bertemu satu baris. Untuk melakukan ini, kami menggunakan sintaks khusus untuk mengakses asal komit / beta ^ {tree} atau 280c30f ^ {tree} yang sama .


 git merge --ff $(git commit-tree origin/beta^{tree} -m "Diff with branch 'beta'" -p HEAD) 

Selesai, pada dasarnya kami terwujud sebagai perbedaan komit antara dua cabang


 git show 

 git diff alpha origin/beta 

Tentu saja, kita dapat membuat komit β€œkomparatif” untuk dua komit (status) di repositori.




3. Pembalikan Cabang


Tantangan:
Kembalikan beberapa komitmen terakhir.


Mari kita kembali ke cabang alpha dan menghapus cabang temp


 git checkout alpha git branch -D temp 

Misalkan kita perlu memutar kembali dua commit terakhir pada cabang alpha. Ada dua cara klasik untuk melakukan ini:


  1. Jalankan git revert dua kali - per komit
  2. git reset, mis. atur ulang posisi cabang

Tetapi Anda bisa melakukan ini dengan cara ketiga:


 git merge --ff $(git commit-tree 7a714bf^{tree} -m "Reverted to commit 7a714bf" -p HEAD) 

Ini akan menambahkan satu komit baru yang mengembalikan perubahan dari dua komit sebelumnya. Berbeda dengan metode pertama, hanya satu komit yang dibuat, bahkan jika Anda perlu memutar mundur sepuluh komit terakhir. Dan perbedaan antara metode dengan git reset adalah kita tidak membuang commit ini dari cabang itu sendiri.


Selanjutnya, jika kemudian Anda perlu mengembalikan keadaan asli cabang, maka ini dapat dilakukan dengan cara yang sama


 git merge --ff $(git commit-tree 64fafc7^{tree} -m "Reverted back to commit 64fafc7" -p HEAD) 

Pada saat yang sama, kedua komitmen ini akan tetap dalam sejarah cabang, yang menurutnya akan ditarik kembali dan dikembalikan.




4. Kebalikan sebagian


Tantangan:
Kembalikan perubahan ke beberapa file selama beberapa komit terakhir.


Sekali lagi, kembalikan cabang alpha ke kondisi semula


 git reset --hard origin/alpha 

Cabang alpha berisi 3 commit, di mana setiap perubahan dilakukan pada file Bill.txt, pada komit terakhir, file Azure.txt juga ditambahkan. Misalkan kita perlu memutar kembali perubahan ke file Bill.txt untuk 2 commit terakhir, tanpa menyentuh file lainnya.


Pertama, putar kembali semua file 2 yang dikomit kembali


 git merge --ff $(git commit-tree 7a714bf^{tree} -m "any text" -p HEAD) 

Selanjutnya, kembalikan cabang ke komit sebelumnya, tetapi tanpa menyentuh status proyek pada disk


 git reset HEAD~1 

Dan sekarang sudah cukup untuk zasteydit file yang diperlukan dan komit, dan perubahan lainnya dapat dibuang.


 git add Bill.txt git commit -m "Reverted file Bill.txt to 7a714bf" git reset --hard HEAD 



5. Penggabungan buatan


Tantangan:
Lonjakan satu cabang ke cabang lainnya, dapatkan hasil yang telah ditentukan.


Bayangkan situasi ini. Bug kritis telah terdeteksi dalam produksi, dan seperti biasa, bug itu harus segera diperbaiki. Namun, tidak jelas berapa banyak waktu yang diperlukan untuk mempelajarinya dan membuat perbaikan terbaru yang benar, sehingga perbaikan cepat sementara dibuat dengan cepat, yang mengisolasi interaksi dengan modul masalah. Jadi, di cabang master, komit muncul dengan tambalan sementara ini, dan setelah beberapa waktu alih-alih sebagai master, Anda perlu menginjak perbaikan terbaru yang sudah penuh.


Jadi, kita perlu membuat menggabungkan cabang alpha di master, tetapi ini tidak boleh menjadi gabungan tradisional ketika semua perubahan unik dari cabang alpha ditambahkan ke master dari atas dan ada konflik, dan kita harus sepenuhnya menimpa master dengan cabang alpha.


Untuk memulainya, mari kita ingat apa yang dimaksud dengan menggabungkan komit - ini sebenarnya komit biasa yang sama, tetapi hanya memiliki dua komitmen induk, ini terlihat jelas jika Anda melihat isinya (bagaimana pohonnya dibentuk adalah masalah yang terpisah) . Dan siapa yang ditentukan oleh siapa yang sederhana - komit orang tua pertama dianggap yang utama.


 git cat-file -p 7229df8 

 tree 3c1afe75f54518dbd82ea7a4e3c4ff50389a573a parent fd54ab7dde87593b9892b6d1ffbf1afd39ba6f9e parent 280c30ff81a574f8dd41721726cf60b22fb2eced author Baur <atanov...@gmail.com> 1540619579 +0600 committer Baur <atanov...@gmail.com> 1540619592 +0600 Merge branch 'beta' into 'master' 

Atur ulang cabang alpha saat ini dan beralih ke master


 git reset --hard origin/alpha git checkout master 

Dan sekarang tim yang sama, tetapi dengan komitmen dua orang tua


 git merge --ff $(git commit-tree alpha^{tree} -m "Merge 'alpha' into 'master', but take 'alpha' tree" -p HEAD -p alpha) 

Selesai, kami mementaskan cabang alpha di master, dan kami tidak harus menghapus kode sementara dan menyelesaikan konflik, karena dalam kasus ini kami hanya perlu menulis ulang perubahan terbaru.



Sebenarnya, tidak terlalu aneh untuk membuat gabungan dengan pohon yang disalin dari komit lain. Situasi seperti itu dapat muncul karena git adalah alat yang sangat fleksibel yang memungkinkan Anda untuk menerapkan berbagai pendekatan untuk bekerja dengan cabang dan repositori. Tapi tetap saja, contoh paling umum adalah di repositori kami sejak awal - coba parsing sendiri atau buka spoiler untuk membaca penjelasannya.


spoiler

Mari kita perhatikan bagaimana cabang beta dicekik kembali untuk dikuasai. Selama waktu ketika dua komit muncul di dalamnya, tidak ada komit baru di cabang master itu sendiri. Ini berarti bahwa dengan menggabungkan beta dalam master, setiap konflik dikecualikan karena perubahan simultan.




Jika kita melakukan git merge beta, maka gabungan fast-forward (perilaku default ) akan terjadi, yaitu, cabang master hanya akan berdiri di komit yang sama dengan cabang beta, dan tidak akan ada gabungan komit. Akan seperti ini:



Tapi di sini tidak ada gabungan fast-forward dibuat menggunakan perintah git merge beta --no-ff. Artinya, kami memaksa penciptaan komit gabungan, meskipun itu tidak perlu. Dan karena keadaan akhir yang diinginkan dari proyek untuk penggabungan di masa depan diketahui - ini adalah pohon beta, git cukup menyalin tautan ke pohon ini ke dalam sebuah komit baru:


 git cat-file -p origin/beta 

 tree 3c1afe75f54518dbd82ea7a4e3c4ff50389a573a <--- parent 560b449675513bc8f8f4d6cda56a922d4e36917a author Baur <atanov...@gmail.com> 1540619512 +0600 committer Baur <atanov...@gmail.com> 1540619512 +0600 Added info about windows 

 git cat-file -p 7229df8 

 tree 3c1afe75f54518dbd82ea7a4e3c4ff50389a573a <--- parent fd54ab7dde87593b9892b6d1ffbf1afd39ba6f9e parent 280c30ff81a574f8dd41721726cf60b22fb2eced author Baur <atanov...@gmail.com> 1540619579 +0600 committer Baur <atanov...@gmail.com> 1540619592 +0600 Merge branch 'beta' into 'master' 


6a. Metode rebase melalui penggabungan - deskripsi


Tantangan:
Perlu untuk membuat cabang rebase "berat" (banyak konflik pada komitmen yang berbeda).


Ada tema holivar klasik di git - rebase vs merge. Tapi saya tidak akan holivarit. Sebaliknya, saya akan berbicara tentang bagaimana mereka dapat menjadi teman dalam konteks tugas ini.


Secara umum, git telah dirancang khusus sehingga kita dapat melakukan penggabungan secara efektif. Dan ketika saya datang ke proyek di mana alur kerja didasarkan pada rebase, pertama kali saya merasa tidak nyaman dan tidak biasa, sampai saya mengembangkan teknik yang menyederhanakan pekerjaan saya sehari-hari dengan git. Salah satunya adalah metode asli saya untuk melakukan rebase berat.


Jadi, kita perlu me-rebase cabang alpha pada pengembangan, sehingga nantinya akan diwarnai secantik cabang beta. Jika kita mulai rebase seperti biasa, komit pertama dan terakhir akan menghasilkan dua konflik yang berbeda di dua tempat yang berbeda. Tetapi jika alih-alih rebase kita hanya melakukan penggabungan, hanya akan ada satu konflik di satu tempat di satu komit gabungan.


Jika Anda ingin memastikan ini, saya menawarkan tim siap pakai di bawah spoiler.


Teks tersembunyi

Kembalikan cabang ke keadaan semula


 git checkout master git reset --hard origin/master git checkout alpha git reset --hard origin/alpha 

Buat dan tahan di cabang alpha-rebase-konflik dan rebase pada master


 git checkout -b alpha-rebase-conflicts git rebase master 

Akan ada konflik di berbagai komitmen, termasuk konflik hantu.


Sekarang mari kita coba penggabungan, kembali ke cabang alpha dan hapus cabang untuk rebase.


 git checkout alpha git branch -D alpha-rebase-conflicts 

Beralih ke master dan gabungkan


 git checkout master git merge alpha 

Hanya akan ada satu konflik sederhana, kami memperbaikinya dan melakukannya


 git add Bill.txt git commit -m "Merge branch 'alpha' into 'master'" 

Marge berhasil diselesaikan.


Konflik Git adalah bagian alami dari kehidupan kita, dan contoh sederhana ini menunjukkan bahwa menggabungkan jelas lebih nyaman daripada rebase dalam hal ini. Dalam proyek nyata, perbedaan ini diukur dengan jumlah waktu dan saraf yang jauh lebih besar. Oleh karena itu, misalnya, ada rekomendasi yang ambigu untuk memeras semua komit dari cabang fitur menjadi satu komit sebelum penggabungan.


Gagasan metode ini adalah untuk membuat penggabungan tersembunyi sementara di mana kami akan menyelesaikan semua konflik sekaligus. Ingat hasilnya (pohon). Selanjutnya, jalankan rebase biasa, tetapi dengan opsi "menyelesaikan konflik secara otomatis, memilih perubahan kami." Dan pada akhirnya, tambahkan satu komit tambahan ke cabang, yang akan mengembalikan pohon yang benar.


Mari kita mulai. Sekali lagi, kembalikan kedua cabang ke kondisi semula.


 git checkout master git reset --hard origin/master git checkout alpha git reset --hard origin/alpha 

Mari kita membuat temp cabang sementara di mana kita akan membuat penggabungan.


 git checkout -b temp git merge origin/master 

Konflik.


Mari kita selesaikan satu konflik sederhana dalam file Bill.txt seperti biasa (di editor mana pun).
Perhatikan bahwa hanya ada satu konflik, dan bukan dua, seperti rebase.


 git add Bill.txt git commit -m "Merge branch 'origin/master' into 'temp'" 

Kami kembali ke cabang alpha, melakukan rebase dengan resolusi otomatis dari semua konflik yang menguntungkan kami, dan membawa temp cabang ke negara, dan menghapus temp cabang itu sendiri.


 git checkout alpha git rebase origin/master -X theirs git merge --ff $(git commit-tree temp^{tree} -m "Fix after rebase" -p HEAD) git branch -D temp 


Akhirnya, alfa mergim indah di master.


 git checkout master git merge alpha --no-ff --no-edit 


Perhatikan bahwa master, alpha dan cabang temp jarak jauh ketiganya menunjuk ke pohon yang sama, meskipun ini adalah tiga commit yang berbeda.


Kontra dari metode ini:


  • Tidak ada koreksi manual dari setiap komitmen konflik - konflik diselesaikan secara otomatis. Komit perantara semacam itu mungkin tidak dikompilasi.
  • Menambahkan (tetapi tidak selalu) komitmen ekstra pada setiap rebase

Pro:


  • Kami hanya memperbaiki konflik nyata (tidak ada konflik hantu)
  • Semua konflik diperbaiki hanya satu kali.
  • Dua poin pertama menghemat waktu
  • Riwayat komit lengkap dan semua perubahan disimpan (misalnya, Anda dapat memilih-ceri)
  • Metode ini diterapkan dalam bentuk naskah dan selalu dapat digunakan untuk rebase jika perlu (tidak memerlukan pengetahuan tentang pohon dan sebagainya)


6b. Metode rebase melalui skrip gabungan


Skrip diterbitkan di sini: https://github.com/capslocky/git-rebase-via-merge


Mari kita periksa pekerjaannya pada contoh kita. Sekali lagi, kembalikan kedua cabang ke kondisi semula


 git checkout master git reset --hard origin/master git checkout alpha git reset --hard origin/alpha 

Unduh skrip dan buat itu bisa dieksekusi


 curl -L https://git.io/rebase-via-merge -o ~/git-rebase-via-merge.sh chmod +x ~/git-rebase-via-merge.sh 

windows

File akan muncul di sini: C: \ Users \ user-name \ git-rebase-via-merge.sh


Ubah cabang default yang perlu Anda rebase, dalam kasus kami kami membutuhkan sumber / master


 nano ~/git-rebase-via-merge.sh 

 default_base_branch='origin/master' 

Mari kita juga membuat dan berdiri di cabang sementara agar tidak menyentuh cabang alpha itu sendiri


 git checkout -b alpha-rebase-test 

Dan sekarang Anda dapat menjalankan skrip (bukan git rebase asal / master tradisional)


 ~/git-rebase-via-merge.sh 


hasil skrip
 $ ~/git-rebase-via-merge.sh This script will perform rebase via merge. Current branch: alpha-rebase-test (64fafc7) Base branch: origin/master (9c6b60a) Continue (c) / Abort (a) c Auto-merging Bill.txt CONFLICT (content): Merge conflict in Bill.txt Automatic merge failed; fix conflicts and then commit the result. You have at least one merge conflict. Fix all conflicts in the following files, stage them up and type 'c': Bill.txt Continue (c) / Abort (a) c [detached HEAD 785d49e] Hidden temp commit to save result of merging 'origin/master' into 'alpha-rebase-test' as detached head. Merge succeeded on hidden commit: 785d49e Starting rebase automatically resolving any conflicts in favor of current branch. First, rewinding head to replay your work on top of it... Auto-merging Bill.txt [detached HEAD a680316] Added history of windows Author: Baur <atanov...@gmail.com> Date: Sat Oct 27 11:45:50 2018 +0600 1 file changed, 6 insertions(+), 3 deletions(-) Committed: 0001 Added history of windows Auto-merging Bill.txt [detached HEAD dcd34a8] Replaced history of windows Author: Baur <atanov...@gmail.com> Date: Sat Oct 27 11:55:42 2018 +0600 1 file changed, 4 insertions(+), 5 deletions(-) Committed: 0002 Replaced history of windows Auto-merging Bill.txt [detached HEAD 8d6d82c] Added file about Azure and info about Windows 10 Author: Baur <atanov...@gmail.com> Date: Sat Oct 27 12:06:27 2018 +0600 2 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 Azure.txt Committed: 0003 Added file about Azure and info about Windows 10 All done. Restoring project state from hidden merge with single additional commit. Updating 8d6d82c..268b320 Fast-forward Bill.txt | 4 ++++ 1 file changed, 4 insertions(+) Done. 


 ~/git-rebase-via-merge.sh origin/develop 

, ours / theirs :


ours β€” (HEAD)
theirs β€” (, origin/develop)


rebase β€” .



7.


git .


.


 git config alias.copy '!git merge --ff $(git commit-tree ${1}^{tree} -p HEAD -m "Tree copy from ${1}")' 

git copy xxx, xxx β€” .


 git copy xxx 


 git merge --ff $(git commit-tree xxx^{tree} -p HEAD -m "Tree copy from xxx") 


 git copy a8fc5e3 

 git copy origin/beta 

 git copy HEAD~3 

git amend.


 git commit --amend -m "Just for test" 

:


 git commit --amend 



, , . , . β€” . , , . . " " " " . ( , devops), , .

Source: https://habr.com/ru/post/id433748/


All Articles