Git menggabungkan master menjadi cabang fitur

1017

Katakanlah kita memiliki situasi berikut di Git:

  1. Repositori yang dibuat:

    mkdir GitTest2
    cd GitTest2
    git init
    
  2. Beberapa modifikasi dalam master berlangsung dan dikomit:

    echo "On Master" > file
    git commit -a -m "Initial commit"
    
  3. Feature1 bercabang master dan beberapa pekerjaan dilakukan:

    git branch feature1
    git checkout feature1
    echo "Feature1" > featureFile
    git commit -a -m "Commit for feature1"
    
  4. Sementara itu, bug ditemukan dalam kode master dan cabang hotfix dibuat:

    git checkout master
    git branch hotfix1
    git checkout hotfix1
    
  5. Bug diperbaiki di cabang perbaikan terbaru dan bergabung kembali ke master (mungkin setelah peninjauan permintaan / kode tarik):

    echo "Bugfix" > bugfixFile
    git commit -a -m "Bugfix Commit"
    git checkout master
    git merge --no-ff hotfix1
    
  6. Pengembangan fitur1 berlanjut:

    git checkout feature1
    

Katakanlah saya perlu perbaikan terbaru di cabang fitur saya, mungkin karena bug juga terjadi di sana. Bagaimana saya bisa mencapai ini tanpa menduplikasi komitmen ke cabang fitur saya?

Saya ingin mencegah untuk mendapatkan dua komitmen baru pada cabang fitur saya yang tidak ada hubungannya dengan implementasi fitur. Ini tampaknya penting bagi saya jika saya menggunakan permintaan tarikan: Semua komitmen ini juga akan dimasukkan dalam permintaan tarikan dan harus ditinjau meskipun ini sudah dilakukan (karena perbaikan terbaru sudah ada di master).

Saya tidak bisa melakukan git merge master --ff-only: "fatal: Tidak mungkin untuk maju cepat, batal.", Tapi saya tidak yakin apakah ini membantu saya.

theomega
sumber
8
Jika cabang feature1sepenuhnya lokal, lihatlah git rebase.
Jokester
19
Terima kasih, sebagai pemula git, git rebasesepertinya ilmu hitam bagi saya ....
theomega
13
jika cabang fitur - hanya perbaikan bug tidak boleh terjadi di sana (setidaknya jika bukan bug pemblokiran) karena tujuan cabang ini adalah untuk menunjukkan fitur baru. Bug akan diperbaiki ketika digabungkan dengan master di mana komit dengan perbaikan hadir.
gipi
21
Mungkin patut dicatat bagi pemula yang ada di 3. git branch feature1dan git checkout feature1bisa digabungkan menjadi git checkout -b feature14. bisa sepenuhnya dikurangi menjadigit checkout -b hotfix1 master
Naruto Sempai
3
Apakah Anda bersedia untuk kembali dan mengubah jawaban yang diterima, karena jawaban yang diterima saat ini mengerikan.
Mahakuasa

Jawaban:

1218

Bagaimana kita menggabungkan cabang master ke cabang fitur? Mudah:

git checkout feature1
git merge master

Tidak ada gunanya memaksa penggabungan maju cepat di sini, karena hal itu tidak dapat dilakukan. Anda berkomitmen baik ke cabang fitur dan cabang master. Maju cepat tidak mungkin sekarang.

Lihatlah GitFlow . Ini adalah model percabangan untuk git yang dapat diikuti, dan Anda secara tidak sadar sudah melakukannya. Ini juga merupakan ekstensi untuk Git yang menambahkan beberapa perintah untuk langkah-langkah alur kerja baru yang melakukan hal-hal secara otomatis yang seharusnya perlu Anda lakukan secara manual.

Jadi apa yang Anda lakukan dengan benar dalam alur kerja Anda? Anda memiliki dua cabang untuk dikerjakan, cabang feature1 Anda pada dasarnya adalah cabang "berkembang" dalam model GitFlow.

Anda membuat cabang perbaikan terbaru dari master dan menggabungkannya kembali. Dan sekarang kamu terjebak.

Model GitFlow meminta Anda untuk menggabungkan perbaikan terbaru juga ke cabang pengembangan, yang merupakan "feature1" dalam kasus Anda.

Jadi jawaban sebenarnya adalah:

git checkout feature1
git merge --no-ff hotfix1

Ini menambahkan semua perubahan yang dibuat di dalam perbaikan terbaru ke cabang fitur, tetapi hanya perubahan itu. Mereka mungkin bertentangan dengan perubahan pengembangan lainnya di cabang, tetapi mereka tidak akan bertentangan dengan cabang master jika Anda menggabungkan cabang fitur kembali ke master pada akhirnya.

Berhati-hatilah dengan rebasing. Hanya rebase jika perubahan yang Anda lakukan tetap lokal ke repositori Anda, misalnya Anda tidak mendorong cabang apa pun ke beberapa repositori lainnya. Rebasing adalah alat yang hebat bagi Anda untuk mengatur komit lokal Anda ke dalam urutan yang berguna sebelum mendorongnya ke dunia, tetapi rebasing setelahnya akan mengacaukan hal-hal untuk pemula git seperti Anda.

Sven
sumber
7
Tidak. Komit yang memperbaiki bug hanya muncul sekali di cabang perbaikan terbaru, meskipun nama cabang akan dihapus setelah digabungkan ke cabang master dan devel. Komit gabungan hanya menunjukkan perubahan yang diperkenalkan oleh gabungan, yang terlihat seperti komit duplikat. Tapi beginilah cara git bekerja: Branch dan gabung kembali. Pekerjaan pengembangan nyata hanya terjadi di komit non-gabungan, dan gabungan hanya diterima jika hasilnya adalah perangkat lunak yang berfungsi.
Sven
42
Ini harus menjadi jawaban yang diterima. Ini berfungsi baik dengan fitur permintaan tarik GitHub juga.
Nostalg.io
125
Saya pikir perlu dicatat bahwa surat git merge masterwasiat akan bergabung dari salinan master lokal Anda , jadi meskipun Anda telah melakukan git pulldi cabang fitur Anda setelah orang lain menggabungkan cabang yang berbeda menjadi master, Anda harus git checkout master, kemudian git pull, kemudian, git checkout feature1lagi dan MAKA git merge master.
Damick
50
@damick Or just git fetchandgit merge origin/master
Yngvar Kristiansen
20
@damick @ yngvar-kristiansen git pull origin masterakan secara otomatis bergabung orgin/masterke cabang saat ini
L422Y
613

Anda harus dapat rebase cabang Anda pada master:

git checkout feature1
git rebase master

Kelola semua konflik yang muncul. Ketika Anda sampai di commit dengan perbaikan bug (sudah di master), Git akan mengatakan bahwa tidak ada perubahan dan bahwa mungkin itu sudah diterapkan. Anda kemudian melanjutkan rebase (sambil melewatkan komit yang sudah di master) dengan

git rebase --skip

Jika Anda melakukan git logpada cabang fitur Anda, Anda akan melihat komit perbaikan bug hanya muncul sekali, dan di bagian master.

Untuk diskusi yang lebih terperinci, lihat dokumentasi Git book di git rebase( https://git-scm.com/docs/git-rebase ) yang membahas kasus penggunaan persis ini.

================ Edit untuk konteks tambahan ====================

Jawaban ini diberikan khusus untuk pertanyaan yang diajukan oleh @theomega, dengan mempertimbangkan situasinya. Perhatikan bagian ini:

Saya ingin mencegah [...] melakukan di cabang fitur saya yang tidak ada hubungannya dengan implementasi fitur.

Rebasing cabang pribadinya pada master adalah persis apa yang akan menghasilkan hasil itu. Sebaliknya, menggabungkan master ke cabangnya justru akan melakukan apa yang secara spesifik tidak diinginkannya terjadi : menambahkan komit yang tidak terkait dengan implementasi fitur yang sedang dikerjakannya melalui cabangnya.

Untuk mengatasi pengguna yang membaca judul pertanyaan, lewati konten aktual dan konteks pertanyaan, dan kemudian hanya baca jawaban atas secara membabi buta dengan asumsi itu akan selalu berlaku untuk kasus penggunaan mereka (berbeda), izinkan saya untuk menguraikan:

  • hanya rebase cabang pribadi (yaitu yang hanya ada di repositori lokal Anda dan belum dibagikan dengan yang lain). Memulihkan cabang yang dibagikan akan "memecah" salinan yang mungkin dimiliki orang lain.
  • jika Anda ingin mengintegrasikan perubahan dari cabang (apakah itu master atau cabang lain) ke cabang yang umum (mis. Anda telah mendorong cabang untuk membuka permintaan tarik, tetapi sekarang ada konflik dengan master, dan Anda perlu memperbarui cabang Anda untuk menyelesaikan konflik-konflik itu) Anda harus menggabungkannya (misalnya dengan git merge masterseperti pada jawaban @ Sven).
  • Anda juga dapat menggabungkan cabang ke cabang pribadi lokal Anda jika itu yang Anda inginkan, tetapi perlu diketahui bahwa itu akan menghasilkan komitmen "asing" di cabang Anda.

Akhirnya, jika Anda tidak senang dengan kenyataan bahwa jawaban ini bukan yang paling cocok untuk situasi Anda walaupun itu untuk @theomega, menambahkan komentar di bawah ini tidak akan sangat membantu: Saya tidak mengontrol jawaban mana yang dipilih, hanya @theomega yang melakukannya.

David Sulc
sumber
136
Tidak, itu tidak aman: jika Anda rebase, Anda mengubah sejarah cabang, yang akan memengaruhi pengembang yang menarik cabang. inf act, git tidak akan membiarkan Anda mendorong cabang rebased secara default: Anda perlu memaksa pembaruan -fketika mendorong untuk menimpa cabang dengan versi rebased. Hati-hati!
David Sulc
17
Bagaimana tim profesional menggunakan git menangani masalah ini? Apakah hanya memperhatikan, berpikir dengan hati-hati dan kemudian lakukan -f? Atau apakah alur kerja lengkap saya cacat karena saya perlu -f?
theomega
30
Yah, saya berani menggunakan aturan "suci" adalah Anda tidak rebase (atau mengubah riwayat komit) pada kode yang telah dibagikan: itu hanya untuk kode lokal Anda. Pada dasarnya, Anda harus mengubah perubahan menjadi "bersihkan" sebelum dibagikan. Dalam kasus Anda, Anda dapat mendorong cabang rebased baru (dengan nama yang berbeda), dan meminta kolega untuk mendasarkan perubahan mereka dari cabang itu (yaitu dengan rebase cabang lokal mereka dari yang baru, seperti di atas). Kemudian, hapus feature1dari Github.
David Sulc
19
Sebagian besar tim profesional yang saya kerjakan hampir tidak pernah menggunakan rebase - mereka hanya menggabungkan semuanya secara default, sehingga tidak ada modifikasi riwayat yang terjadi. Ini adalah cara kerja pilihan saya. Di sisi lain, beberapa tim menggunakan rebase untuk 'membersihkan' komit sebelum mereka mendorong mereka (tetapi tidak pernah setelah mendorong).
Jonathan Hartley
11
Ya, Anda TIDAK PERNAH harus rebase cabang publik. Namun, pertanyaan OP tampaknya berkaitan dengan mengintegrasikan komitmen baru yang dibuat mastermenjadi cabang pribadi (ia menyebutkan cabang lokal "nya"). Dalam hal ini, rebasebaik-baik saja dan sama halnya dengan "membersihkan" yang Anda sebutkan.
David Sulc
69

Berdasarkan artikel ini , Anda harus:

  • buat cabang baru yang didasarkan pada versi master baru

    git branch -b newmaster

  • menggabungkan cabang fitur lama Anda ke yang baru

    git checkout newmaster

  • menyelesaikan konflik pada cabang fitur baru

Dua perintah pertama dapat digabungkan ke git checkout -b newmaster.

Dengan cara ini riwayat Anda tetap jelas karena Anda tidak perlu penggabungan kembali. Dan Anda tidak perlu menjadi sangat berhati-hati karena Anda tidak perlu melakukan rebase Git.

zimi
sumber
7
alangkah baiknya jika Anda membuat perintah git terkait ikuti setiap poin. Kalau tidak, menurut saya ini memang pilihan yang lebih aman dan bersih.
VirgileD
@zimi Bagaimana kalau kita memiliki cabang jarak jauh? Akankah kami membuat kembali cabang fitur pembaruan baru? Atau bisakah kita mengatur remote-upstream?
BILL
@VirgileD Saya baru saja memposting jawaban saya sendiri dengan lebih detail, termasuk perintah git terkait.
jkdev
29

git merge

Anda dapat mengikuti langkah-langkah di bawah ini

1. menggabungkan origin/mastercabang ke featurecabang

# step1: change branch to master, and pull to update all commits
$ git checkout master
$ git pull

# step2: change branch to target, and pull to update commits
$ git checkout feature
$ git pull

# step3: merge master to feature(⚠️ current is feature branch)
$ git merge master


2. menggabungkan featurecabang ke origin/mastercabang

origin/masteradalah cabang master jarak jauh, sedangkan mastercabang master lokal

$ git checkout master
$ git pull origin/master

$ git merge feature
$ git push origin/master

xgqfrms
sumber
Rasanya seperti rebase adalah hyped! Selamat bergabung, :)!
Foreever
27

Jawaban Zimi menggambarkan proses ini secara umum. Berikut spesifiknya:

  1. Buat dan alihkan ke cabang baru. Pastikan cabang baru didasarkan mastersehingga akan menyertakan perbaikan terbaru terbaru.

    git checkout master
    git branch feature1_new
    git checkout feature1_new
    
    # Or, combined into one command:
    git checkout -b feature1_new master
    
  2. Setelah beralih ke cabang baru, gabungkan perubahan dari cabang fitur yang ada. Ini akan menambahkan komit Anda tanpa menduplikasi komit perbaikan terbaru.

    git merge feature1
    
  3. Di cabang baru, selesaikan konflik antara fitur Anda dan cabang master.

Selesai! Sekarang gunakan cabang baru untuk terus mengembangkan fitur Anda.

jkdev
sumber
2
Masalah dengan ini adalah bahwa pengembang membuang waktu terus-menerus menelurkan cabang baru ketika mereka perlu memperbarui terhadap master. Kami akan membuat banyak dan banyak cabang, mungkin 3 kali sehari selama kerja aktif. Anda harus menulis instruksi tentang membersihkan semua cabang tempat sampah lokal, dan cara membuangnya di tempat yang jauh. Kami juga membutuhkan saran untuk menamai semua cabang ini sehingga kami tidak bingung. Tanpa itu, ini akan mengubah sistem cabang menjadi kacau.
pauljohn32
4
Anda benar, ini tidak boleh dilakukan sepanjang waktu. Hanya ketika (1) perubahan pada master diperlukan untuk fitur Anda, atau (2) Anda akan menggabungkan cabang Anda dengan master dan mungkin ada konflik. Dan untuk menghindari kekacauan, Anda dapat menghapus cabang Anda setelah digabungkan.
jkdev
11

Berikut ini adalah skrip yang dapat Anda gunakan untuk menggabungkan cabang master Anda ke cabang Anda saat ini.

Script melakukan hal berikut:

  • Beralih ke cabang master
  • Tarik cabang master
  • Beralih kembali ke cabang Anda saat ini
  • Menggabungkan cabang master ke cabang Anda saat ini

Simpan kode ini sebagai file batch (.bat) dan letakkan skrip di mana saja di repositori Anda. Kemudian klik untuk menjalankannya dan Anda siap.

:: This batch file pulls current master and merges into current branch

@echo off

:: Option to use the batch file outside the repo and pass the repo path as an arg
set repoPath=%1
cd %repoPath%

FOR /F "tokens=*" %%g IN ('git rev-parse --abbrev-ref HEAD') do (SET currentBranch=%%g)

echo current branch is %currentBranch%
echo switching to master
git checkout master
echo.
echo pulling origin master
git pull origin master
echo.
echo switching back to %currentBranch%
git checkout %currentBranch%
echo.
echo attemting merge master into %currentBranch%
git merge master
echo.
echo script finished successfully
PAUSE
Aaron M.
sumber
10

Anda mungkin dapat melakukan "cherry-pick" untuk menarik komit yang tepat yang Anda perlukan ke cabang fitur Anda.

Lakukan git checkout hotfix1untuk mendapatkan cabang hotfix1. Kemudian lakukan a git loguntuk mendapatkan hash SHA-1 (urutan besar huruf dan angka acak yang secara unik mengidentifikasi komit) dari komit tersebut. Salin itu (atau 10 karakter pertama atau lebih).

Kemudian, git checkout feature1untuk kembali ke cabang fitur Anda.

Kemudian, git cherry-pick <the SHA-1 hash that you just copied>

Itu akan menarik komit itu, dan hanya komit itu, ke cabang fitur Anda. Perubahan itu ada di cabang - Anda tinggal "memetiknya". Kemudian, lanjutkan pekerjaan, edit, komit, dorong, dll. Sesuka hati Anda.

Ketika, pada akhirnya, Anda melakukan penggabungan lain dari satu cabang ke cabang fitur Anda (atau sebaliknya), Git akan mengenali bahwa Anda telah bergabung dalam komit tertentu , tahu bahwa itu tidak harus membuatnya lagi, dan hanya "lewati" itu.

Bob Gilmore
sumber
Saya tidak menganggap ini ide yang bagus. Kemudian, IMO, komit perbaikan terbaru benar-benar akan muncul di riwayat cabang fitur Anda, yang pada dasarnya tidak Anda inginkan.
Martin Pecka
1
“Ketika, pada akhirnya, Anda melakukan penggabungan lain dari satu cabang ke cabang fitur Anda (atau sebaliknya), git akan mengenali bahwa Anda telah menggabungkan [...]” - apakah itu cara kerjanya yang sebenarnya? Saya tidak berpikir itu git mergeberfungsi dalam "replay commit" ini - cara yang sepertinya Anda mengisyaratkan ("dan ​​lewati saja"). Memadukan memetik dan menggabungkan buah ceri tampaknya dapat menyebabkan masalah; lihat: news.ycombinator.com/item?id=3947950
Guildenstern
0

Saya berada di cabang fitur dan membuat refactorings. Saya ingin menggabungkan perubahan master sekarang ke cabang fitur saya. Saya jauh di belakang. Catatan Saya tidak ingin menarik perubahan master ke lokal saya karena cabang fitur saya memiliki modul yang dipindahkan dari satu tempat ke tempat lain. Saya menemukan hanya melakukan di bawah tanpa tarikan tidak bekerja. itu tertulis "Sudah up to date."

 //below does not get the latest from remote master to my local feature branch without git pull
    git checkout master 
    git fetch 
    git checkout my-feature-branch 
    git merge master

Ini di bawah ini berfungsi, perhatikan menggunakan git merge origin / master:

 git checkout master 
    git fetch 
    git checkout my-feature-branch 
    git merge origin/master
Tony
sumber