Cara mendapatkan hanya satu file dari cabang lain

1267

Saya menggunakan git dan bekerja pada cabang master. Cabang ini memiliki file bernama app.js.

Saya memiliki experimentcabang di mana saya membuat banyak perubahan dan banyak komitmen. Sekarang saya ingin membawa semua perubahan yang dilakukan hanya app.jsdari dari experimentke mastercabang.

Bagaimana aku melakukan itu?

Sekali lagi saya tidak ingin penggabungan. Saya hanya ingin membawa semua perubahan app.jsdari experimentcabang ke mastercabang.

Nick Vanderbilt
sumber
1
Jawaban yang dikecualikan dan yang lainnya pada hari ini menjawab bagaimana cara menyalin konten file, itulah yang saya inginkan pada diri saya ketika saya menemukan yang itu. Namun, jika dibaca dengan tepat, Nick ingin membawa perubahan, bukan teks lengkap, dan file di masterdapat berbeda experiment, misalnya dapat berisi perubahan yang digabungkan dari cabang lain yang akan hilang dalam file hanya disalin. PS di sisi lain ia tidak ingin bergabung, tetapi sejauh yang saya tahu git mergeistilah hanya untuk cabang, bukan untuk file tertentu, jadi tidak ada kontradiksi di sini.
Alexei Martianov

Jawaban:

1605
git checkout master               # first get back to master
git checkout experiment -- app.js # then copy the version of app.js 
                                  # from branch "experiment"

Lihat juga git cara membatalkan perubahan satu file?


Pembaruan Agustus 2019, Git 2.23

Dengan yang baru git switchdan git restoreperintah, itu akan menjadi:

git switch master
git restore -s experiment -- app.js

Secara default, hanya pohon yang bekerja dipulihkan.
Jika Anda ingin memperbarui indeks juga (artinya mengembalikan konten file, dan menambahkannya ke indeks dalam satu perintah):

git restore -s experiment --staged --worktree -- app.js
# shorter:
git restore -s experiment -WS -- app.js

Seperti Jakub Narębski menyebutkan dalam komentar:

git show experiment:path/to/app.js > path/to/app.js

berfungsi juga, kecuali itu, sebagaimana dirinci dalam pertanyaan SO " Bagaimana cara mengambil satu file dari revisi tertentu di Git? ", Anda perlu menggunakan path lengkap dari direktori root repo.
Maka jalur / ke / app.js digunakan oleh Jakub dalam contohnya.

Seperti yang disebutkan Frosty dalam komentar:

Anda hanya akan mendapatkan status terbaru dari app.js

Tetapi, untuk git checkoutatau git show, Anda sebenarnya dapat mereferensikan revisi apa pun yang Anda inginkan, seperti yang diilustrasikan dalam pertanyaan SO " git checkout revisi file di git gui ":

$ git show $REVISION:$FILENAME
$ git checkout $REVISION -- $FILENAME

akan sama adalah $ FILENAME adalah path lengkap file berversi.

$REVISIONdapat seperti yang ditunjukkan pada git rev-parse:

experiment@{yesterday}:app.js # app.js as it was yesterday 
experiment^:app.js            # app.js on the first commit parent
experiment@{2}:app.js         # app.js two commits ago

dan seterusnya.

schmijos menambahkan dalam komentar :

Anda juga dapat melakukan ini dari simpanan:

git checkout stash -- app.js

Ini sangat berguna jika Anda bekerja pada dua cabang dan tidak ingin melakukan.

VONC
sumber
13
Satu catatan: Anda hanya akan mendapatkan status terbaru app.js, Anda tidak akan mendapatkan riwayat apa pun yang dibawa dari cabang percobaan.
Frosty
2
@ThomasReggi Anda harus dapat mengimpor (checkout) file dari cabang mana saja ke cabang saat ini. Jika Anda tidak bisa, itu bisa menjadi pertanyaan yang bagus untuk ditanyakan di sini, dengan detail spesifik seperti pesan kesalahan yang tepat, dan versi Git dan OS yang digunakan.
VonC
2
Dalam sebuah sub-direktori, Anda juga dapat menggunakan experiment:./app.js. (Anda tidak perlu menentukan path lengkap.) Saya belajar ini berkat pesan kesalahan yang sangat membantu, git memberi saya: "Apakah maksud Anda 'mybranch: full / path / to / my / file.xsl' aka 'mybranch: ./file.xsl '? " Ya saya lakukan! Saya tidak berpikir saya pernah begitu senang dengan pesan kesalahan fatal.
Evan Lenz
1
@ ThomaszGandor Ya, saya menyebutkan bahwa di stackoverflow.com/a/21066489/6309 , di mana git show tidak akan mengubah indeks, tetapi checkout git memang mengubah indeks.
VonC
1
@FriedBrice Lihat jawaban saya: hari ini, itu akan menjadigit restore -s new-feature path/to/app.js
VonC
360

Semuanya lebih sederhana, gunakan checkout git untuk itu.

Misalkan you're on mastercabang, untuk mendapatkan app.js from new-featurecabang lakukan:

git checkout new-feature path/to/app.js

// note that there is no leading slash in the path!

Ini akan membawa Anda isi file yang diinginkan. Anda dapat, seperti biasa, menggunakan bagian dari sha1 daripada nama cabang fitur baru untuk mendapatkan file seperti di komit tertentu.

Catatan : new-featureharus cabang lokal , bukan cabang jarak jauh.

Dmitry Avtonomov
sumber
77
Saya merasa terbantu untuk selalu menentukan asal-usulnya git checkout origin/source_branch path/to/filekarena jika Anda lalai memperbarui cabang sumber repo lokal Anda, Anda mungkin mendapatkan versi file yang lama ... Tanya saya bagaimana saya tahu. ;)
talyric
3
@Mymozaaa pertanyaannya tidak menyebutkan remote, dengan demikian asumsi bahwa itu adalah repo murni lokal
Dmitry Avtonomov
1
Akankah perintah ini membawa sejarah file, atau hanya versi terakhir file?
user1366265
1
@ user1366265 perintah ini akan meletakkan file seperti di komit tertentu yang Anda tentukan atau kepala cabang yang Anda tentukan. Tidak ada yang namanya "riwayat file", semua informasi riwayat hanya disimpan di cabang.
Dmitry Avtonomov
3
Ini sepertinya secara otomatis menampilkan file yang sudah keluar. Apakah mungkin melakukan hal yang sama tanpa melakukan pementasan?
bluenote10
44
git checkout branch_name file_name

Contoh:

git checkout master App.java

Ini tidak akan berfungsi jika nama cabang Anda memiliki periode di dalamnya.

git checkout "fix.june" alive.html
error: pathspec 'fix.june' did not match any file(s) known to git.
Sarath
sumber
@ PhilipRego Jawaban ini benar. Saya menduga ada perbedaan kapitalisasi atau tanda baca di cabang Anda, atau Anda hanya memiliki cabang yang jauh dan bukan yang lokal. Lihat dokumen checkout git: git-scm.com/docs/git-checkout#Documentation/…
Bret
@Bret Saya menemukan itu tidak berfungsi ketika nama cabang memiliki titik. Saya menyarankan edit
Philip Rego
Ini jawaban terbaik. Saya berharap jawaban ini diberi nilai tertinggi. Yang tertinggi saat ini sangat membingungkan dan tidak langsung
Russell Lego
41

Tambahan untuk jawaban VonC dan chhh.

git show experiment:path/to/relative/app.js > app.js
# If your current working directory is relative than just use
git show experiment:app.js > app.js

atau

git checkout experiment -- app.js
AlexLordThorsen
sumber
2
Keren! Aku benci menentukan jalan yang panjang. Apakah tanda hubung ganda ( --) antara nama cabang dan jalur opsional? Apakah hanya untuk mencegah jalur, yang akan dimulai dengan tanda hubung, agar tidak diperlakukan sebagai opsi / switch?
Tomasz Gandor
Jujur saya tidak tahu. Saya bahkan tidak menyadari bahwa saya telah lupa dasbor ganda sampai Anda menunjukkan ini.
AlexLordThorsen
6
@TomaszGandor --bersifat opsional, tetapi lebih bermanfaat untuk menghindari konflik dengan nama cabang. Misalnya, git checkout -- fooberarti "periksa file foo dari HEAD" (mis. Menimpa perubahan lokal di foo , mis. Subset dari git reset --hard), tetapi git checkout foodapat berarti bahwa atau "mari kita pergi ke branch foo ".
Alois Mahdal
8

Atau jika Anda ingin semua file dari cabang lain:

git checkout <branch name> -- .
Pelawak
sumber
24
Pertanyaan awal berisi "hanya satu file".
greatvovan
1
ini menggantikan file yang ada daripada menggabungkan
Amare
3
Ini .membuat perbedaan besar: alih-alih pindah ke cabang lain, ia menyalin semua file dari sana sambil tetap meninggalkan Anda pada yang sekarang. Anda mendapatkan konten dari cabang lain tanpa masuk ke dalamnya.
Xeverous
4

Tinjau file di github dan tarik dari sana

Ini adalah pendekatan pragmatis yang tidak langsung menjawab OP, tetapi beberapa menemukan berguna:

Jika cabang yang dimaksud adalah di GitHub, maka Anda dapat menavigasi ke cabang dan file yang diinginkan menggunakan salah satu dari banyak alat yang ditawarkan GitHub, lalu klik 'Raw' untuk melihat teks biasa, dan (secara opsional) menyalin dan menempelkan teks sebagai diinginkan.

Saya suka pendekatan ini karena memungkinkan Anda melihat file jarak jauh secara keseluruhan sebelum menariknya ke mesin lokal Anda.

fearless_fool
sumber
2
Namun menyalin dan menempel file mentah kemungkinan akan menyebabkan perubahan karakter yang tidak diinginkan di git diff Anda. Lebih aman untuk menyimpan file secara langsung ke proyek Anda untuk memastikan tidak ada perubahan.
Philip Rego
0

Jika Anda ingin file dari komit tertentu (cabang apa pun), katakan 06f8251f

git checkout 06f8251f path_to_file

misalnya, di windows:

git checkout 06f8251f C: \ A \ B \ C \ D \ file.h

arupjbasu
sumber
1
Terima kasih telah meluangkan waktu untuk menjawab! Tapi ini tidak menjawab pertanyaan, dan jawaban yang bagus yang sangat tetep sudah diposting 9 tahun yang lalu. Tidak perlu menabrak pertanyaan.
Nathan
Ini adalah skenario praktis yang valid. Jawabannya berkaitan dengan cabang dengan benar, tetapi bagaimana dengan melihat komit tertentu dari cabang.
arupjbasu
0

Cara lain adalah membuat tambalan dengan perbedaan dan menerapkannya di cabang master Misalnya. Katakanlah komit terakhir sebelum Anda mulai bekerja di app.js adalah 00000aaaaa dan komit yang terdiri dari versi yang Anda inginkan adalah 00000bbbbb

Anda menjalankan ini di cabang percobaan:

git diff 00000aaaaa 00000bbbbb app.js > ~/app_changes.git

Ini akan membuat file dengan semua perbedaan antara kedua commit untuk app.js yang dapat Anda terapkan di mana pun Anda inginkan. Anda dapat menyimpan file itu di mana saja di luar proyek

Kemudian, pada master Anda jalankan:

git apply ~/app_changes.git

sekarang Anda akan melihat perubahan dalam proyek seolah-olah Anda membuatnya secara manual.

Santi
sumber
-3
git checkout master               -go to the master branch first
git checkout <your-branch> -- <your-file> --copy your file data from your branch.

git show <your-branch>:path/to/<your-file> 

Semoga ini bisa membantu Anda. Tolong beri tahu saya jika Anda memiliki pertanyaan.

Rohit Saini
sumber