Cara memilih ceri hanya mengubah hanya satu file, bukan seluruh komit

108

Saya perlu menerapkan perubahan yang diperkenalkan di satu cabang ke cabang lain. Saya bisa menggunakan cherry pick untuk melakukan itu. Namun, dalam kasus saya, saya ingin menerapkan perubahan yang hanya relevan untuk satu file, saya tidak perlu memilih keseluruhan komit. Bagaimana cara melakukannya?

ashim
sumber

Jawaban:

137

Anda memiliki opsi berbeda berdasarkan apa yang ingin Anda capai:

Jika Anda ingin konten file sama dengan cabang target, Anda dapat menggunakan git checkout <branch> -- <filename>. Namun ini tidak akan “memilih-ceri” perubahan yang terjadi dalam satu komit, tetapi hanya mengambil status hasil dari file tersebut. Jadi jika Anda menambahkan baris dalam komit, tetapi komit sebelumnya berubah lebih banyak, dan Anda hanya ingin menambahkan baris itu tanpa perubahan lain, maka pembayaran bukanlah yang Anda inginkan.

Sebaliknya jika Anda ingin menerapkan tambalan yang diperkenalkan dalam komit hanya untuk satu file, Anda memiliki beberapa opsi. Anda dapat menjalankan git cherry-pick -n, yaitu tanpa melakukan itu, mengedit komit (misalnya mengatur ulang semua file menggunakan git reset -- .dan hanya menambahkan file yang sebenarnya ingin Anda ubah menggunakan git add <filename>). Atau Anda dapat membuat diff untuk file dan menerapkan diff kemudian:

git diff <branch>^..<branch> -- <filename> | git apply
menyodok
sumber
22

Buat patch filedan terapkan.

git diff branchname -- filename > patchfile
git apply patchfile

EDIT:

Karena Anda perlu mengambil perubahan dari sebuah komit, buat tambalan seperti ini:

git show sha1 -- filename > patchfile
Sailesh
sumber
1
git diff sha1(atau git diff branch- itu sama jika cabang menunjuk ke hash yang sama) hanya akan menghasilkan diff dari direktori kerja saat ini dalam kaitannya dengan hash itu, tapi tidak perubahan apa yang diperkenalkan sendiri oleh komit.
aduk
Benar. Mengedit jawabannya. Terima kasih.
Sailesh
1
-1 git checkoutdengan nama file adalah palu yang tepat untuk paku ini. Kedua opsi ini sangat rumit.
Rein Henrichs
7
Untuk kasus khusus ini, ya. Tetapi secara umum, jika Anda ingin memilih perubahan dari komit yang dibuat ke file tertentu, maka checkouttidak akan berfungsi, karena ini mungkin melibatkan perubahan sebelumnya yang tidak diinginkan, dan mungkin tidak berisi perubahan yang dibuat di cabang saat ini.
Sailesh
11

Hal lain yang berguna untuk dilakukan adalah mendapatkan tambalan secara lokal dan kemudian menggunakan:

git checkout {<name_of_branch>, commit's SHA} <path to the file> 

Itu bukan pemetikan ceri.

0x90
sumber
2
Peringatan: seperti yang dikatakan @poke dalam jawabannya, ini tidak menyalin perubahan; itu menyalin seluruh status file. Jadi jika Anda ingin menambahkan perubahan komit ke file, maka dengan memeriksa seperti ini Anda akan menimpa perubahan baru yang tidak baik.
Alexander Bird
7

Git sudah menyiapkan semuanya :)

Gunakan saja git checkout <sha> <path-to-file>

Raghotham S.
sumber
4
Itu bukan pilihan yang tepat - yang memeriksa file secara penuh. Tujuannya adalah untuk membuat perubahan tertentu dari sebuah komit. Seringkali itu adalah hal yang sama, tetapi terkadang tidak.
AndrewF
6
git checkout the_branch_with_the_change the/path/to/the/file/you/want.extension

ini berfungsi jika Anda ingin satu file dari cabang lain disalin ke cabang yang sedang bekerja

Ismail Iqbal
sumber
1
Hati-hati, perubahan yang dilakukan pada file yang tidak ada di versi dari cabang lain akan hilang.
Patrick Schlüter
Setuju dengan itu. ini berguna jika Anda hanya memerlukan salinan file dan ingin mengubahnya di cabang saat ini
Ismail Iqbal
1
Seseorang dapat menggunakan globs (path / *) dan menentukan lebih dari satu path / file
Todd
1

Ini yang kamu cari:

git checkout target-branch sha1 path/to/file

sha1 adalah opsional

Ruslan Osipov
sumber
11
tidak, "pilih perubahan dalam komit" bukan "pilih seluruh file"
Abyx
1

Yang cenderung saya lakukan adalah menggunakan git ls-tree

kerjakan saja:

git ls-tree -r <commit-id> |grep 'your filename'
# there will be output that shows a SHA1 of your file
git show ${SHA1 of your file} > 'your filename'

Ini akan mencetak semua nama file yang cocok dengan grep Anda dan memberikan kunci SHA1 dari file di komit.

Git show juga dapat digunakan pada file di luar cabang Anda. menggunakan >dari shell Anda untuk menyalurkan output menjadi file memberi Anda hasil yang Anda cari.

Alex
sumber
0

Anda dapat mencoba melakukan ini:

git show COMMIT_ID -- path/to/specific-file | git apply

Sebagai contoh:

git show 3feaf20 -- app/views/home/index.html | git apply
arashb31
sumber
-9
git reset HEAD~1

memindahkan file ke tahap pra-komit

git stash

menghapus dari memori

Sekarang cabang Anda cukup bersih (kembali ke komit sebelumnya)

Venkata
sumber