Bagaimana cara saya 'menimpa', bukannya 'menggabungkan', cabang di cabang lain di Git?

257

Saya punya dua cabang, emaildan staging. stagingadalah yang terbaru dan saya tidak lagi membutuhkan perubahan lama di emailcabang, namun saya tidak ingin menghapusnya.

Jadi saya hanya ingin membuang semua konten stagingke dalam emailsehingga keduanya menunjukkan komit yang sama. Apakah itu mungkin?

Rafid
sumber
4
Kemungkinan duplikat Ubah cabang saat ini untuk dikuasai di git
Tomas Kubes

Jawaban:

196

Anda dapat menggunakan strategi penggabungan 'milik kami':

$ git checkout staging
$ git merge -s ours email # Merge branches, but use our branch head
rajutan
sumber
26
Saya mencoba ini, dan sepertinya saya mundur? Bukankah ini membuang isi email ke dalam pementasan dan bukan sebaliknya?
Maks
27
@ Max Saya memiliki kebingungan yang sama dan itu menyebabkan saya banyak masalah. Anda perlu melakukan perintah ini dari cabang yang lebih baru (pementasan), dan kemudian lakukan penggabungan / PR normal ke cabang lama Anda (email).
MrGlass
7
Mengapa ;di akhir setiap perintah? Saya melakukannya tanpa ;dan tampaknya berfungsi. Juga jawaban ini tidak lengkap, langkah ketiga adalah untuk checkout cabang lama (email) dan kemudian bergabung dengan pementasan lagi.
Rosdi Kasim
4
git rebase -s theirs <oldbranc> <newbranch> berfungsi juga (tidak peduli cabang mana Anda berada). Perhatikan bahwa dalam rebase 'milik mereka' sebenarnya merupakan cabang baru karena 'milik kita' adalah kepala yang saat ini kita lamarkan komit.
Rolf
4
@Rolf: tetapi rebase akan menghilangkan informasi penggabungan dan meratakan sejarah. Belum tentu apa yang Anda kejar. Juga bukan ide yang baik, jika Anda bekerja dengan sejarah yang sudah diterbitkan.
Knittl
99

Jika Anda hanya ingin dua cabang 'email' dan 'staging' sama, Anda dapat menandai cabang 'email', lalu setel ulang cabang 'email' ke yang 'staging':

$ git checkout email
$ git tag old-email-branch
$ git reset --hard staging

Anda juga dapat rebase cabang 'pementasan' di cabang 'email'. Tetapi hasilnya akan berisi modifikasi dari dua cabang.

Sylvain Defresne
sumber
1
Anda mungkin berarti git checkout, git checktidak ada setahu saya
knittl
4
Anda benar, saya sudah terbiasa dengan tab penyelesaian perintah git sehingga saya selalu menulis "git check <TAB>" untuk menulis "git checkout"! Dikoreksi.
Sylvain Defresne
17
git reset merusak repo orang lain yang telah mengkloning repo Anda
Geoffrey De Smet
Saya percaya ini adalah jawaban yang tepat. emailkepala cabang harus menunjuk ke kepala yang sama stagingdan mereka berdua akan memiliki komitmen yang sama, sejarah yang sama.
cicerocamargo
76

Saya telah melihat beberapa jawaban dan itulah satu-satunya prosedur yang memungkinkan saya memperbaikinya tanpa konflik.

Jika Anda ingin semua perubahan dari branch_new di branch_old, maka:

git checkout branch_new
git merge -s ours branch_old
git checkout branch_old
git merge branch_new

Setelah menerapkan keempat perintah tersebut, Anda dapat menekan branch_old tanpa masalah

Brugolo
sumber
5
Jawaban Anda sangat sesuai dengan masalah saya karena saya tidak ingin mengatur ulang HEAD, sebutkan saja preferensi untuk file yang lebih baru di cabang yang lebih baru ketika menggabungkan sesuatu ke yang lebih lama, dan bekerja tanpa masalah! +1
kompor
Saya mendorong branch_new saya ke remote setelah "kita bergabung", dan metode ini bekerja untuk saya. Apakah perlu bagi saya untuk mendorong? Atau apakah itu akan berhasil tanpa? (Tidak yakin apakah itu akan menggunakan cabang lokal atau jarak jauh). Terima kasih!
aspergillusOryzae
Mengapa Anda tidak bisa begitu saja melakukan hal di bawah ini? git checkout branch_old git merge -s milik mereka branch_new Petunjuk diambil dari stackoverflow.com/questions/14275856/…
Ripu Daman
Dikatakan, tidak bisa menemukan strategi penggabungan 'milik mereka'.
arango_86
Berfungsi sempurna untuk saya, memiliki keuntungan tidak menyetel ulang apa pun
Romain
68

Jawaban lain memberi saya petunjuk yang benar, tetapi mereka tidak sepenuhnya membantu.

Inilah yang bekerja untuk saya:

$ git checkout email
$ git tag old-email-branch # This is optional
$ git reset --hard staging
$
$ # Using a custom commit message for the merge below
$ git merge -m 'Merge -s our where _ours_ is the branch staging' -s ours origin/email
$ git push origin email

Tanpa langkah keempat menyatu dengan strategi kita, dorongan itu dianggap sebagai pembaruan yang tidak terlalu cepat dan akan ditolak (oleh GitHub).

Shyam Habarakada
sumber
Itu membuat pesan menggabungkan-komit salah, tapi ya, itu berfungsi dengan baik.
cdunn2001
cdunn2001, saya ingin tahu. Apa pesan gabungan-komitmen yang Anda harapkan dan bagaimana itu bisa kacau dengan ini?
Shyam Habarakada
Dikatakan "Gabungkan 'asal / email' cabang pelacak jarak jauh ke dalam email". Itu tidak menyebutkan pementasan. Bukan masalah besar sekalipun. Hanya mengubah komit, atau gunakan merge -m 'This is not my beautiful house.' -s ours origin/email.
cdunn2001
@ShyamHabarakada, saya melakukan apa yang Anda katakan, dan saya mendapatkan masalah tentang pembaruan yang tidak terlalu cepat. karena tidak ada yang terjadi ketika saya melakukan langkah ke-4.
kommradHomer
Langkah ke-4 mengharuskan Anda menggunakan asal / email, itu tidak berfungsi hanya dengan email lokal.
Travis Reeder
45

Jika Anda seperti saya dan Anda tidak ingin berurusan dengan penggabungan, Anda dapat melakukan langkah-langkah di atas, kecuali menggunakan kekuatan alih-alih penggabungan, karena itu akan membuat jejak kertas log yang mengganggu:

git checkout email
git reset --hard staging
git push origin email --force

Catatan: Ini hanya jika Anda BENAR-BENAR tidak pernah ingin melihat barang-barang di email lagi.

jsarma
sumber
1
git push email asal - memaksa tidak bekerja untuk saya karena Step2 meninggalkan cabang berbeda. Jadi setelah Step2, inilah yang saya lakukan: git reset asal / email dan kemudian git push
user3505394
2
Inilah yang ditanyakan - "bagaimana cara menimpa dan bukan menggabungkan". Harus diterima jawaban.
jozols
17

Saya ingin menggabungkan dua cabang sehingga semua konten dalam old_branchdiperbarui dengan isi darinew_branch

Bagi saya ini bekerja seperti pesona:

$ git checkout new_branch
$ git merge -m 'merge message' -s ours origin/old_branch
$ git checkout old_branch
$ git merge new_branch
$ git push origin old_branch
Madhu
sumber
10

Bagaimana tentang:

git branch -D email
git checkout staging
git checkout -b email
git push origin email --force-with-lease
Arek S
sumber
@emptywalls karena melakukan push paksa tanpa memperingatkan pengguna bahwa itu dapat ditolak oleh server, juga tidak menjelaskan mengapa itu diperlukan. Yang mengatakan, itu adalah pilihan yang layak untuk proyek satu-pengembang
David Costa
@ Davidvidosta mengapa ini ditolak oleh server? ini adalah cabang email hapus sederhana & salin pementasan ke email '... Jadi saya hanya ingin membuang semua konten' pementasan 'ke' email 'sehingga keduanya menunjuk ke komit yang sama' - itulah yang sebenarnya terjadi sini.
Arek S
@ArekS dapat ditolak oleh pengait sisi server jika cabang disetel sebagai "terproteksi" misalnya di GitLab. Masalahnya adalah jika orang lain mengambil cabangnya dari email sebelum operasi ini dan kemudian mencoba mendorong, referensi tidak cocok lagi (karena beberapa komit hilang begitu saja)
David Costa
1
Saya mengedit yang asli dari --force to --force-with-leasing, yang melakukan trik dengan cara yang tidak merusak.
frandroid
1
Ini adalah cara terbaik jika Anda hanya ingin menerbangkan cabang dan mulai membersihkannya dari cabang sumber.
Shane
6

Jawaban lain tampak tidak lengkap.
Saya sudah mencoba sepenuhnya di bawah ini, dan itu berhasil dengan baik.

CATATAN:
1. Buat salinan repositori Anda sebelum Anda mencoba di bawah ini, agar aman.

Rincian:
1. Semua pengembangan terjadi di cabang dev
2. cabang qa hanya salinan yang sama dari dev
3. Waktu ke waktu, kode dev perlu dipindahkan / ditimpa ke cabang qa

jadi kita perlu menimpa cabang qa, dari cabang dev

Bagian 1:
Dengan perintah di bawah ini, qa lama telah diperbarui ke dev yang lebih baru:

git checkout dev
git merge -s ours qa
git checkout qa
git merge dev
git push

Komentar otomatis untuk dorongan terakhir memberi di bawah:

// Output:
//  *<MYNAME> Merge branch 'qa' into dev,*  

Komentar ini terlihat terbalik, karena urutan di atas juga terlihat terbalik

Bagian 2:

Di bawah ini adalah tak terduga, komitmen lokal baru di dev, yang tidak perlu
jadi, kita perlu membuang, dan membuat dev tidak tersentuh.

git checkout dev

// Output:
//  Switched to branch 'dev'  
//  Your branch is ahead of 'origin/dev' by 15 commits.  
//  (use "git push" to publish your local commits)


git reset --hard origin/dev  

//  Now we threw away the unexpected commits

Bagian 3:
Verifikasi semuanya seperti yang diharapkan:

git status  

// Output:
//  *On branch dev  
//  Your branch is up-to-date with 'origin/dev'.  
//  nothing to commit, working tree clean*  

Itu saja.
1. qa lama sekarang ditimpa oleh kode cabang dev baru
2. lokal bersih (asal terpencil / dev tidak tersentuh)

Manohar Reddy Poreddy
sumber
6

Cara termudah untuk melakukannya:

//the branch you want to overwrite
git checkout email 

//reset to the new branch
git reset --hard origin/staging

// push to remote
git push -f

Sekarang cabang email dan pementasan adalah sama.

B.Neo
sumber
2
Peringatan: Ini menghapus semua commit di emailcabang. Ini seperti menghapus emailcabang dan membuatnya baru di kepala stagingcabang.
Cameron Hudson
2
git checkout email
git merge -m "Making email same as staging disregarding any conflicts from email in the process" -s recursive -X theirs staging
Willa
sumber
1
Jawaban ini akan lebih jelas bagi saya jika komentar dibuat terpisah dari komentar penggabungan dalam perintah. Jelaskan secara singkat apa yang dilakukan -X dan bagaimana hal itu memengaruhi penggabungan ini. Terimakasih Meskipun. Membuat saya mencarinya :)
noelicus
@noelicus terima kasih atas komentarnya dan Anda benar. Saya mungkin mengedit jawaban di masa mendatang.
Willa
0

Yang ini tidak mengubah cabang baru yang lebih baru, dan memberi Anda kesempatan untuk melakukan modifikasi lebih lanjut sebelum komit terakhir.

git checkout new -b tmp
git merge -s ours old -m 'irrelevant'
git checkout old
git merge --squash tmp
git branch -D tmp
#do any other stuff you want
git add -A; git commit -m 'foo' #commit (or however you like)
Jan Kyu Peblik
sumber