Bagaimana cara menyalin versi satu file dari satu cabang git ke yang lain?

944

Saya punya dua cabang yang sepenuhnya digabung.

Namun, setelah penggabungan selesai, saya menyadari bahwa satu file telah dikacaukan oleh penggabungan (orang lain melakukan format otomatis, gah), dan itu akan lebih mudah untuk mengubah ke versi baru di cabang lain, dan kemudian masukkan kembali satu baris perubahan saya setelah membawanya ke cabang saya.

Jadi apa cara termudah di git untuk melakukan ini?

madlep
sumber
3
Harap perhatikan bahwa dalam jawaban yang diterima, solusi pertama tahapan perubahan, dan solusi kedua tidak. stackoverflow.com/a/56045704/151841
user151841

Jawaban:

1675

Jalankan ini dari cabang tempat Anda ingin file berakhir:

git checkout otherbranch myfile.txt

Formula umum:

git checkout <commit_hash> <relative_path_to_file_or_dir>
git checkout <remote_name>/<branch_name> <file_or_dir>

Beberapa catatan (dari komentar):

  • Menggunakan hash komit, Anda dapat menarik file dari komit apa pun
  • Ini berfungsi untuk file dan direktori
  • menimpa file myfile.txtdanmydir
  • Wildcard tidak berfungsi, tetapi jalur relatif tidak
  • Beberapa jalur dapat ditentukan

sebuah alternatif:

git show commit_id:path/to/file > path/to/file
madlep
sumber
13
Ya tentu saja. Tapi itulah maksud dari pertanyaan itu.
Ikke
37
Mungkin jelas, tetapi Anda harus menggunakan nama file yang lengkap ... Wildcard tidak berfungsi!
Chris Hart
6
walaupun .. ini juga cara yang baik: git show commit_id: path / to / file> path / ke / file
milushov
14
remote: git checkout origin / otherbranch myfile.txt
Roman Rhrn Nesterov
6
Menggunakan wildcard tidak berfungsi, Anda hanya perlu membungkusnya dengan ''mereka sehingga mereka tidak bisa ditafsirkan oleh shell.
Wiktor Czajkowski
82

Saya akhirnya pada pertanyaan ini pada pencarian serupa. Dalam kasus saya, saya ingin mengekstrak file dari cabang lain ke direktori kerja saat ini yang berbeda dari lokasi asli file. Jawaban :

git show TREEISH:path/to/file >path/to/local/file
lkraav
sumber
18
Maksud dari 'git show' adalah untuk menampilkan data ke terminal dalam format yang dapat dibaca, yang tidak dijamin untuk mencocokkan isi file dengan tepat. Sama seperti itu lebih baik untuk menyalin dokumen-kata secara keseluruhan, dan tidak mencoba untuk Salin dan Tempel kontennya ke dokumen lain.
Gonen
Saya hanya ingin melihatnya sehingga saya dapat membandingkan konten dengan cabang saat ini (periksa beberapa kode). Saya ingin menggunakan vim dengan ini ... untuk penyorotan sintaks, dll.
isaaclw
3
Untuk membandingkan konten sebelum melakukan checkout, git diff <other branch> <path to file>berfungsi dengan baik.
Randall
2
@Gonen: Pada git versi 2.21.0, halaman manual "git show" mengatakan "Untuk gumpalan polos, itu menunjukkan konten polos." Saya tidak yakin apakah ini berarti kita selalu baik. Saya agak khawatir untuk mengambil gambar seperti itu ...
hibbelig
52

Bagaimana dengan menggunakan perintah checkout:

  git diff --stat "$branch"
  git checkout --merge "$branch" "$file"
  git diff --stat "$branch"
RzR
sumber
8
note merge (perintah ke-2) tidak dapat berfungsi jika file tidak ada di kedua cabang
simpleuser
Hm Saya tidak punya diffstat. Apakah itu versi spesifik dari alat diff, karena saya belum pernah mendengarnya (dan haruskah saya beralih ke itu?): D
dudewad
git diffmendukung --statargumen yang pada dasarnya melakukan hal yang sama dengan diffstat.
hlovdal
Saya harus memeriksa kedua cabang secara lokal agar ini berfungsi.
UnitasBrooks
18

1) Pastikan Anda berada di cabang tempat Anda membutuhkan salinan file tersebut. untuk misalnya: saya ingin file cabang di master sehingga Anda perlu checkout atau harus di mastergit checkout master

2) Sekarang checkout file tertentu saja yang Anda inginkan dari cabang ke master,

git checkout sub_branch file_path/my_file.ext

di sini sub_branchberarti di mana Anda memiliki file itu diikuti dengan nama file yang perlu Anda salin.

Mohideen bin Mohammed
sumber
Sangat berguna dan dijelaskan dengan baik.
Abk
15

Mengikuti jawaban madlep Anda juga bisa menyalin satu direktori dari cabang lain dengan direktori blob.

git checkout other-branch app/**

Mengenai pertanyaan op jika Anda hanya mengubah satu file di sana, ini akan berfungsi dengan baik ^ _ ^

6ft Dan
sumber
1
Perhatikan bahwa kedua cabang harus ditarik dengan benar, pertama, atau digunakan origin/other-branchuntuk merujuk ke cabang repo. Dasar, tapi gigit aku. (jawabannya hebat - tidak perlu diedit)
akauppi
8

Saya akan menggunakan git restore(tersedia sejak git 2.23)

git restore --source otherbranch path/to/myfile.txt


Mengapa lebih baik daripada opsi lain?

git checkout otherbranch -- path/to/myfile.txt- Ini menyalin file ke direktori kerja tetapi juga ke area pementasan (efek yang sama seperti jika Anda akan menyalin file ini secara manual dan dieksekusi git adddi atasnya). git restoretidak menyentuh area pementasan (kecuali jika diminta oleh --stagedopsi).

git show otherbranch:path/to/myfile.txt > path/to/myfile.txtmenggunakan pengalihan shell standar. Jika Anda menggunakan Powershell maka mungkin ada masalah dengan pengkodean teks atau Anda bisa mendapatkan file yang rusak jika itu biner . Dengan git restoremengubah file dilakukan semua oleh gitexecutable.

Keuntungan lain adalah Anda dapat mengembalikan seluruh folder dengan:

git restore --source otherbranch path/to

atau dengan git restore --overlay --source otherbranch path/tojika Anda ingin menghindari menghapus file. Misalnya jika ada lebih sedikit file otherbranchdaripada di direktori kerja saat ini (dan file-file ini dilacak ) tanpa --overlayopsi git restoreakan menghapusnya. Tapi ini adalah bahaviour default yang bagus, Anda kemungkinan besar ingin keadaan direktori sama seperti di otherbranch, bukan "sama tetapi dengan file tambahan di cabang saya saat ini"

Mariusz Pawelski
sumber
Jawaban bagus. Apakah ada git restorecara untuk menyalin file dari cabang sumber ke file baru di cabang target? Dengan git show saya bisa melakukan ini dengan pengalihan shell ( git show otherbranch:path/to/file1.txt > path/to/file2.txt), tapi saya ingin menghindari pengalihan shell karena alasan yang Anda sebutkan.
AdmiralAdama
1
@AdmiralAdama tidak juga. Dan saya pikir tidak ada peluang besar untuk mendapatkannya git restore(tapi siapa yang tahu;)). Masalah pengalihan ini pada dasarnya adalah masalah Powershell, tidak yakin apakah ada shell lain yang bermasalah dengannya. Saya biasanya kembali ke "git bash" atau bahkan "cmd" di mana saya perlu menggunakan git showperintah " with redirection". Atau gunakan GUI seperti GitExtensions di mana Anda dapat menelusuri pohon file komit dan klik "Simpan sebagai" pada file apa pun.
Mariusz Pawelski
Ah saya mengerti. Saya tidak menggunakan Powershell jadi mungkin pengalihan shell adalah np untuk saya. Terimakasih atas infonya.
AdmiralAdama
3

Harap perhatikan bahwa dalam jawaban yang diterima, opsi pertama akan mem - stage seluruh file dari cabang lain (seperti yang git add ...telah dilakukan), dan bahwa opsi kedua hanya menghasilkan menyalin file, tetapi tidak melakukan tahapan pada perubahan (seolah-olah Anda memiliki baru mengedit file secara manual dan memiliki perbedaan yang luar biasa).

Git salin file dari cabang lain tanpa mementaskannya

Perubahan yang dilakukan (misalnya git add filename):

$ git checkout directory/somefile.php feature-B

$ git status
On branch feature-A
Your branch is up-to-date with 'origin/feature-A'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   directory/somefile.php

Perubahan luar biasa (tidak dipentaskan atau dilakukan):

$ git show feature-B:directory/somefile.php > directory/somefile.php

$ git status
On branch feature-A
Your branch is up-to-date with 'origin/feature-A'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   directory/somefile.php

no changes added to commit (use "git add" and/or "git commit -a")
pengguna151841
sumber
Saya mendapatkan "fitur-B bukan file", nama cabang yang lebih dulu, tentang ini -> "> direktori / somefile.php" dapatkah ini mengubah penyandian file?
Tiago Oliveira de Freitas