Hapus file dari Git commit

1613

Saya menggunakan Git dan saya telah melakukan beberapa file menggunakan

git commit -a

Kemudian, saya menemukan bahwa file telah keliru ditambahkan ke komit.

Bagaimana saya bisa menghapus file dari komit terakhir?

Lolly
sumber
2
Tautan ini sangat cocok untuk pertanyaan Anda: stackoverflow.com/questions/307828/…
b3h3m0th
@CharlesB: ya, ini adalah komit terakhir saya
Lolly
8
sudahkah Anda mendorong komit ke server?
Paritosh Singh
4
Saya hanya melakukannya menggunakan:git reset filepath
felipekm

Jawaban:

3090

Saya pikir jawaban lain di sini salah, karena ini adalah pertanyaan untuk memindahkan file yang salah berkomitmen ke area stage dari komit sebelumnya, tanpa membatalkan perubahan yang dilakukan pada mereka. Ini dapat dilakukan seperti yang disarankan Paritosh Singh:

git reset --soft HEAD^ 

atau

git reset --soft HEAD~1

Kemudian atur ulang file yang tidak diinginkan untuk membiarkannya keluar dari komit:

git reset HEAD path/to/unwanted_file

Sekarang komit lagi, Anda bahkan dapat menggunakan kembali pesan komit yang sama:

git commit -c ORIG_HEAD  
juzzlin
sumber
86
Terima kasih untuk ini. Perlu ditambahkan bahwa jika Anda telah mendorong komit Anda sebelumnya (salah), dan sekarang coba git pushperbaiki hingga repo Anda, itu akan mengeluh Updates were rejected because the tip of your current branch is behind its remote counterpart.. Jika Anda yakin ingin mendorongnya (mis. Itu garpu Anda) maka Anda bisa menggunakan -fopsi untuk memaksakan dorongan, mis git push origin master -f. (Jangan lakukan ini pada repo hulu yang diambil orang lain)
andy magoon
57
git reset --soft HEAD^adalah operasi
pembatalan yang
2
@PabloFernandez, pertama-tama, jawaban yang diterima bisa saja apa yang dicari OP (Juga, itu diposting bulan sebelumnya). Kedua, jawaban yang diterima selalu di atas terlepas dari jumlah suara yang naik.
MITjanitor
4
@PabloFernandez di bagian atas dari semua jawaban adalah tiga tab yang memungkinkan Anda untuk mengontrol urutan jawaban: aktif , tertua dan suara . Dugaan saya adalah milik Anda disetel ke terlama . Alihkan ke suara meskipun jawaban yang diterima masih di atas, jawaban ini akan menjadi yang kedua.
ahsteele
15
Saya tahu banyak tentang ini git resettetapi ingin cara untuk mempengaruhi komit yang ada "di tempat". Saya baru tahu git commit -C. Jadi bagi saya, yang saya inginkan adalah resep persis Anda dengan satu langkah lagi, "komit baru lagi" dijabarkan sebagai git commit -C [hash of original HEAD commit from first step].
metamatt
323

PERHATIAN ! Jika Anda hanya ingin menghapus file dari komit Anda sebelumnya, dan menyimpannya di disk , baca jawaban juzzlin atas.

Jika ini adalah komit terakhir Anda dan Anda ingin menghapus file sepenuhnya dari repositori lokal dan jauh Anda, Anda dapat:

  1. hapus file git rm <file>
  2. komit dengan bendera amandemen: git commit --amend

Bendera amand memberitahu git untuk melakukan lagi, tetapi "menggabungkan" (bukan dalam arti menggabungkan dua cabang) ini melakukan dengan komit terakhir.

Seperti yang dinyatakan dalam komentar, menggunakan di git rmsini seperti menggunakan rmperintah itu sendiri!

CharlesB
sumber
120
Anda juga dapat menggunakan git rm --cacheduntuk menyimpan file di disk
Arkadiy Kukarkin
14
Peringatan untuk mereka yang menelusuri jawaban ini: pastikan Anda ingin HAPUS file (seperti yang hilang!), Tidak hanya menghapusnya dari daftar Komit.
Scott Biggs
8
Untuk menambah apa yang orang lain katakan (dan untuk membuatnya lebih mudah untuk diingat untuk tidak melakukan hal ini kecuali jika Anda benar-benar ingin): The rmdalam gitperintah adalah melakukan apa rmsendiri tidak!
yo '
@CharlesB Bisakah Anda menambahkan catatan dari komentar Arkadiy Kukarkin ke jawaban Anda untuk memberikan lebih banyak visibilitas?
mopo922
2
Perhatikan bahwa file masih dapat dipulihkan, jika Anda berubah pikiran, komit sebelumnya git commit --amendmasih ada dan dapat ditemukan misalnya dengan git reflog. Jadi itu tidak seburuk yang dikatakan komentar lain.
Steohan
165

Semua jawaban yang ada berbicara tentang menghapus file yang tidak diinginkan dari yang terakhir komit .

Jika Anda ingin menghapus file yang tidak diinginkan dari yang lama komit (bahkan didorong) dan tidak ingin membuat komit baru, yang tidak perlu, karena tindakan:

1.

Temukan komit yang Anda inginkan file untuk menyesuaikan.

git checkout <commit_id> <path_to_file>

Anda dapat melakukan ini beberapa kali jika Anda ingin menghapus banyak file.

2.

git commit -am "remove unwanted files"

3.

Temukan komit dari komit di mana file ditambahkan secara keliru , katakanlah "35c23c2" di sini

git rebase 35c23c2~1 -i  // notice: "~1" is necessary

Perintah ini membuka editor sesuai dengan pengaturan Anda. Yang standar adalah vim.

Pindahkan komit terakhir, yang seharusnya menjadi "hapus file yang tidak diinginkan", ke baris selanjutnya dari komit yang salah ("35c23c2" dalam kasus kami), dan tetapkan perintah sebagai fixup:

pick 35c23c2 the first commit
fixup 0d78b28 remove unwanted files

Anda harus baik setelah menyimpan file.

Menyelesaikan :

git push -f

Jika Anda sayangnya mendapatkan konflik, Anda harus menyelesaikannya secara manual.

Brian
sumber
2
Melakukan ini dengan nano luar biasa! Ctrl + K, Ctrl + U, beri tanda 'f', Ctrl + X, beri tanda 'y', dan voila!
sequielo
6
Jika Anda benar-benar ingin menghapus file dari repo (bukan sistem file), daripada hanya mengembalikannya ke versi sebelumnya, maka alih-alih langkah 1 lakukan git rm --cached <file(s)>.
waldyrious
2
Tunggu, Anda bisa memindahkan komit di sekitar file rebase interaktif sesuka hati?
Dan Rosenstark
2
Anda benar-benar bisa, tetapi Anda mungkin (atau mungkin tidak) mendapatkan konflik.
Brian
6
Proses ini bisa dibuat sedikit lebih mudah dengan menambahkan --fixup=35c23c2ke git commitperintah. Ini akan mengatur komit secara otomatis sebagai perbaikan dari komit yang diperlukan dan jadi Anda tidak perlu menentukannya di rebase. Selain itu, jika Anda menambahkan --autosquashke git rebaseperintah, git akan secara otomatis memindahkan Anda berkomitmen untuk lokasi yang benar, sehingga Anda tidak perlu melakukan apapun di rebase interaktif - hanya menyimpan hasilnya (yang berarti Anda bahkan tidak perlu -ibendera, meskipun saya tetap ingin menggunakannya untuk memastikan semuanya terlihat seperti yang saya harapkan).
Guss
144

Seperti yang ditunjukkan oleh jawaban yang diterima, Anda dapat melakukan ini dengan mengatur ulang seluruh komit. Tapi ini pendekatan yang agak berat.
Cara yang lebih bersih untuk melakukan ini adalah menjaga komit, dan cukup menghapus file yang diubah darinya.

git reset HEAD^ -- path/to/file
git commit --amend --no-edit

The git resetakan mengambil berkas itu di komit sebelumnya, dan tahap dalam indeks. File di direktori kerja tidak tersentuh.
Kemudian git commitakan melakukan dan menekan indeks ke dalam komit saat ini.

Ini pada dasarnya mengambil versi file yang ada di komit sebelumnya dan menambahkannya ke komit saat ini. Ini menghasilkan tidak ada perubahan bersih, sehingga file dihapus secara efektif dari komit.

Patrick
sumber
5
Ini adalah jawaban yang jauh lebih baik untuk menghapus hanya satu file, tanpa merombak keseluruhan komit.
nimish
Ini persis sama dengan jawaban ini: D stackoverflow.com/a/27340569/1623984
ThatsAMorais
@ThatsAMorais memang :-). Saya bertanya-tanya apakah pertanyaan ini digabungkan dengan pertanyaan lain, dan itulah mengapa saya tidak melihatnya. Atau mungkin aku hanya buta. Yang manapun, saya pikir saya cenderung untuk meninggalkannya karena berdasarkan suara tampaknya lebih populer (mungkin orang lebih suka jawaban pendek dan langsung).
Patrick
Dengan segala cara, tinggalkan saja! :) Kami jelas memiliki ide yang tepat, dan tujuannya adalah untuk membantu. Saya pikir penggabungan adalah teori yang bagus.
ThatsAMorais
Bagaimana Anda melakukan ini jika Anda sudah mendorong ke cabang di github? Saya mencoba mendorong setelah melakukan perbaikan ini dan mendapat pesan "Pembaruan ditolak karena ujung cabang Anda saat ini berada di belakang petunjuk: mitra jarak jauh."
Ollie Williams
41

Jika Anda belum mendorong perubahan pada server yang dapat Anda gunakan

git reset --soft HEAD~1

Ini akan mengatur ulang semua perubahan dan kembali ke satu komit kembali

Jika Anda telah mendorong perubahan Anda, ikuti langkah-langkah yang dijawab oleh @CharlesB

Paritosh Singh
sumber
2
-1 git reset menghapus perubahan file yang terjadi dari area staging, di sini perubahan telah dilakukan
CharlesB
OK, tapi saya akan menyimpan downvote saya karena bukan itu yang diinginkan OP :) maaf
CharlesB
ok tidak apa-apa buat saya, tapi mengapa lawan tidak menginginkan ini. Apa masalahnya?
Paritosh Singh
bukan masalah besar, tetapi karena OP ingin menghapus file yang tidak diinginkan dari komit terakhir, dan itu hanya me-reset ke negara sebelum melakukan. Anda masih harus mengulang komit.
CharlesB
3
@Aris menggunakan <git diff --cached> untuk melihat perubahan
Paritosh Singh
37

Menghapus file menggunakan rm akan menghapusnya!

Anda selalu menambahkan komit di git daripada menghapus, jadi dalam contoh ini kembalikan file ke keadaan sebelum komit pertama (ini mungkin tindakan 'rm' hapus jika file tersebut baru) lalu komit kembali dan file akan pergi.

Untuk mengembalikan file ke kondisi sebelumnya:

    git checkout <commit_id> <path_to_file>

atau mengembalikannya ke status di HEAD remote:

    git checkout origin/master <path_to_file>

kemudian ubah komit dan Anda akan menemukan file telah menghilang dari daftar (dan tidak dihapus dari disk Anda!)

Bob Flannigon
sumber
36
git checkout HEAD~ path/to/file
git commit --amend
Denis Shchepetov
sumber
1
Ini adalah cara terbaik untuk memodifikasi komit terakhir, komitmen yang belum didorong. Ini akan mengatur ulang perubahan dalam satu file, secara efektif menghapus file itu dari komit terakhir.
Alex Bravo
Ini juga mengubah file. Bagaimana cara mempertahankan perubahan lokal pada file?
theonlygusti
29

Yang berikut ini akan membatalkan tahapan hanya file yang Anda maksud, yang diminta OP.

git reset HEAD^ /path/to/file

Anda akan melihat sesuatu seperti yang berikut ...

Perubahan yang harus dilakukan: (gunakan "git reset HEAD ..." untuk unstage)

diubah: / path / ke / file

Perubahan yang tidak dilakukan untuk komit: (gunakan "git add ..." untuk memperbarui apa yang akan dilakukan) (gunakan "git checkout - ..." untuk membuang perubahan dalam direktori kerja)

diubah: / path / ke / file

  • "Perubahan untuk dikomit" adalah versi file sebelumnya sebelum komit. Ini akan terlihat seperti penghapusan jika file tidak pernah ada. Jika Anda melakukan perubahan ini, akan ada revisi yang mengembalikan perubahan ke file di cabang Anda.
  • "Perubahan yang tidak dilakukan untuk komit" adalah perubahan yang Anda komit, dan status file saat ini

Pada titik ini, Anda dapat melakukan apa pun yang Anda suka ke file, seperti mengatur ulang ke versi yang berbeda.

Saat Anda siap untuk berkomitmen:

git commit --amend -a

atau (jika Anda memiliki beberapa perubahan lain yang belum Anda lakukan, belum)

git commit add /path/to/file
git commit --amend
ThatsAMorais
sumber
3
Jawaban juzzlin sangat bagus, tetapi berlebihan untuk membatalkan tahapan seluruh komit ketika Anda hanya ingin menghapus stage. Menghapus seluruh komit dapat menyebabkan masalah jika saat ini Anda tidak melakukan perubahan pada file di komit yang tidak ingin Anda lewatkan.
ThatsAMorais
27

Saya akan menjelaskan kepada Anda dengan contoh.
Biarkan A, B, C menjadi 3 komitmen berturut-turut. Komit B berisi file yang seharusnya tidak dilakukan.

git log  # take A commit_id
git rebase -i "A_commit_ID" # do an interactive rebase
change commit to 'e' in rebase vim # means commit will be edited
git rm unwanted_file
git rebase --continue
git push --force-with-lease <branchName>    
Moaz Rashad
sumber
Jika file tertentu tidak dalam komit terakhir atau sebelumnya, ini adalah cara yang paling elegan. Saya bahkan akan mengatakan itu adalah cara paling elegan secara umum. Saya suka rebasing interaktif.
bvgheluwe
Untuk komitmen tunggal, ubah noopke edit [A_commit_ID]ataue [A_commit_ID]
TamusJRoyce
23

Anda cukup mencoba.

git reset --soft HEAD~1

dan buat komit baru.

Namun, ada perangkat lunak yang luar biasa "gitkraken". yang membuatnya mudah untuk bekerja dengan git.

HamzaMushtaq
sumber
1
Dan hanya untuk dicatat: setelah ini, Anda harus melakukan git commit --amendpenghapusan file diperbarui di komit terakhir Anda; dan setelahnya, Anda dapat memeriksa memang telah dihapus dengangit log -1 --stat
sdbbs
13
git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "removed unwanted file from git"

akan meninggalkan Anda file lokal. Jika Anda tidak menginginkan file tersebut secara lokal, Anda dapat melewati opsi --cached.

Jika semua pekerjaan ada di cabang lokal Anda, Anda perlu menyimpan file di komit kemudian, dan seperti memiliki riwayat bersih, saya pikir cara yang lebih sederhana untuk melakukan ini bisa menjadi:

git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit --squash <commit_id>
git add <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "brand new file!"
git rebase --interactive <commit_id>^

dan Anda kemudian dapat menyelesaikan rebase dengan mudah tanpa harus mengingat perintah yang lebih kompleks atau komit pesan atau ketik sebanyak.

Bryan Buckley
sumber
Ini bekerja untuk saya. Saya berasumsi jika Anda ingin menambahkan file kembali ke dalam campuran, cukup gunakan git add -A atau git add. dan mereka kembali.
Alexander Mills
11

Menggunakan git GUI dapat menyederhanakan menghapus file dari komit sebelumnya.

Dengan asumsi bahwa ini bukan cabang bersama dan Anda tidak keberatan menulis ulang riwayat , maka jalankan:

git gui citool --amend

Anda dapat menghapus centang pada file yang keliru dilakukan dan kemudian klik "Komit".

masukkan deskripsi gambar di sini

File dihapus dari komit, tetapi akan disimpan di disk . Jadi, jika Anda tidak memeriksa file setelah menambahkannya secara keliru, itu akan ditampilkan dalam daftar file Anda yang tidak dilacak (dan jika Anda tidak memeriksa file setelah salah memodifikasi, itu akan ditampilkan dalam perubahan Anda tidak dipentaskan untuk daftar komit).

JDiMatteo
sumber
2
Di Ubuntu, Anda dapat menginstal git gui dengansudo apt-get install git-gui
JDiMatteo
Terima kasih! Saya terjebak dengan masalah (bug?) Di mana folder yang berisi repo .git ditambahkan, dan semua perintah hapus biasa tidak berfungsi. Namun ini membantu. Karena beberapa komit kembali, saya pertama kali memanfaatkan git rebase -i HEAD~4dan kemudian menjalankan perintah Anda untuk membuka editor. Catatan lain: "Unstaging" dapat ditemukan di menu "Commit".
Johny Skovdal
Solusi termudah dari semuanya. Paling sederhana untuk diingat. Dan jauh lebih sedikit kesalahan daripada menggunakan git reset --soft HEAD^(mengingat --soft arg), diikuti oleh git commit -c ORIG_HEAD(daripada - amend, yang mengacaukan semuanya).
Brent Faust
9

Jika Anda ingin menyimpan komit (mungkin Anda sudah menghabiskan waktu menulis pesan komit terperinci dan tidak ingin kehilangan komit), dan Anda hanya ingin menghapus file dari komit, tetapi tidak dari repositori sepenuhnya:

git checkout origin/<remote-branch> <filename>
git commit --amend
mattexx
sumber
6

Lakukan urutan perintah berikut:

//to remove the last commit, but preserve changes  
git reset --soft HEAD~1

//to remove unneded file from the staging area  
git reset HEAD `<your file>` 

//finally make a new commit  
git commit -m 'Your message'
Sergey Onishchenko
sumber
Saya sudah mencoba melakukan langkah-langkah ini, dan saya melihat kesalahan kesalahan ini: gagal mendorong beberapa referensi untuk 'git ....' Untuk mencegah Anda kehilangan riwayat, pembaruan yang tidak dipercepat ditolak. Gabungkan perubahan jarak jauh (mis. 'git pull') sebelum mendorong lagi. Lihat bagian 'Catatan tentang maju cepat' dari 'git push --help' untuk detailnya. (setelah git pull, saya memiliki perubahan yang sama)
Dezigo
Ini berarti bahwa keadaan repo jarak jauh Anda telah berubah saat Anda melakukan pekerjaan lokal Anda. Dan setelah 'git pull' perubahan lokal Anda harus digabung dengan yang jauh, itu saja. Tentu saja, perubahan Anda harus tetap.
Sergey Onishchenko
Dengan kata lain, jika Anda mendapatkan kesalahan @Dezigo, tambahkan flag -f untuk memaksa pembaruan.
jungledev
5

Hanya ingin melengkapi jawaban teratas karena saya harus menjalankan perintah tambahan:

git reset --soft HEAD^
git checkout origin/master <filepath>

Bersulang!

dan repo
sumber
Selamat datang. Jawaban ini akan lebih baik jika Anda menjelaskan apa yang sebenarnya dilakukan perintah.
Mark Chorley
3

Sesuatu yang bekerja untuk saya, tetapi masih berpikir harus ada solusi yang lebih baik:

$ git revert <commit_id>
$ git reset HEAD~1 --hard

Biarkan saja perubahan yang ingin Anda buang di komit lain, periksa yang lain

$ git commit --amend // or stash and rebase to <commit_id> to amend changes
saiyancoder
sumber
3

git reset --soft HEAD^mengembalikan komit Anda, dan saat Anda mengetik git status, itu memberi tahu Anda apa yang harus dilakukan:

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
kapulaga
sumber
2

Sebenarnya, saya pikir cara yang lebih cepat dan lebih mudah adalah dengan menggunakan mode interaktif git rebase.

git rebase -i head~1  

(Atau kepala ~ 4, seberapa jauh Anda ingin pergi)

dan kemudian, alih-alih 'memilih', gunakan 'edit'. Saya tidak menyadari betapa kuatnya 'edit' itu.

https://www.youtube.com/watch?v=2dQosJaLN18

Semoga Anda merasa terbantu.

Mat
sumber
videonya 10 menit dan tidak terlalu berguna
MolbOrg
2

Punya masalah yang sama di mana saya memiliki perubahan di cabang lokal di mana saya ingin mengembalikan hanya satu file. Apa yang berhasil untuk saya adalah -

( fitur / target_branch di bawah adalah tempat saya memiliki semua perubahan saya termasuk yang ingin saya batalkan untuk file tertentu)

( asal / fitur / target_branch adalah cabang jarak jauh tempat saya ingin mendorong perubahan saya)

( fitur / pementasan adalah cabang pementasan sementara saya di mana saya akan mendorong dari semua perubahan yang saya inginkan kecuali perubahan ke satu file)

  1. Buat cabang lokal dari asal / fitur / target_branch saya - menyebutnya fitur / pementasan

  2. Menggabungkan fitur cabang lokal saya / target_branch ke cabang fitur / pementasan

  3. Memeriksa fitur / pementasan lalu git reset --soft ORIG_HEAD (Sekarang semua perubahan dari fitur / pementasan 'akan dipentaskan tetapi tidak dikomit.)

  4. Unstaged file yang sebelumnya saya laporkan dengan perubahan yang tidak perlu

  5. Mengubah cabang upstream untuk fitur / pementasan ke asal / fitur / target_branch

  6. Mengkomit selebihnya dari perubahan bertahap dan mendorong upstream ke asal / fitur / target_branch jauh saya

pengguna1201303
sumber
1

Jika Anda tidak membutuhkan file itu lagi, Anda bisa melakukannya

git rm file
git commit --amend
git push origin branch
tven
sumber
1

Jika Anda menggunakan GitHub dan belum mendorong komit, GitHub Desktop menyelesaikan masalah ini dengan mudah:

  1. Pilih Repositori -> Batalkan Komit Terkini
  2. Batalkan pilihan file yang Anda tambahkan secara keliru. Pesan komit Anda sebelumnya akan berada di kotak dialog.
  3. Tekan tombol Komit!
Ron
sumber
1

Jika Anda ingin menghapus file dari komit sebelumnya gunakan filter

git filter-branch --prune-empty --index-filter 'git rm --ignore-unmatch --cached "file_to_be_removed.dmg"'

Jika Anda melihat kesalahan ini:

Tidak dapat membuat cadangan baru. Cadangan sebelumnya sudah ada di referensi / asli / Paksa menimpa cadangan dengan -f

Hapus saja cadangan referensi pada repo lokal Anda

$ rm -rf .git/refs/original/refs
wilo087
sumber
1

jika Anda tidak mendorong perubahan Anda untuk git

git reset --soft HEAD~1

Ini akan mengatur ulang semua perubahan dan kembali ke satu komit kembali

Jika ini adalah komit terakhir yang Anda buat dan Anda ingin menghapus file dari repositori lokal dan jauh coba ini:

git rm <file>
 git commit --amend

atau bahkan lebih baik:

atur ulang dulu

git reset --soft HEAD~1

setel ulang file yang tidak diinginkan

git reset HEAD path/to/unwanted_file

komit lagi

git commit -c ORIG_HEAD  
TanvirChowdhury
sumber
itu sama seperti di atas tetapi bahkan sangat membantu untuk memeriksa ulang
Reshma
0

Ini berfungsi bagi saya untuk menghapus file dari bit ember repo yang saya mendorong file ke cabang awalnya.

git checkout origin/develop <path-to-file>
git add <path-to-file>
git commit -m "Message"
git push
swathi
sumber
0

Saya menyalin file saat ini di folder yang berbeda, kemudian menyingkirkan semua perubahan yang tidak dicopot dengan:

git reset --hard @{u}

Kemudian salin kembali. Komit, Dorong.

Miranda
sumber
0

Anda cukup menggunakan perintah ini:

git restore --staged <file>
suulisin
sumber
0
Here is the step to remove files from Git Commit.

>git reset --soft HEAD^1(either commitid ) -- now files moved to the staging area.
>git rm --cached filename(it will removed the file from staging area)
>git commit -m 'meaningfull message'(Now commit the required files)
Sheo Dayal Singh
sumber
-1

Tidak ada jawaban saat ini yang masuk akal. Kedengarannya ada permintaan yang cukup bahwa solusi nyata harus diusulkan: https://github.com/git/git/blob/master/Documentation/SubmittingPatches

git --uncommit <nama file>

akan menyenangkan. Saya mengerti bahwa kita tidak ingin memodifikasi riwayat, tetapi jika saya lokal dan tidak sengaja menambahkan file "retas" lokal dan ingin menghapusnya dari komit, ini akan sangat membantu.

Bob9630
sumber