Bagaimana cara checkout hanya satu file dari repo git?
Bagaimana cara checkout hanya satu file dari repo git?
Jawaban:
Awalnya, saya sebutkan pada 2012 git archive
(lihat Jared Forsyth 's jawaban dan Robert Ksatria ' s jawaban ), karena git1.7.9.5 (Maret 2012) , Paul Brannan 's jawabannya :
git archive --format=tar --remote=origin HEAD:path/to/directory -- filename | tar -O -xf -
Tetapi: pada 2013, itu tidak lagi memungkinkan untuk URL https://github.com jarak jauh .
Lihat halaman lama " Bisakah saya mengarsipkan repositori? "
Halaman saat ini (2018) " Tentang pengarsipan konten dan data di GitHub " merekomendasikan penggunaan layanan pihak ketiga seperti GHTorrent atau GH Archive .
Jadi Anda juga bisa berurusan dengan salinan / klon lokal:
Anda bisa juga melakukan yang berikut jika Anda memiliki salinan lokal dari repositori telanjang seperti yang disebutkan dalam jawaban ini ,
git --no-pager --git-dir /path/to/bar/repo.git show branch:path/to/file >file
Atau Anda harus mengkloning repo terlebih dahulu, yang berarti Anda mendapatkan riwayat lengkap: - dalam repo .git - di pohon kerja.
git config core.sparsecheckout true
).git/info/sparse-checkout
fileUntuk membaca kembali pohon yang berfungsi:
$ git read-tree -m -u HEAD
Dengan begitu, Anda berakhir dengan pohon kerja termasuk apa yang Anda inginkan (meskipun hanya satu file)
Richard Gomes menunjuk ( dalam komentar ) untuk " Bagaimana saya mengkloning, mengambil, atau jarang checkout satu direktori atau daftar direktori dari repositori git? "
Fungsi bash yang menghindari pengunduhan riwayat, yang mengambil cabang tunggal dan yang mengambil daftar file atau direktori yang Anda butuhkan.
git archive
sekarang.
Klon pertama repo dengan opsi -n, yang menekan checkout default semua file, dan opsi --depth 1, yang berarti hanya mendapat revisi terbaru dari setiap file
git clone -n git://path/to/the_repo.git --depth 1
Kemudian periksa file yang Anda inginkan seperti itu:
cd the_repo
git checkout HEAD name_of_file
-n
pohon kerja dan indeks berakhir sinkron. Artinya, semua konten muncul sebagai dihapus. Anda harus salah satu git reset HEAD
atau git checkout HEAD file
. Juga sangat sulit untuk bekerja dengan repositori pada saat ini kecuali Anda benar-benar mengerti cara kerja git.
rm -rf .git
ke skrip NickMoore akan membersihkan semua jejak repo yang dikloning dan mungkin menghilangkan kepedulian Jefromi tentang memiliki repo yang sulit digunakan untuk diletakkan. Membuatnya sangat berguna bagi saya untuk beberapa aplikasi, seperti tantangan saya hari ini untuk membangun kait pasca-terima untuk memperbarui versi kait pasca-terima lain secara otomatis.
git
bukan yang terbaik untuk pekerjaan semacam ini). Jawaban ini juga berlaku untuk pertanyaan ini , atau yang populer lainnya , dan banyak yang lain: ubah name_of_file
ke name_of_folder
. Git di saat ini (2014) menawarkan submodul kepada pemilik repo menawarkan beberapa por friendly untuk pengguna repo.
Jika Anda sudah memiliki salinan git repo, Anda selalu dapat checkout versi file menggunakan a git log
untuk mengetahui hash-id (misalnya 3cdc61015724f9965575ba954c8cd4232c8b42e4) dan kemudian Anda cukup mengetik:
git checkout hash-id path-to-file
Ini adalah contoh aktual:
git checkout 3cdc61015724f9965575ba954c8cd4232c8b42e4 /var/www/css/page.css
path-to-file
direktori, dan saat ini HEAD
berisi file tertentu sementara target
tidak, (atau sebaliknya), ini tidak akan memperbarui file dengan benar. Apakah ada cara untuk mengatasinya?
Biasanya tidak mungkin mengunduh hanya satu file git
tanpa mengunduh seluruh repositori seperti yang disarankan dalam jawaban pertama. Itu karena Git tidak menyimpan file seperti yang Anda pikirkan (seperti yang dilakukan CVS / SVN), tetapi Git menghasilkannya berdasarkan seluruh sejarah proyek.
Tetapi ada beberapa solusi untuk kasus-kasus tertentu. Contoh di bawah ini dengan placeholder untuk user
, project
, branch
, filename
.
GitHub
wget https://raw.githubusercontent.com/user/project/branch/filename
GitLab
wget https://gitlab.com/user/project/raw/branch/filename
GitWeb
Jika Anda menggunakan Git di Server - GitWeb , maka Anda dapat mencoba contohnya (mengubahnya menjadi jalur yang benar):
wget "http://example.com/gitweb/?p=example;a=blob_plain;f=README.txt;hb=HEAD"
GitWeb di drupalcode.org
Contoh:
wget "http://drupalcode.org/project/ads.git/blob_plain/refs/heads/master:/README.md"
googlesource.com
Ada fitur tidak berdokumen yang memungkinkan Anda mengunduh versi mentah file yang disandikan base64:
curl "https://chromium.googlesource.com/chromium/src/net/+/master/http/transport_security_state_static.json?format=TEXT" | base64 --decode
Dalam kasus lain, periksa apakah repositori Git Anda menggunakan antarmuka web apa pun.
Jika tidak menggunakan antarmuka web apa pun, Anda dapat mempertimbangkan untuk mendorong kode Anda ke layanan eksternal seperti GitHub , Bitbucket , dll. . dan menggunakannya sebagai cermin.
Jika Anda belum wget
menginstal, coba curl -O (url)
alternatifnya.
wget
jawaban yang brilian dan kesederhanaan ini kembali, bersama dengan kebahagiaan. Terima kasih sobat.
git checkout branch_or_version - path / file
contoh: git checkout HEAD -- main.c
git checkout -- <filename>
Ref: https://git-scm.com/docs/git-checkout
Dup: Membatalkan modifikasi copy pekerjaan dari satu file di Git?
git-checkout
.
Sekarang kita bisa! Karena ini adalah hasil pertama di google, saya pikir saya akan memperbarui ini ke posisi terbaru. Dengan munculnya git 1.7.9.5, kami memiliki git archive
perintah yang akan memungkinkan Anda untuk mengambil satu file dari host jarak jauh.
git archive --remote=git://git.foo.com/project.git HEAD:path/in/repo filename | tar -x
Lihat jawaban lengkapnya di sini https://stackoverflow.com/a/5324532/290784
github.com
HEAD
atau master
tidak HEAD:directory
.
git archive --remote=git@bitbucket.org:user/repo branch:path/to file | tar -x
Bekerja di GIT 1.7.2.2
Misalnya Anda memiliki remote some_remote dengan cabang-cabang branch1 , branch32
jadi untuk checkout file tertentu Anda memanggil perintah ini:
git checkout remote/branch path/to/file
sebagai contoh akan seperti ini
git checkout some_remote/branch32 conf/en/myscript.conf
git checkout some_remote/branch1 conf/fr/load.wav
Perintah checkout ini akan menyalin seluruh struktur file conf / en dan conf / fr ke direktori saat ini di mana Anda memanggil perintah-perintah ini (tentu saja saya menganggap Anda menjalankan git init di beberapa titik sebelumnya)
git fetch some_remote
sebelumnya, bukan?
Sangat sederhana:
git checkout from-branch-name -- path/to/the/file/you/want
Ini tidak akan checkout from-branch-name
cabang. Anda akan tetap pada cabang apa pun Anda berada, dan hanya file tunggal yang akan diperiksa dari cabang tertentu.
Inilah bagian yang relevan dari halaman manual ini git-checkout
git checkout [-p|--patch] [<tree-ish>] [--] <pathspec>...
When <paths> or --patch are given, git checkout does not switch
branches. It updates the named paths in the working tree from the
index file or from a named <tree-ish> (most often a commit). In
this case, the -b and --track options are meaningless and giving
either of them results in an error. The <tree-ish> argument can be
used to specify a specific tree-ish (i.e. commit, tag or tree) to
update the index for the given paths before updating the working
tree.
Hat tip untuk Ariejan de Vroom yang mengajari saya ini dari posting blog ini .
git clone --filter
dari Git 2.19
Opsi ini sebenarnya akan melewatkan mengambil sebagian besar objek yang tidak dibutuhkan dari server:
git clone --depth 1 --no-checkout --filter=blob:none \
"file://$(pwd)/server_repo" local_repo
cd local_repo
git checkout master -- mydir/myfile
Server harus dikonfigurasi dengan:
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1
Tidak ada dukungan server pada v2.19.0, tetapi sudah dapat diuji secara lokal.
TODO: --filter=blob:none
melompati semua gumpalan, tetapi masih mengambil semua objek pohon. Tetapi pada repo yang normal, ini harus kecil dibandingkan dengan file itu sendiri, jadi ini sudah cukup baik. Ditanya di: https://www.spinics.net/lists/git/msg342006.html Devs menjawab a --filter=tree:0
sedang mengerjakan hal itu.
Ingat yang --depth 1
sudah tersirat --single-branch
, lihat juga: Bagaimana saya mengkloning satu cabang di Git?
file://$(path)
diperlukan untuk mengatasi git clone
protokol shenanigans: Bagaimana cara dangkal mengkloning repositori git lokal dengan path relatif?
Format --filter
didokumentasikan pada man git-rev-list
.
Ekstensi dibuat untuk protokol jarak jauh Git untuk mendukung fitur ini.
Documents on Git tree:
Uji itu
#!/usr/bin/env bash
set -eu
list-objects() (
git rev-list --all --objects
echo "master commit SHA: $(git log -1 --format="%H")"
echo "mybranch commit SHA: $(git log -1 --format="%H")"
git ls-tree master
git ls-tree mybranch | grep mybranch
git ls-tree master~ | grep root
)
# Reproducibility.
export GIT_COMMITTER_NAME='a'
export GIT_COMMITTER_EMAIL='a'
export GIT_AUTHOR_NAME='a'
export GIT_AUTHOR_EMAIL='a'
export GIT_COMMITTER_DATE='2000-01-01T00:00:00+0000'
export GIT_AUTHOR_DATE='2000-01-01T00:00:00+0000'
rm -rf server_repo local_repo
mkdir server_repo
cd server_repo
# Create repo.
git init --quiet
git config --local uploadpack.allowfilter 1
git config --local uploadpack.allowanysha1inwant 1
# First commit.
# Directories present in all branches.
mkdir d1 d2
printf 'd1/a' > ./d1/a
printf 'd1/b' > ./d1/b
printf 'd2/a' > ./d2/a
printf 'd2/b' > ./d2/b
# Present only in root.
mkdir 'root'
printf 'root' > ./root/root
git add .
git commit -m 'root' --quiet
# Second commit only on master.
git rm --quiet -r ./root
mkdir 'master'
printf 'master' > ./master/master
git add .
git commit -m 'master commit' --quiet
# Second commit only on mybranch.
git checkout -b mybranch --quiet master~
git rm --quiet -r ./root
mkdir 'mybranch'
printf 'mybranch' > ./mybranch/mybranch
git add .
git commit -m 'mybranch commit' --quiet
echo "# List and identify all objects"
list-objects
echo
# Restore master.
git checkout --quiet master
cd ..
# Clone. Don't checkout for now, only .git/ dir.
git clone --depth 1 --quiet --no-checkout --filter=blob:none "file://$(pwd)/server_repo" local_repo
cd local_repo
# List missing objects from master.
echo "# Missing objects after --no-checkout"
git rev-list --all --quiet --objects --missing=print
echo
echo "# Git checkout fails without internet"
mv ../server_repo ../server_repo.off
! git checkout master
echo
echo "# Git checkout fetches the missing file from internet"
mv ../server_repo.off ../server_repo
git checkout master -- d1/a
echo
echo "# Missing objects after checking out d1/a"
git rev-list --all --quiet --objects --missing=print
Output dalam Git v2.19.0:
# List and identify all objects
c6fcdfaf2b1462f809aecdad83a186eeec00f9c1
fc5e97944480982cfc180a6d6634699921ee63ec
7251a83be9a03161acde7b71a8fda9be19f47128
62d67bce3c672fe2b9065f372726a11e57bade7e
b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
308150e8fddde043f3dbbb8573abb6af1df96e63 d1/a
f70a17f51b7b30fec48a32e4f19ac15e261fd1a4 d1/b
84de03c312dc741d0f2a66df7b2f168d823e122a d2
0975df9b39e23c15f63db194df7f45c76528bccb d2/a
41484c13520fcbb6e7243a26fdb1fc9405c08520 d2/b
7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
8b25206ff90e9432f6f1a8600f87a7bd695a24af master/master
ef29f15c9a7c5417944cc09711b6a9ee51b01d89
19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
1b671b190e293aa091239b8b5e8c149411d00523 mybranch/mybranch
c3760bb1a0ece87cdbaf9a563c77a45e30a4e30e
a0234da53ec608b54813b4271fbf00ba5318b99f root
93ca1422a8da0a9effc465eccbcb17e23015542d root/root
master commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
mybranch commit SHA: fc5e97944480982cfc180a6d6634699921ee63ec
040000 tree b64bf435a3e54c5208a1b70b7bcb0fc627463a75 d1
040000 tree 84de03c312dc741d0f2a66df7b2f168d823e122a d2
040000 tree 7d5230379e4652f1b1da7ed1e78e0b8253e03ba3 master
040000 tree 19f7a4ca4a038aff89d803f017f76d2b66063043 mybranch
040000 tree a0234da53ec608b54813b4271fbf00ba5318b99f root
# Missing objects after --no-checkout
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
?308150e8fddde043f3dbbb8573abb6af1df96e63
# Git checkout fails without internet
fatal: '/home/ciro/bak/git/test-git-web-interface/other-test-repos/partial-clone.tmp/server_repo' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
# Git checkout fetches the missing directory from internet
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1/1), 45 bytes | 45.00 KiB/s, done.
# Missing objects after checking out d1
?f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
?8b25206ff90e9432f6f1a8600f87a7bd695a24af
?41484c13520fcbb6e7243a26fdb1fc9405c08520
?0975df9b39e23c15f63db194df7f45c76528bccb
Kesimpulan: semua gumpalan kecuali d1/a
hilang. Misalnya f70a17f51b7b30fec48a32e4f19ac15e261fd1a4
, yang d1/b
tidak ada setelah check outd1/
.
Perhatikan itu root/root
dan mybranch/mybranch
juga hilang, tetapi --depth 1
menyembunyikannya dari daftar file yang hilang. Jika Anda menghapus --depth 1
, maka mereka muncul di daftar file yang hilang.
Anda bisa melakukannya dengan
git archive --format=tar --remote=origin HEAD | tar xf -
git archive --format=tar --remote=origin HEAD <file> | tar xf -
Dua varian tentang apa yang sudah diberikan:
git archive --format=tar --remote=git://git.foo.com/project.git HEAD:path/to/directory filename | tar -O -xf -
dan:
git archive --format=zip --remote=git://git.foo.com/project.git HEAD:path/to/directory filename | funzip
Ini menulis file ke output standar.
Di git Anda tidak melakukan 'checkout' file sebelum Anda memperbaruinya - sepertinya inilah yang Anda cari.
Banyak sistem seperti clearcase, csv dan sebagainya mengharuskan Anda untuk 'checkout' file sebelum Anda dapat mengubahnya. Git tidak memerlukan ini. Anda mengkloning repositori dan kemudian membuat perubahan dalam salinan repositori lokal Anda.
Setelah Anda memperbarui file yang dapat Anda lakukan:
git status
Untuk melihat file apa yang telah dimodifikasi. Anda menambahkan yang ingin Anda komit index
dulu ( index
seperti daftar yang harus diperiksa):
git add .
atau
git add blah.c
Maka do git status
akan menunjukkan kepada Anda file mana yang dimodifikasi dan yang index
siap untuk dilakukan atau diperiksa.
Untuk mengkomit file ke salinan repositori Anda, lakukan:
git commit -a -m "commit message here"
Lihat git
situs web untuk tautan ke manual dan panduan.
git format-patch
untuk membuat tambalan untuk pengiriman ( git format-patch -1
akan membuat tambalan hanya untuk komit terbaru Anda).
Berikut adalah solusi lengkap untuk menarik dan mendorong hanya file tertentu di dalam repositori git:
git clone --no-checkout <git url>
git reset
git checkout origin/master <path to file>
git add <path to file>
git commit -m <message text>
git push
Lihat juga tautan untuk beberapa info tambahan.
Kedengarannya seperti Anda mencoba untuk meneruskan ide dari kontrol versi terpusat, yang git pada dasarnya tidak - itu didistribusikan. Jika Anda ingin bekerja dengan repositori git, Anda mengkloningnya. Anda kemudian memiliki semua konten dari pohon kerja, dan semua sejarah (well, setidaknya semuanya mengarah ke ujung cabang saat ini), bukan hanya satu file atau snapshot dari komit tunggal.
git clone /path/to/repo
git clone git://url/of/repo
git clone http://url/of/repo
Jika Anda memerlukan file tertentu dari cabang tertentu dari repositori Git jarak jauh, perintahnya adalah:
git archive --remote=git://git.example.com/project.git refs/heads/mybranch path/to/myfile |tar xf -
Sisanya dapat diturunkan dari jawaban @ VonC:
Jika Anda memerlukan file tertentu dari cabang master, itu adalah:
git archive --remote=git://git.example.com/project.git HEAD path/to/myfile |tar xf -
Jika Anda memerlukan file tertentu dari tag, itu adalah:
git archive --remote=git://git.example.com/project.git mytag path/to/myfile |tar xf -
Saya tidak melihat apa yang berhasil bagi saya yang tercantum di sini jadi saya akan memasukkannya jika ada yang berada dalam situasi saya.
Situasi saya, saya memiliki repositori jarak jauh mungkin 10.000 file dan saya perlu membangun file RPM untuk sistem Linux saya. Membangun RPM mencakup klon git dari segalanya. Yang saya butuhkan adalah satu file untuk memulai RPM build. Saya dapat mengkloning seluruh pohon sumber yang melakukan apa yang saya butuhkan tetapi butuh dua menit ekstra untuk mengunduh semua file itu ketika yang saya butuhkan hanyalah satu. Saya mencoba menggunakan opsi arsip git yang dibahas dan saya mendapatkan "fatal: Operasi tidak didukung oleh protokol." Sepertinya saya harus mengaktifkan opsi arsip di server dan server saya dikelola oleh penjahat birokratis yang sepertinya senang mempersulit penyelesaiannya.
Apa yang akhirnya saya lakukan adalah saya pergi ke antarmuka web untuk bitbucket dan melihat satu file yang saya butuhkan. Saya melakukan klik kanan pada tautan untuk mengunduh salinan mentah dari file dan memilih “copy shortcut” dari popup yang dihasilkan. Saya tidak bisa hanya mengunduh file mentah karena saya perlu mengotomatisasi sesuatu dan saya tidak memiliki antarmuka browser di server Linux saya.
Demi diskusi, yang menghasilkan URL:
https://ourArchive.ourCompany.com/projects/ThisProject/repos/data/raw/foo/bar.spec?at=refs%2Fheads%2FTheBranchOfInterest
Saya tidak dapat langsung mengunduh file ini dari repositori bitbucket karena saya harus masuk terlebih dahulu. Setelah sedikit menggali, saya menemukan ini berhasil: Di Linux:
echo "myUser:myPass123"| base64
bXlVc2VyOm15UGFzczEyMwo=
curl -H 'Authorization: Basic bXlVc2VyOm15UGFzczEyMwo=' 'https://ourArchive.ourCompany.com/projects/ThisProject/repos/data/raw/foo/bar.spec?at=refs%2Fheads%2FTheBranchOfInterest' > bar.spec
Kombinasi ini memungkinkan saya untuk mengunduh satu file yang saya perlukan untuk membangun yang lainnya.
Saya menambahkan jawaban ini sebagai alternatif untuk melakukan checkout resmi atau operasi lokal serupa. Dengan asumsi bahwa Anda memiliki akses ke antarmuka web penyedia Git Anda, Anda mungkin dapat langsung melihat file apa pun pada komit yang diinginkan yang diberikan. Misalnya, di GitHub Anda dapat menggunakan sesuatu seperti:
https://github.com/hubotio/hubot/blob/ed25584f/src/adapter.coffee
Berikut ed25584f
adalah 8 karakter pertama dari hash SHA-1 dari commit of interest, diikuti oleh path ke file sumber.
Similary, di Bitbucket kita dapat mencoba:
https://bitbucket.org/cofarrell/stash-browse-code-plugin/src/06befe08
Dalam hal ini, kami menempatkan hash komit di akhir URL sumber.
Jika Anda hanya perlu mengunduh file, tidak perlu memeriksa dengan Git.
GitHub Mate jauh lebih mudah untuk melakukannya, itu adalah ekstensi Chrome, memungkinkan Anda mengklik ikon file untuk mengunduhnya. juga open source
git
! =github
Jika Anda telah mengedit versi lokal file dan ingin kembali ke versi asli yang dikelola di server pusat, ini dapat dengan mudah dicapai menggunakan Git Extensions .
Mudah!