GIT: Checkout ke folder tertentu

128

Saya ingin menggunakan sesuatu yang mirip dengan:

git checkout -- <path>/<file>

tapi saya ingin checkout file ke beberapa folder yang saya pilih, daripada menimpa lokal <path>/<file>.

Ada ide?

Rafid
sumber
2
Lihat: stackoverflow.com/questions/160608/…
Adam Vandenberg

Jawaban:

57

Per Lakukan "git export" (seperti "svn export")?

Anda dapat menggunakan git checkout-indexuntuk itu, ini adalah perintah tingkat rendah, jika Anda ingin mengekspor semuanya, Anda dapat menggunakan -a,

git checkout-index -a -f --prefix=/destination/path/

Mengutip halaman manual:

Final "/" [pada awalan] penting. Nama yang diekspor secara harfiah hanya diawali dengan string yang ditentukan.

Jika Anda ingin mengekspor direktori tertentu, ada beberapa trik yang terlibat. Perintah hanya mengambil file, bukan direktori. Untuk menerapkannya pada direktori, gunakan perintah 'find' dan kirimkan hasilnya ke git.

find dirname -print0 | git checkout-index --prefix=/path-to/dest/ -f -z --stdin

Juga dari halaman manual:

Intuitif bukan tujuan di sini. Repeatability adalah.

Hasen
sumber
Sayangnya ini tidak akan bekerja dari repositori telanjang git, bahkan dengan set --prefix :-( (diuji dengan git 1.9.1)
apeiros
1
jika Anda ingin memeriksa cabang / melakukan repositori telanjang, gunakanGIT_WORK_TREE=../path/to/place git checkout
allicoder
4
git worktree(lihat di bawah) imho adalah jawaban kanonik hari ini dan mungkin ditambahkan di sini.
geek-merlin
213

Solusi lain yang sedikit lebih bersih - cukup tentukan pohon kerja yang berbeda.

Untuk checkout segala sesuatu dari KEPALA Anda (bukan indeks) ke direktori spesifik keluar:

git --work-tree=/path/to/outputdir checkout HEAD -- .

Untuk checkout subdirektori atau file dari KEPALA Anda ke direktori tertentu:

git --work-tree=/path/to/outputdir checkout HEAD -- subdirname
Adrian Macneil
sumber
4
Catatan kecil - Anda memang membutuhkan jalur absolut karena ekspansi shell tilde tidak terjadi, yaitu --work-tree=/home/thomasg/okcopyalih-alih --work-tree=~/okcopy(mungkin menggunakan jalur relatif sambil duduk di dalam pohon git yang sama juga berfungsi, tetapi dengan cara itu terletak kegilaan dan git statuskeluaran di R'lyehian)
Tom Goodfellow
10
Ini berfungsi seperti yang diharapkan dengan komit lama juga (misalnya memberikan SHA sebagai pengganti HEAD), namun git statuskemudian menunjukkan banyak mod (mungkin karena indeks sekarang cocok dengan direktori lain dan bukan pohon kerja normal yang tidak tersentuh). git resetkembali ke keadaan baik.
Tom Goodfellow
2
Sama di sini git statusmenunjukkan banyak mod, dan git resettidak membantu. Saya harus git checkout -f HEADmengembalikan keadaan repo saya.
DUzun
11
FYI: Anda harus membuat direktori sendiri, jika tidak Anda akan mendapatkan kesalahan ini:fatal: This operation must be run in a work tree
timaschew
13
Bencana ini mengubah indeks pohon kerja utama, yang biasanya buruk. Seperti yang disarankan @TomGoodfellow, git resetcukup untuk mengembalikan pohon kerja utama ke kewarasan. Untuk mengekspor subdirektori repositori dengan aman di SHA1, cabang, atau tag mana pun tanpa memodifikasi pohon kerja utama, lihat solusi terkenal Charles Bailey . Demikian juga, untuk secara aman checkout beberapa cabang secara bersamaan, sub -perintah baru adalah teman Anda. git archivegit worktree add
Cecil Curry
25

Untuk satu file:

git show HEAD:abspath/to/file > file.copy
Tobu
sumber
2
+1 dan untuk memperjelas "komit sebelumnya tertentu" (bukan KEPALA): Ini merujuk pada SHA1 IDyang dapat dengan mudah ditemukan melalui gitk. Jika saya hanya perlu "checkout" file itu ke lokasi sementara (yaitu tidak kembali), maka saya akan menggunakan showsub- perintah :git show 82e54378856215ef96c5db1ff1160a741b5dcd70:MyProj/proguard/mapping.txt > myproj_mapping.txt
ef2011
19

Solusi di atas tidak bekerja untuk saya karena saya perlu memeriksa versi pohon yang ditandai. Omong cvs export-omong, itu dimaksudkan untuk digunakan. git checkout-indextidak mengambil argumen tag, karena memeriksa file dari indeks. git checkout <tag>akan mengubah indeks terlepas dari pohon kerja, jadi saya harus mengatur ulang pohon asli. Solusi yang berhasil bagi saya adalah mengkloning repositori. Kloning bersama cukup cepat dan tidak memakan banyak ruang. The .gitdirektori dapat dihapus jika diinginkan.

git clone --shared --no-checkout <repository> <destination>
cd <destination>
git checkout <tag>
rm -rf .git

Versi git yang lebih baru harus mendukung git clone --branch <tag>untuk memeriksa tag yang ditentukan secara otomatis:

git clone --shared --branch <tag> <repository> <destination>
rm -rf <destination>/.git
proski
sumber
3
git --work-tree=/path/to/outputdir checkout <tag> -- .tidak bekerja untukmu?
warvariuc
1
Tidak, tidak. File aktual di direktori kerja asli tidak berubah, tetapi versi bertahap hilang dan diganti dengan versi dari tag. Ini sangat buruk jika versi bertahap berisi serangkaian perubahan yang dipilih dengan cermat untuk dilakukan. Saya tidak ingin perintah ekspor menyentuh indeks saya, titik.
proski
19

Jika Anda bekerja di bawah fitur Anda dan tidak ingin checkout kembali ke master, Anda dapat menjalankan:

cd ./myrepo

git worktree add ../myrepo_master master

git worktree remove ../myrepo_master

Ini akan membuat ../myrepo_masterdirektori dengan masterkomit cabang, tempat Anda dapat melanjutkan pekerjaan

itsnikolay
sumber
1
Jawaban terbaik - sederhana, dan tidak seperti git --work-tree=/path/to/outputdir checkout HEAD -- .itu tidak melakukan apa pun pada indeks, cukup salin cabang yang dipilih ke lokasi yang ditentukan (dengan penambahan file .git).
Roger Dueck
Dan bagaimana saya membatalkan perubahan ini?
Scott P.
@ ScottP.hanya hapus myrepo_masterdirektori
itsnikolay
1
membatalkan ini adalah sub-perintah dari worktree:git worktree remove ../myrepo_master
Martijn Dashorst
8

Jawaban Adrian melemparkan "fatal: Operasi ini harus dijalankan di pohon kerja." Berikut ini yang berhasil bagi kami.

git worktree add <new-dir> --no-checkout --detach
cd <new-dir>
git checkout <some-ref> -- <existing-dir>

Catatan:

  • --no-checkout Jangan checkout apa pun ke dalam worktree baru.
  • --detach Jangan membuat cabang baru untuk tabel kerja baru.
  • <some-ref>bekerja dengan referensi apa pun, misalnya, bekerja dengan HEAD~1.
  • Bersihkan dengan git worktree prune.
Shaun Luttin
sumber
+1 untuk mengomentari cara pembersihan - semua orang senang mengacaukan repo saat ini. hanya yang ini tidak memiliki efek samping.
Andrew Hill
1

Tambahan jawaban @ hasen . Untuk daftar file yang akan checkout , Anda mungkin ingin menggunakan git ls-filesalih-alih findseperti:

git ls-files -z *.txt | git checkout-index --prefix=/path-to/dest/ -f -z --stdin
snipsnipsnip
sumber
Terima kasih telah menggunakan dengan benar -z! Bagus bahwa Anda memberikan skrip yang tidak rentan terhadap serangan injeksi jenis tertentu.
ErikE
0

Saya mendefinisikan alias git untuk mencapai hal ini (sebelum saya menemukan pertanyaan ini).

Ini adalah fungsi bash pendek yang menyimpan jalur saat ini, beralih ke repo git, melakukan checkout dan kembali ke tempat dimulainya.

git check untuk mengembangkan ~ / my_project_git

Contoh ini akan mengecek cabang pengembangan ke direktori "~ / my_project_git".

Ini adalah kode alias di dalamnya ~/.gitconfig:

[alias]
    checkTo = "!f(){ [ -z \"$1\" ] && echo \"Need to specify branch.\" && \
               exit 1; [ -z \"$2\" ] && echo \"Need to specify target\
               dir\" && exit 2; cDir=\"$(pwd)\"; cd \"$2\"; \
               git checkout \"$1\"; cd \"$cDir\"; };f"
cb0
sumber
0

Saya menggunakan alias ini untuk memeriksa cabang di direktori sementara:

[alias]
    cot = "!TEMP=$(mktemp -d); f() { git worktree prune && git worktree add $TEMP $1 && zsh -c \"cd $TEMP; zsh\";}; f" # checkout branch in temporary directory

Pemakaian:

git cot mybranch

Anda kemudian dijatuhkan di shell baru di direktori sementara tempat Anda bisa bekerja di cabang. Anda bahkan dapat menggunakan perintah git di direktori ini.

Setelah selesai, hapus direktori dan jalankan:

git worktree prune

Ini juga dilakukan secara otomatis di alias, sebelum menambahkan worktree baru.

fdietze
sumber
0

Gunakan git archive branch-index | tar -x -C your-folder-on-PCuntuk mengkloning cabang ke folder lain. Saya pikir, maka Anda dapat menyalin file apa pun yang Anda butuhkan

dqthe
sumber