UPDATE² : Dengan Git 2.23 (Agustus 2019), ada perintah baru
git restore
yang melakukan ini, lihat jawaban yang diterima .UPDATE : Ini akan bekerja lebih intuitif pada Git 1.8.3, lihat jawaban saya sendiri .
Bayangkan use case berikut ini: Saya ingin menyingkirkan semua perubahan dalam subdirektori tertentu dari pohon kerja Git saya, membiarkan semua subdirektori lainnya tetap utuh.
Saya bisa melakukannya
git checkout .
, tetapi git checkout. menambahkan direktori yang dikecualikan oleh checkout jarangMemang ada
git reset --hard
, tetapi itu tidak akan membiarkan saya melakukannya untuk subdirektori:> git reset --hard . fatal: Cannot do hard reset with paths.
Lagi: Mengapa git tidak bisa melakukan hard / soft reset dengan jalan?
Saya dapat membalik-tambalan kondisi saat ini menggunakan
git diff subdir | patch -p1 -R
, tetapi ini adalah cara yang agak aneh untuk melakukan ini.
Apa perintah Git yang tepat untuk operasi ini?
Script di bawah ini menggambarkan masalah. Masukkan perintah yang tepat di bawah How to make files
komentar - perintah saat ini akan mengembalikan file a/c/ac
yang seharusnya dikecualikan oleh checkout jarang. Perhatikan bahwa saya tidak ingin mengembalikan secara eksplisit a/a
dan a/b
, saya hanya "tahu" a
dan ingin mengembalikan semuanya di bawah. EDIT : Dan saya juga tidak "tahu" b
, atau direktori lain yang berada pada tingkat yang sama dengan a
.
#!/bin/sh
rm -rf repo; git init repo; cd repo
for f in a b; do
for g in a b c; do
mkdir -p $f/$g
touch $f/$g/$f$g
git add $f/$g
git commit -m "added $f/$g"
done
done
git config core.sparsecheckout true
echo a/a > .git/info/sparse-checkout
echo a/b >> .git/info/sparse-checkout
echo b/a >> .git/info/sparse-checkout
git read-tree -m -u HEAD
echo "After read-tree:"
find * -type f
rm a/a/aa
rm a/b/ab
echo >> b/a/ba
echo "After modifying:"
find * -type f
git status
# How to make files a/* reappear without changing b and without recreating a/c?
git checkout -- a
echo "After checkout:"
git status
find * -type f
sumber
git stash && git stash drop
?git checkout -- /path/to/subdir/
?git stash
tidak menerima argumen jalur ...Jawaban:
Dengan Git 2.23 (Agustus 2019), Anda memiliki perintah baru
git restore
Itu akan menggantikan kedua indeks dan pohon kerja dengan
HEAD
konten, sepertireset --hard
akan, tetapi untuk jalur tertentu.Jawaban asli (2013)
Perhatikan (seperti yang dikomentari oleh Dan Fabulich ) bahwa:
git checkout -- <path>
tidak melakukan hard reset: ia mengganti konten pohon yang berfungsi dengan konten yang dipentaskan.git checkout HEAD -- <path>
melakukan reset keras untuk jalan, mengganti indeks dan pohon yang bekerja dengan versi dariHEAD
komit.Sebagaimana dijawab oleh Ajedi32 , kedua formulir checkout tidak menghapus file yang dihapus dalam revisi target .
Jika Anda memiliki file tambahan di pohon kerja yang tidak ada di HEAD, a
git checkout HEAD -- <path>
tidak akan menghapusnya.Catatan: Dengan
git checkout --overlay HEAD -- <path>
(Git 2.22, Q1 2019) , file yang muncul dalam indeks dan pohon yang berfungsi, tetapi tidak dalam<tree-ish>
dihapus, untuk membuatnya sama<tree-ish>
persis.Tetapi checkout itu dapat menghormati a
git update-index --skip-worktree
(untuk direktori yang ingin Anda abaikan), sebagaimana disebutkan dalam " Mengapa file yang dikecualikan tetap muncul kembali di checkout git sparse saya? ".sumber
git checkout HEAD -- .
, file yang dikecualikan oleh checkout jarang muncul kembali. Apa yanggit update-index --skip-worktree
seharusnya dilakukan?git checkout HEAD -- <path>
, dan kemudian hapus direktori yang dipulihkan (tetapi yang masih dinyatakan dalam checkout jarang).Menurut pengembang Git Duy Nguyen yang dengan ramah mengimplementasikan fitur dan sakelar kompatibilitas , berikut ini berfungsi seperti yang diharapkan pada Git 1.8.3 :
(di mana
a
direktori yang ingin Anda atur ulang). Perilaku asli dapat diakses melaluisumber
git checkout -- .
mana.
artinya direktori saat ini.git reset -- a
(di mana a adalah direktori yang ingin Anda atur ulang)git reset --hard
repo keseluruhan?rm -rf a
sebelumnya.Coba ubah
untuk
Sejak versi 1.7.0, Git menghormati bendera skip-worktree .
ls-files
Menjalankan skrip pengujian Anda (dengan beberapa perubahan kecil yang mengubah
git commit
... kegit commit -q
dangit status
kegit status --short
) menghasilkan:Menjalankan skrip pengujian Anda dengan
checkout
output perubahan yang diusulkan :sumber
git checkout
menghormati bit "skip-worktree"?checkout.c
dantree.c
tidak mengungkapkan bahwa flag skip-worktree digunakan.Untuk kasus hanya membuang perubahan,
git checkout -- path/
ataugit checkout HEAD -- path/
perintah yang disarankan oleh jawaban lain berfungsi dengan baik. Namun, ketika Anda ingin mengatur ulang direktori ke revisi selain HEAD, solusi itu memiliki masalah yang signifikan: itu tidak menghapus file yang dihapus di revisi target.Jadi sebagai gantinya, saya sudah mulai menggunakan perintah berikut:
Ini berfungsi dengan menemukan perbedaan antara komit target dan indeks, kemudian menerapkan perbedaan itu secara terbalik ke direktori kerja dan indeks. Pada dasarnya, ini berarti membuat isi indeks cocok dengan isi revisi yang Anda tentukan. Fakta yang
git diff
mengambil argumen jalur memungkinkan Anda membatasi efek ini ke file atau direktori tertentu.Karena perintah ini cukup panjang dan saya berencana untuk sering menggunakannya, saya telah mengatur alias untuknya yang saya beri nama
reset-checkout
:Anda bisa menggunakannya seperti ini:
Atau hanya:
sumber
git checkout --overlay HEAD -- <path>
perintah yang @VonC sebutkan dalam jawabannya?git checkout --overlay HEAD -- <path>
belum dirilis (Git 2.22 akan dirilis pada Q2 2019)Saya akan menawarkan opsi yang mengerikan di sini, karena saya tidak tahu bagaimana melakukan apa pun dengan git kecuali
add
commit
danpush
, inilah cara saya "mengembalikan" sebuah subdirektori:Saya memulai repositori baru di komputer lokal saya, mengembalikan semuanya ke komit yang ingin saya salin kode dari dan kemudian menyalin file-file itu ke direktori kerja saya,
add
commit
push
dan voila. Jangan membenci pemain, benci Tuan Torvalds karena lebih pintar dari kita semua.sumber
Reset biasanya akan mengubah segalanya, tetapi Anda dapat menggunakan
git stash
untuk memilih apa yang ingin Anda simpan. Seperti yang Anda sebutkan,stash
tidak menerima jalur secara langsung, tetapi masih dapat digunakan untuk menyimpan jalur tertentu dengan--keep-index
bendera. Dalam contoh Anda, Anda akan menyimpan direktori b, lalu mengatur ulang yang lainnya.Ini membawa Anda ke titik di mana bagian terakhir dari skrip Anda akan menampilkan ini:
Saya percaya ini adalah hasil target (b tetap dimodifikasi, a / * file kembali, a / c tidak diciptakan kembali).
Pendekatan ini memiliki manfaat tambahan karena sangat fleksibel; Anda bisa mendapatkan serinci yang Anda inginkan untuk menambahkan file tertentu, tetapi tidak yang lain, dalam direktori.
sumber
git add
semuanya kecualia
, kan? Kedengarannya sulit dalam latihan.git add .
kemudiangit reset a
dapat menambahkan semuanya kecualia
.git add
tidak menambahkan file yang dihapus. Jadi, jika Anda hanya memulihkan file yang dihapus,git add .
akan menambahkan semua file yang dimodifikasi, tetapi tidak yang dihapus.Jika ukuran subdirektori tidak terlalu besar, DAN Anda ingin menjauh dari CLI, berikut ini adalah solusi cepat untuk mengatur ulang subdirektori secara manual :
Bersulang. Anda cukup mereset sub-direktori secara manual di cabang fitur Anda menjadi sama dengan cabang master !!
sumber
Ajedi32 's jawabannya adalah apa yang saya cari tapi untuk beberapa komit aku berlari ke kesalahan ini:
error: cannot apply binary patch to 'path/to/directory' without full index line
Mungkin karena beberapa file direktori adalah file biner. Menambahkan opsi '--binary' ke perintah git diff memperbaikinya:
sumber
Bagaimana dengan
sumber