Saya menggunakan git pada proyek baru yang memiliki dua cabang pengembangan paralel - namun saat ini eksperimental:
master
: impor basis kode yang ada ditambah beberapa mod yang secara umum saya yakiniexp1
: cabang eksperimental # 1exp2
: cabang eksperimental # 2
exp1
dan exp2
mewakili dua pendekatan arsitektur yang sangat berbeda. Sampai saya melanjutkan, saya tidak memiliki cara untuk mengetahui yang mana (jika salah satu) akan bekerja. Ketika saya membuat kemajuan di satu cabang, saya kadang-kadang memiliki pengeditan yang berguna di cabang lain dan ingin menggabungkan hanya itu.
Apa cara terbaik untuk menggabungkan perubahan selektif dari satu cabang pengembangan ke yang lain sambil meninggalkan yang lainnya?
Pendekatan yang saya pertimbangkan:
git merge --no-commit
diikuti oleh penghapusan manual sejumlah besar pengeditan yang tidak ingin saya lakukan di antara cabang-cabang.Menyalin manual file umum ke direktori temp diikuti oleh
git checkout
untuk pindah ke cabang lain dan kemudian lebih banyak menyalin manual dari direktori temp ke pohon kerja.Variasi di atas. Tinggalkan
exp
cabang untuk saat ini dan gunakan dua repositori lokal tambahan untuk eksperimen. Ini membuat penyalinan file secara manual jauh lebih mudah.
Ketiga pendekatan ini tampak membosankan dan rentan kesalahan. Saya berharap ada pendekatan yang lebih baik; sesuatu yang mirip dengan parameter jalur filter yang akan membuat git-merge
lebih selektif.
sumber
git merge -s ours --no-commit
diikuti oleh beberapagit read-tree
menjadi solusi yang baik untuk ini? Lihat stackoverflow.com/questions/1214906/…Jawaban:
Anda menggunakan perintah cherry-pick untuk mendapatkan komitmen individu dari satu cabang.
Jika perubahan yang Anda inginkan tidak berada dalam komit individual, maka gunakan metode yang ditampilkan di sini untuk membagi komit menjadi komit individual . Secara kasar, Anda menggunakan
git rebase -i
untuk mendapatkan komit asli untuk diedit, lalugit reset HEAD^
untuk secara selektif mengembalikan perubahan, lalugit commit
untuk mengkomit bit itu sebagai komit baru dalam sejarah.Ada metode bagus lain di sini di Red Hat Magazine, di mana mereka menggunakan
git add --patch
atau mungkingit add --interactive
yang memungkinkan Anda untuk menambahkan hanya bagian dari sebongkah, jika Anda ingin membagi perubahan yang berbeda ke file individual (cari di halaman itu untuk "split").Setelah memecah perubahan, Anda sekarang dapat memilih apa yang Anda inginkan.
sumber
Saya memiliki masalah yang sama persis seperti yang disebutkan oleh Anda di atas. Tetapi saya menemukan ini lebih jelas dalam menjelaskan jawabannya.
Ringkasan:
Periksa jalur dari cabang yang ingin Anda gabungkan,
Petunjuk: Ini juga berfungsi tanpa
--
seperti yang terlihat di pos tertaut.atau untuk secara selektif menggabungkan bakhil
Atau, gunakan reset dan kemudian tambahkan dengan opsi
-p
,Akhirnya komit
sumber
foo.c
lakukangit reset HEAD foo.c
untuk unstage file itu dan Anda kemudian dapat diff itu. Saya menemukan ini setelah mencobanya dan kembali ke sini untuk mencari jawaban atas hal inigit diff --cached
git checkout -p <revision> -- <path>
akan sama dengan mengeluarkan tiga perintah pertama yang Anda jelaskan :)Untuk menggabungkan file secara selektif dari satu cabang ke cabang lain, jalankan
di mana
branchX
cabang yang ingin Anda gabungkan menjadi cabang saat ini.The
--no-commit
pilihan akan menggelar file yang telah digabungkan oleh Git tanpa benar-benar melakukan mereka. Ini akan memberi Anda kesempatan untuk memodifikasi file yang digabungkan namun Anda ingin dan kemudian melakukannya sendiri.Bergantung pada bagaimana Anda ingin menggabungkan file, ada empat kasus:
1) Anda ingin penggabungan yang benar.
Dalam hal ini, Anda menerima file yang digabungkan dengan cara Git menggabungkannya secara otomatis dan kemudian mengkomitnya.
2) Ada beberapa file yang tidak ingin Anda gabungkan.
Misalnya, Anda ingin mempertahankan versi di cabang saat ini dan mengabaikan versi di cabang yang Anda gabungkan.
Untuk memilih versi di cabang saat ini, jalankan:
Ini akan mengambil versi
file1
di cabang saat ini dan menimpa yangfile1
diautomatisasi oleh Git.3) Jika Anda menginginkan versi di branchX (dan bukan gabungan sebenarnya).
Lari:
Ini akan mengambil versi
file1
inbranchX
dan overwrite yangfile1
digabungkan secara otomatis oleh Git.4) Kasus terakhir adalah jika Anda hanya ingin memilih gabungan tertentu
file1
.Dalam hal ini, Anda dapat mengedit yang dimodifikasi
file1
secara langsung, memperbarui ke versi apa pun yang Anda inginkanfile1
, dan kemudian komit.Jika Git tidak dapat menggabungkan file secara otomatis, itu akan melaporkan file sebagai " unmerged " dan menghasilkan salinan di mana Anda harus menyelesaikan konflik secara manual.
Untuk menjelaskan lebih lanjut dengan contoh, katakanlah Anda ingin bergabung
branchX
ke cabang saat ini:Anda kemudian menjalankan
git status
perintah untuk melihat status file yang dimodifikasi.Sebagai contoh:
Di mana
file1
,,file2
danfile3
file-file git telah berhasil digabungkan secara otomatis.Ini artinya bahwa perubahan pada
master
danbranchX
untuk ketiga file tersebut telah digabungkan bersama tanpa konflik.Anda dapat memeriksa bagaimana penggabungan dilakukan dengan menjalankan
git diff --cached
;Jika Anda menemukan beberapa penggabungan yang tidak diinginkan maka Anda bisa
git commit
Jika Anda tidak ingin menggabungkan
file1
dan ingin mempertahankan versi di cabang saat iniLari
Jika Anda tidak ingin bergabung
file2
dan hanya ingin versi masukbranchX
Lari
Jika Anda ingin
file3
digabungkan secara otomatis, jangan lakukan apa pun.Git sudah menggabungkannya pada saat ini.
file4
di atas adalah penggabungan gagal oleh Git. Ini berarti ada perubahan di kedua cabang yang terjadi pada baris yang sama. Di sinilah Anda harus menyelesaikan konflik secara manual. Anda bisa membuang gabungan yang dilakukan dengan mengedit file secara langsung atau menjalankan perintah checkout untuk versi di cabang yang Anda inginkanfile4
.Akhirnya, jangan lupa
git commit
.sumber
git merge --no-commit branchX
hanya maju cepat, penunjuk akan diperbarui, dan --no-komit karenanya diabaikan secara diam-diam--no-ff
untuk mencegah perilaku itu?Saya tidak suka pendekatan di atas. Menggunakan cherry-pick sangat bagus untuk memilih satu perubahan, tetapi itu menyebalkan jika Anda ingin membawa semua perubahan kecuali untuk beberapa perubahan buruk. Ini pendekatan saya.
Tidak ada
--interactive
argumen yang bisa Anda sampaikan ke git merge.Berikut ini alternatifnya:
Anda memiliki beberapa perubahan dalam 'fitur' cabang dan Anda ingin membawa beberapa tetapi tidak semuanya ke 'master' dengan cara yang tidak ceroboh (yaitu Anda tidak ingin memilih dan melakukan masing-masing)
Jadi bungkus saja dalam skrip shell, ubah master menjadi $ to dan ubah fitur menjadi $ from dan Anda siap melakukannya:
sumber
git rebase -i $to
kegit rebase -i $to || $SHELL
, sehingga pengguna dapat memanggilgit --skip
dll, jika perlu jika rebase gagal. Juga layak untuk merantai baris bersama dengan&&
bukannya baris baru.Ada cara lain:
Ini adalah campuran antara
git checkout
dangit add -p
dan mungkin persis apa yang Anda cari:sumber
Sementara beberapa jawaban ini cukup bagus, saya merasa tidak ada yang benar-benar menjawab kendala asli OP: memilih file tertentu dari cabang tertentu. Solusi ini dapat melakukannya, tetapi mungkin membosankan jika ada banyak file.
Katakanlah Anda memiliki
master
,exp1
, danexp2
cabang. Anda ingin menggabungkan satu file dari masing-masing cabang eksperimental menjadi master. Saya akan melakukan sesuatu seperti ini:Ini akan memberi Anda in-file diff untuk setiap file yang Anda inginkan. Tidak ada lagi. Tidak kurang. Ini berguna Anda memiliki perubahan file yang sangat berbeda antara versi - dalam kasus saya, mengubah aplikasi dari Rails 2 ke Rails 3.
EDIT : ini akan menggabungkan file, tetapi menggabungkan cerdas. Saya tidak dapat menemukan cara menggunakan metode ini untuk mendapatkan informasi di-file in-file (mungkin masih akan untuk perbedaan ekstrem. Mengganggu hal-hal kecil seperti spasi putih digabungkan kembali kecuali Anda menggunakan
-s recursive -X ignore-all-space
opsi)sumber
git checkout exp1 path/to/file_a path/to/file_x
git checkout feature <path>/*
untuk mendapatkan kelompok file.1800 INFORMASI jawaban sepenuhnya benar. Namun, sebagai git noob, "gunakan git cherry-pick" tidak cukup bagi saya untuk mencari tahu tanpa menggali lebih dalam di internet jadi saya pikir saya akan memposting panduan yang lebih rinci jika ada orang lain di perahu serupa.
Kasus penggunaan saya ingin secara selektif menarik perubahan dari cabang github orang lain ke saya sendiri. Jika Anda sudah memiliki cabang lokal dengan perubahan, Anda hanya perlu melakukan langkah 2 dan 5-7.
Buat (jika tidak dibuat) cabang lokal dengan perubahan yang ingin Anda bawa.
$ git branch mybranch <base branch>
Beralihlah ke dalamnya.
$ git checkout mybranch
Tarik ke bawah perubahan yang Anda inginkan dari akun orang lain. Jika Anda belum melakukannya, Anda ingin menambahkannya sebagai remote.
$ git remote add repos-w-changes <git url>
Tarik semuanya dari cabang mereka.
$ git pull repos-w-changes branch-i-want
Lihat log komit untuk melihat perubahan mana yang Anda inginkan:
$ git log
Beralih kembali ke cabang tempat Anda ingin menarik perubahan.
$ git checkout originalbranch
Cherry memilih komitmen Anda, satu per satu, dengan hash.
$ git cherry-pick -x hash-of-commit
Kiat topi: http://www.sourcemage.org/Git_Guide
sumber
git cherry
perintah (lihat manual terlebih dahulu) untuk mengidentifikasi komit yang belum Anda gabungkan.Berikut adalah cara Anda dapat mengganti
Myclass.java
file dimaster
cabang denganMyclass.java
difeature1
cabang. Ini akan berfungsi bahkan jikaMyclass.java
tidak adamaster
.Perhatikan bahwa ini akan menimpa - bukan menggabungkan - dan mengabaikan perubahan lokal di cabang master.
sumber
theirs
menimpaours
=> +1 Cheers;)2. Manual copying of common files into a temp directory followed by ...copying out of the temp directory into the working tree.
Cara sederhana, untuk benar-benar menggabungkan file tertentu dari dua cabang, bukan hanya mengganti file tertentu dengan yang dari cabang lain.
Langkah satu: Diff cabang-cabangnya
git diff branch_b > my_patch_file.patch
Membuat file tambalan dari perbedaan antara cabang saat ini dan branch_b
Langkah dua: Terapkan tambalan pada file yang cocok dengan suatu pola
git apply -p1 --include=pattern/matching/the/path/to/file/or/folder my_patch_file.patch
catatan berguna pada opsi
Anda dapat menggunakan
*
sebagai wildcard dalam pola include.Garis miring tidak perlu lepas.
Selain itu, Anda dapat menggunakan --exclude sebagai gantinya dan menerapkannya pada semua hal kecuali file yang sesuai dengan pola, atau membalikkan tambalan dengan -R
Opsi -p1 adalah peninggalan dari perintah * unix patch dan fakta bahwa isi file patch mendahului setiap nama file dengan
a/
ataub/
(atau lebih tergantung pada bagaimana file patch dihasilkan) yang perlu Anda strip sehingga Anda dapat mencari tahu file asli ke jalur ke file patch perlu diterapkan.Lihatlah halaman manual untuk git-apply untuk lebih banyak opsi.
Langkah tiga: tidak ada langkah ketiga
Jelas Anda ingin melakukan perubahan, tetapi siapa bilang Anda tidak memiliki beberapa tweak terkait lainnya yang ingin Anda lakukan sebelum membuat komit.
sumber
Berikut adalah cara Anda mendapatkan riwayat untuk mengikuti hanya beberapa file dari cabang lain dengan minimal keributan, bahkan jika gabungan yang lebih "sederhana" akan menghasilkan lebih banyak perubahan yang tidak Anda inginkan.
Pertama, Anda akan mengambil langkah yang tidak biasa menyatakan sebelumnya bahwa apa yang akan Anda lakukan adalah penggabungan, tanpa git melakukan apa pun pada file di direktori kerja Anda:
. . . di mana "branchname" adalah apa pun yang Anda klaim untuk gabungkan. Jika Anda berkomitmen segera, itu tidak akan membuat perubahan tetapi itu akan tetap menunjukkan keturunan dari cabang lain. Anda dapat menambahkan lebih banyak cabang / tag / dll. ke baris perintah jika Anda perlu, juga. Pada titik ini, tidak ada perubahan untuk dikomit, jadi dapatkan file dari revisi lain, selanjutnya.
Jika Anda menggabungkan dari lebih dari satu cabang lain, ulangi sesuai kebutuhan.
Sekarang file dari cabang lain berada di indeks, siap untuk dilakukan, dengan sejarah.
dan Anda akan memiliki banyak penjelasan yang harus dilakukan dalam pesan komit itu.
Harap dicatat, kalau-kalau tidak jelas, ini harus dikacaukan. Bukan dalam semangat untuk apa "cabang" itu, dan memilih ceri adalah cara yang lebih jujur untuk melakukan apa yang akan Anda lakukan, di sini. Jika Anda ingin melakukan "penggabungan" lain untuk file lain di cabang yang sama yang tidak Anda bawa terakhir kali, itu akan menghentikan Anda dengan pesan "sudah terbaru". Ini adalah gejala tidak bercabang ketika kita seharusnya, dalam cabang "dari" harus lebih dari satu cabang yang berbeda.
sumber
git merge --no-ff --no-commit -s outs branchname1
) persis seperti yang saya cari! Terima kasih!Saya tahu saya sedikit terlambat tetapi ini adalah alur kerja saya untuk menggabungkan file selektif.
sumber
Cara termudah adalah dengan mengatur repo Anda ke cabang yang ingin Anda gabungkan lalu jalankan,
Jika Anda berlari
Anda akan melihat file sudah dipentaskan ...
Lalu lari
Sederhana.
sumber
Saya menemukan posting ini mengandung jawaban paling sederhana. Cukup lakukan:
Contoh:
Lihat posting untuk info lebih lanjut.
sumber
Sungguh aneh bahwa git masih tidak memiliki alat yang nyaman "out of the box". Saya sangat menggunakannya ketika memperbarui beberapa cabang versi lama (yang masih memiliki banyak pengguna perangkat lunak) dengan hanya beberapa perbaikan bug dari cabang versi saat ini. Dalam hal ini, sering kali diperlukan untuk mendapatkan hanya beberapa baris kode dari file di trunk, mengabaikan banyak perubahan lain (yang tidak seharusnya masuk ke versi lama) ... Dan tentu saja interaktif tiga cara menggabungkan diperlukan dalam kasus ini,
git checkout --patch <branch> <file path>
tidak dapat digunakan untuk tujuan penggabungan selektif ini.Anda dapat melakukannya dengan mudah:
Cukup tambahkan baris ini ke
[alias]
bagian di file global.gitconfig
atau lokal Anda.git/config
:Ini berarti Anda menggunakan Beyond Compare. Ubah saja ke perangkat lunak pilihan Anda jika perlu. Atau Anda dapat mengubahnya menjadi penggabungan otomatis tiga arah jika Anda tidak memerlukan penggabungan selektif interaktif:
Kemudian gunakan seperti ini:
Ini akan memberi Anda peluang penggabungan jalan selektif sejati dari sembarang file di cabang lain.
sumber
Bukan apa yang Anda cari, tapi itu berguna bagi saya:
Ini adalah campuran dari beberapa jawaban.
sumber
git checkout HEAD file1
untuk menjaga versi saat ini dan memisahkan filefile1
, seseorang dapat menggunakan-p
opsi untuk memilih bagian dari file yang akan digabung. terima kasih untuk triknya!Saya akan melakukan
Dengan cara ini Anda dapat membatasi rentang komit untuk filepattern dari cabang.
Dicuri dari: http://www.gelato.unsw.edu.au/archives/git/0701/37964.html
sumber
Saya memiliki masalah yang sama persis seperti yang disebutkan oleh Anda di atas. Tapi saya menemukan blog git ini lebih jelas dalam menjelaskan jawabannya.
Perintah dari tautan di atas:
sumber
Saya suka jawaban 'git-interactive-merge', di atas, tetapi ada satu yang lebih mudah. Biarkan git melakukan ini untuk Anda menggunakan kombinasi rebase interaktif dan ke:
Jadi masalahnya adalah Anda ingin C1 dan C2 dari cabang 'fitur' (titik cabang 'A'), tetapi tidak ada yang lain untuk saat ini.
Yang, seperti di atas, menjatuhkan Anda ke editor interaktif tempat Anda memilih baris 'pilih' untuk C1 dan C2 (seperti di atas). Simpan dan keluar, dan kemudian akan melanjutkan dengan rebase dan memberi Anda cabang 'temp' dan juga KEPALA di master + C1 + C2:
Kemudian Anda bisa memperbarui master ke HEAD dan menghapus cabang temp dan Anda bisa melanjutkan:
sumber
Bagaimana dengan
git reset --soft branch
? Saya terkejut bahwa belum ada yang menyebutkannya.Bagi saya, ini adalah cara termudah untuk secara selektif memilih perubahan dari cabang lain, karena, perintah ini menempatkan di pohon kerja saya, semua perubahan berbeda dan saya dapat dengan mudah memilih atau mengembalikan yang mana yang saya butuhkan. Dengan cara ini, saya memiliki kendali penuh atas file yang dikomit.
sumber
Saya tahu pertanyaan ini sudah lama dan ada banyak jawaban lain, tetapi saya menulis skrip saya sendiri yang disebut 'pmerge' untuk menggabungkan sebagian direktori. Ini adalah pekerjaan yang sedang berjalan dan saya masih belajar skrip git dan bash.
Perintah ini menggunakan
git merge --no-commit
dan kemudian menghapus perubahan yang tidak cocok dengan jalur yang disediakan.Penggunaan:
git pmerge branch path
Contoh:
git merge develop src/
Saya belum mengujinya secara ekstensif. Direktori yang berfungsi harus bebas dari perubahan yang tidak dikomit dan file yang tidak terlacak.
sumber
Anda dapat menggunakan
read-tree
untuk membaca atau menggabungkan pohon jarak jauh yang diberikan ke indeks saat ini, misalnya:Untuk melakukan penggabungan, gunakan
-m
saja.Lihat juga: Bagaimana cara saya menggabungkan sub direktori di git?
sumber
Pendekatan sederhana untuk menggabungkan / melakukan selektif berdasarkan file:
git checkout dstBranch git merge srcBranch // make changes, including resolving conflicts to single files git add singleFile1 singleFile2 git commit -m "message specific to a few files" git reset --hard # blow away uncommitted changes
sumber
Jika Anda tidak memiliki terlalu banyak file yang telah berubah, ini akan membuat Anda tanpa komitmen tambahan.
1. Cabang duplikat sementara
$ git checkout -b temp_branch
2. Setel ulang ke komit yang terakhir diinginkan
$ git reset --hard HEAD~n
, di manan
jumlah komit yang Anda perlukan untuk kembali3. Periksa setiap file dari cabang asli
$ git checkout origin/original_branch filename.ext
Sekarang Anda dapat melakukan dan memaksa push (untuk menimpa jarak jauh), jika perlu.
sumber
Jika Anda hanya perlu menggabungkan direktori tertentu dan membiarkan yang lainnya tetap utuh dan belum menyimpan sejarah, Anda dapat mencoba ini ... buat yang baru
target-branch
darimaster
sebelum Anda bereksperimen.Langkah-langkah di bawah ini menganggap Anda memiliki dua cabang
target-branch
dansource-branch
, dan direktoridir-to-merge
yang ingin Anda gabungkan ada disource-branch
. Juga asumsikan Anda memiliki direktori lain sepertidir-to-retain
di target yang Anda tidak ingin mengubah dan mempertahankan sejarah. Juga, anggap ada konflik gabungan didir-to-merge
.sumber
Ketika hanya beberapa file telah berubah di antara commit saat ini dari dua cabang, saya secara manual menggabungkan perubahan dengan menelusuri file yang berbeda.
git difftoll <branch-1>..<branch-2>
sumber