Bagaimana cara menyalin komit dari satu cabang ke cabang lainnya?

728

Saya mendapat dua cabang dari tuan saya:

  • v2.1 : (versi 2) Saya telah mengerjakan selama beberapa bulan
  • wss : yang saya buat kemarin untuk menambahkan satu fitur khusus ke master saya (dalam produksi)

Apakah ada cara untuk menyalin commit kemarin dari wss ke v2.1?

Bob Walsh
sumber
Untuk hanya menyalin komit (atau serangkaian komit) dari satu cabang ke cabang lain jawaban ini membantu saya yang terbaik: stackoverflow.com/questions/1994463/…
caramba

Jawaban:

566

Anda harus benar-benar memiliki alur kerja yang memungkinkan Anda melakukan ini semua dengan menggabungkan:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (wss)

Jadi yang harus Anda lakukan adalah git checkout v2.1dan git merge wss. Jika karena alasan tertentu Anda benar-benar tidak dapat melakukan ini, dan Anda tidak dapat menggunakan git rebase untuk memindahkan cabang wss Anda ke tempat yang tepat, perintah untuk mengambil satu komit dari suatu tempat dan menerapkannya di tempat lain adalah git-pick ceri . Cukup periksa cabang tempat Anda ingin menerapkannya, dan jalankan git cherry-pick <SHA of commit to cherry-pick>.

Beberapa cara rebase dapat menyelamatkan Anda:

Jika riwayat Anda terlihat seperti ini:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (v2-only) - x - x - x (wss)

Anda bisa menggunakan git rebase --onto v2 v2-only wssuntuk memindahkan wss langsung ke v2:

- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - x - x (v2-only)
           \
             x - x - x (wss)

Maka Anda dapat bergabung! Jika Anda benar-benar, benar - benar , benar - benar tidak dapat mencapai titik di mana Anda dapat bergabung, Anda masih dapat menggunakan rebase untuk secara efektif melakukan beberapa pemetik ceri sekaligus:

# wss-starting-point is the SHA1/branch immediately before the first commit to rebase
git branch wss-to-rebase wss
git rebase --onto v2.1 wss-starting-point wss-to-rebase
git checkout v2.1
git merge wss-to-rebase

Catatan: alasan mengapa diperlukan beberapa pekerjaan ekstra untuk melakukan ini adalah karena itu membuat duplikat komit dalam repositori Anda. Ini sebenarnya bukan hal yang baik - inti dari percabangan dan penggabungan yang mudah adalah untuk dapat melakukan segalanya dengan membuat komit (s) satu tempat dan menggabungkan mereka ke mana pun mereka dibutuhkan. Duplikat komit berarti niat untuk tidak menggabungkan kedua cabang tersebut (jika Anda memutuskan ingin melakukannya nanti, Anda akan mendapatkan konflik).

Cascabel
sumber
1
Tidak bisa setuju dengan jawaban ini. +1. Lihat juga jawaban lama saya untuk menggambarkan konsekuensi dari memetik ceri: stackoverflow.com/questions/881092/…
VonC
18
Jawaban luar biasa tentang bagaimana melakukan ini dengan cara yang benar ! Saya berharap saya dapat memilih dua kali untuk upaya membuat diagram ASCII juga.
Gotgenes
@VonC: Terima kasih atas dukungannya, dan info tambahan tentang mengapa tidak memilih cherry-pick - Saya tahu saya sedikit berhemat di sana. @ gotgenes: Terima kasih! Saya pikir ini sepadan dengan usaha - lihat saja halaman git-rebase. Tidak ada cara yang lebih baik untuk menjelaskannya.
Cascabel
Adapun mengapa Anda mungkin tidak dapat bergabung - Git penggabungan tidak cocok dengan git-svn. Untuk menyalin serangkaian komit dari satu cabang SVN ke yang lain, saya akhirnya memetiknya dan kemudian melakukan rebase / reword interaktif untuk menghapus git-svn-idreferensi yang salah sebelum memasukkan dcommitlagi. Meskipun aku mungkin bisa mengabaikan langkah memilih ceri dan hanya menggunakan rebase dengan sendirinya.
Bob
1
Inilah kasus penggunaan saya: perbaikan bug kritis dilakukan ke cabang fitur. Saya membutuhkannya secara master untuk mulai berproduksi sekarang. Ini akan menghemat pantatku.
Kapten Hypertext
910

Menggunakan

git cherry-pick <commit>

untuk diterapkan <commit>ke cabang Anda saat ini .

Saya sendiri mungkin akan memeriksa silang komit yang saya ambil gitkdan memilihnya dengan klik kanan pada entri komit di sana.


Jika Anda ingin lebih otomatis (dengan semua bahayanya) dan dengan asumsi semua komit sejak kemarin terjadi pada wss Anda dapat membuat daftar komit menggunakan git log(dengan --prettydisarankan oleh Jefromi)

git log --reverse --since=yesterday --pretty=%H

jadi semuanya bersama-sama dengan asumsi Anda gunakan bash

for commit in $(git log --reverse --since=yesterday --pretty=%H);
do
    git cherry-pick $commit
done

Jika ada yang tidak beres di sini (ada banyak potensi) Anda dalam masalah karena ini bekerja pada checkout langsung, jadi lakukan pick-cherry manual atau gunakan rebase seperti yang disarankan oleh Jefromi.

Benjamin Bannier
sumber
Semua placeholder untuk opsi --pretty ada di halaman git-log. Anda bisa mendapatkan format apa pun yang Anda inginkan - terutama berguna untuk mendapatkan bidang yang Anda inginkan untuk skrip dalam bentuk yang mudah diurai.
Cascabel
Saya juga ingin menunjukkan bahwa, dengan anggapan Anda benar-benar ingin membuat duplikat komit, metode yang digunakan git rebasedalam jawaban saya lebih kuat. Secara khusus, menggunakan for for loop seperti ini, jika salah satu dari cherry-picks gagal, ia masih akan mencoba melakukan sisanya. Ini ... sangat sangat tidak baik, katakanlah.
Cascabel
2
Sepakat. Itu sebabnya saya tidak pernah menggunakannya, tetapi melakukannya secara manual. Tapi cherry-pick masih jawabannya, setidaknya untuk judul pertanyaan. Saya mengubah respons.
Benjamin Bannier
1
Seseorang berkomitmen pada cabang lama / salah, dan memilih ceri biarkan aku memasukkan komitmen itu ke cabang kanan (sambil tetap mempertahankannya sebagai pengalih). Sempurna.
Patrick
8
Sebuah pemandangan langka, gitjawaban yang sederhana dan langsung ke solusinya, alih-alih berkelok-kelok melalui seluk beluk git untuk membuktikan seberapa baik penjawab itu mengetahuinya.
Przemek D
74

git cherry-pick : Terapkan perubahan yang diperkenalkan oleh beberapa komitmen yang ada

Asumsikan kita memiliki cabang A dengan (X, Y, Z) berkomitmen. Kita perlu menambahkan komit ini untuk cabang B . Kami akan menggunakan cherry-pickoperasi.

Ketika kita menggunakan cherry-pick, kita harus menambahkan komit pada cabang B di urutan kronologis yang sama bahwa komit muncul dalam Cabang A .

cherry-pick memang mendukung serangkaian commit, tetapi jika Anda memiliki gabungan commit dalam rentang itu, itu akan menjadi sangat rumit

git checkout B
git cherry-pick SHA-COMMIT-X
git cherry-pick SHA-COMMIT-Y
git cherry-pick SHA-COMMIT-Z

Contoh alur kerja:

masukkan deskripsi gambar di sini

Kita dapat menggunakan cherry-pickdengan pilihan

-e atau --edit : Dengan opsi ini, git cherry-pick akan memungkinkan Anda mengedit pesan komit sebelum melakukan.

-n atau --no-commit : Biasanya perintah secara otomatis membuat urutan commit. Bendera ini menerapkan perubahan yang diperlukan untuk memilih setiap komit yang dinamai ke pohon kerja Anda dan indeks, tanpa membuat komit. Selain itu, ketika opsi ini digunakan, indeks Anda tidak harus cocok dengan komit HEAD. Pilihan ceri dilakukan terhadap kondisi awal indeks Anda.

Berikut artikel menarik tentang cherry-pick.

LYES - CHIOUKH
sumber
19

Anda bisa membuat tambalan dari komit yang ingin Anda salin dan menerapkan tambalan ke cabang tujuan.

Charles Ma
sumber
16
Bahkan jika Anda karena suatu alasan benar-benar ingin menggunakan tambalan alih-alih memilih ceri / rebase, cara mudah untuk melakukannya adalah dengan git format-patch <revision range>dan git am *.patch.
Cascabel
Ini membutuhkan checkoutcabang lain.
CoolMind
12

Atau jika Anda sedikit kurang di sisi penginjil Anda dapat melakukan sedikit cara jelek yang saya gunakan. Di deploy_template ada komit yang ingin saya salin pada master saya sebagai penyebaran cabang

git branch deploy deploy_template
git checkout deploy
git rebase master

Ini akan membuat penyebaran cabang baru (saya menggunakan -f untuk menimpa cabang penyebaran yang ada) di deploy_template, lalu rebase cabang baru ini ke master, membiarkan deploy_template tidak tersentuh.

Petr Sykora
sumber
1

Untuk kasus sederhana dengan menyalin komit terakhir dari branch wss ke v2.1, Anda cukup mengambil komit id ( git log --oneline | head -n 1) dan lakukan:

git checkout v2.1
git merge <commit>
nolimpl
sumber
Ini membutuhkan pemeriksaan ke cabang lain.
CoolMind
1

Perintah cherry-pick dapat membaca daftar commit dari input standar.

Perintah cherry-pick berikut dilakukan oleh pengguna John yang ada di cabang "mengembangkan" tetapi tidak di cabang "rilis", dan melakukannya dalam urutan kronologis.

git log develop --not release --format=%H --reverse --author John | git cherry-pick --stdin
Gebb
sumber