Tidak dapat mendorong ke GitHub karena file besar yang sudah saya hapus

272

Saat ini saya sudah

  1. Repo GitHub kosong
  2. Repo server SSH (utama)
  3. Repo Lokal

Repo server SSH adalah repo (situs produksi) yang paling mutakhir, jadi saya melakukan klon Git dari sana ke lokal. Saya kemudian mencoba melakukan git pushke GitHub.

Semuanya berjalan baik tetapi kemudian mengatakan sesuatu tentang nama file. Terlalu besar untuk GitHub. Saya tidak memerlukan file ini jadi saya menjalankan beberapa perintah Git untuk menyingkirkannya dari Git cache kemudian mendorong kembali ke server SSH.

Saya tidak melihat file besar secara lokal tetapi masih di server SSH meskipun git difftidak mengembalikan apa pun dan git push return "Semuanya up-to-date" - Dan meskipun file tersebut tidak terlihat dalam repo lokal ketika saya mencoba untuk mendorong ke GitHub saya masih mendapatkan kesalahan tentang hal itu

remote: error: File fpss.tar.gz adalah 135,17 MB; ini melebihi batas ukuran file GitHub sebesar 100 MB

Saya mengikuti langkah-langkah di bawah "memperbaiki masalah" yang tercantum pada bantuan GitHub jadi bukankah itu sudah cukup?

Bagaimana file masih dalam eter ketika itu tidak lokal atau terdaftar dalam status git / diff / push?

Kevin W.
sumber
2
File tersebut masih ada dalam sejarah. Anda perlu menghancurkan histori, mungkin dengan menekan komit yang menambahkan dan menghapus file.
Shahbaz
@ Shahbaz, saya mengikuti langkah-langkah di bawah "memperbaiki masalah" yang tercantum di situs ini ... bukankah itu sudah cukup? help.github.com/articles/working-with-large-files
Kevin W.
Perintah di sana lebih maju daripada pengetahuan saya tentang git, jadi saya tidak bisa mengatakannya. Lagi pula, jika git log -- the_big_filemengembalikan apa pun kepada Anda, maka file tersebut masih dalam sejarah.
Shahbaz
@ Shahbaz yang mengembalikan apa-apa> <
Kevin W.
Mungkinkah Anda juga mendorong cabang lain di mana file itu ada? Juga, jika file tersebut masih ada di server, mengapa git pushdikatakan semuanya serba baru? Karena Anda mengubah riwayat, itu seharusnya mengeluh bahwa dorongan itu tidak mungkin dan Anda harus memaksanya.
Shahbaz

Jawaban:

446

Kamu bisa memakai

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file/dir>' HEAD

Ini akan menghapus semua yang ada di riwayat file itu. Masalahnya adalah bahwa file tersebut ada dalam riwayat.

Perintah ini mengubah hash dari commit Anda yang bisa menjadi masalah nyata, terutama pada repositori bersama. Seharusnya tidak dilakukan tanpa memahami konsekuensinya.

MacGyver
sumber
23
Bekerja untuk saya tetapi saya harus 'memaksanya': git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file / dir>' -f HEAD
alexoviedo999
30
Perintah ini mengubah hash dari commit Anda yang bisa menjadi masalah nyata, terutama pada repositori bersama. Seharusnya tidak dilakukan tanpa memahami konsekuensinya.
Chris
6
Apakah Anda seharusnya mengganti <file / dir> dengan nama file atau dir yang menyebabkan masalah?
David Rhoden
12
Perhatikan bahwa jika Anda ingin menerapkan perubahan ini ke SEMUA cabang, Anda harus menggunakan --allflag sebagai gantiHEAD
Nick Spreitzer
9
Saya mendapatkan:Rewrite 657560fa18c030bcfac9132ce1c3541e84a5bc2c (1/10) (0 seconds passed, remaining 0 predicted) /usr/lib/git-core/git-filter-branch: 1: eval: Syntax error: end of file unexpected
João Abrantes
68

Saya menemukan squashing lebih bermanfaat daripada filter-branch. Saya melakukan yang berikut:

  1. Hapus file besar secara lokal.
  2. Komit penghapusan lokal.
  3. Soft reset kembali sejumlah X komit (bagi saya itu adalah 3): git reset --soft HEAD~3 .
  4. Kemudian komit kembali semua perubahan bersama (squash AKA) git commit -m "New message for the combined commit"
  5. Dorong terjepit komit.

Kasing khusus (dari pengguna @lituo): Jika di atas tidak berfungsi, Anda mungkin memiliki kasing ini. Komit 1 termasuk file besar dan dorongan Komit 1 gagal karena kesalahan file besar. Commit 2 menghapus file besar dengangit rm --cached [file_name]tetapi dorongan Commit 2 masih gagal. Anda dapat mengikuti langkah-langkah yang sama di atas tetapi alih-alih menggunakanHEAD~3, gunakanHEAD~2.

Tapi aku bukan kelas pembungkus
sumber
2
Bekerja untuk saya, hanya harus menggabungkan kembali perubahan dari tiga komit kembali ke repositori lokal saya sebelum push squash bekerja.
dasWesen
5
Ini JAUH lebih baik daripada jawaban teratas. Jawaban teratas mengacaukan seluruh riwayat komit Anda.
manic.coder
Tidak memperbaiki masalah saya
Hirak Sarkar
3
Sejauh ini, inilah satu-satunya jawaban yang memperbaiki file besar yang tidak dikomit atau dikomit, tanpa sepenuhnya repositori! Terpilih sehingga dapat pindah ke atas :-)
Ælex
1
@tapi aku bukan kelas pembungkus: terima kasih banyak! ini bekerja seperti pesona :)
POOJA GUPTA
63

Ini adalah sesuatu yang saya temukan sangat membantu jika Anda sudah bermain-main dengan repo Anda sebelum Anda meminta bantuan. Tipe pertama:

git status

Setelah ini, Anda akan melihat sesuatu di sepanjang baris

On branch master
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

Bagian yang penting adalah "2 commit"! Dari sini, silakan dan ketik:

git reset HEAD~<HOWEVER MANY COMMITS YOU WERE BEHIND>

Jadi, untuk contoh di atas, orang akan mengetik:

git reset HEAD~2

Setelah Anda mengetik itu, "status git" Anda akan mengatakan:

On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Dari sana, Anda dapat menghapus file besar (dengan asumsi Anda belum melakukannya), dan Anda harus dapat mengkomit ulang semuanya tanpa kehilangan pekerjaan Anda.
Saya tahu ini bukan jawaban yang sangat mewah, tapi saya harap ini membantu!

Shreya
sumber
11
Pemenang. Sederhana, bersih, efektif, solusi yang dibangun git. Cinta menjawab seperti ini.
Reece Daniels
3
ini adalah solusi terbaik yang ada.
wrahool
40

Jika file ditambahkan dengan komit terbaru Anda , dan Anda belum mendorong ke repositori jarak jauh , Anda dapat menghapus file dan mengubah komit, Diambil dari sini :

git rm --cached giant_file
    # Stage "giant_file" for removal with "git rm"
    # Leave it on disk with "--cached". if you want to remove it from disk
    # then ignore the "--cached" parameter
git commit --amend -CHEAD
    # Commit the current tree without the giant file using "git commit"
    # Amend the previous commit with your change "--amend" 
    # (simply making a new commit won't work, as you need
    # to remove the file from the unpushed history as well)
    # Use the log/authorship/timestamp of the last commit (the one we are
    # amending) with "-CHEAD", equivalent to --reuse-message=HEAD
git push
    # Push our rewritten, smaller commit with "git push"
BlueMoon93
sumber
1
Solusi ini tidak akan berfungsi karena file tidak lagi ada di indeks git (hasilnya sebagai untrackeddaftar file di git status.
loretoparisi
Tidak ada yang terjadi Setelah menerapkan ini mengurangi jumlah total file tetapi setelah menunjukkan proses 99% macet lagi. Ada saran apa yang saya lewatkan?
CoDe
4
apa arti -CHEAD?
Aerin
1
Bagaimana jika saya ingin mencoba ini dari komit tertentu - bukan komit terakhir? Saya mencoba git rm --cached giant_file commit_idtetapi tidak berhasil :(
puifais
@puifais saya akan kembali ke komit sebelumnya, lakukan langkah-langkah ini, dan kemudian bergabung dengan yang sekarang. Saya tidak yakin apakah ini pendekatan terbaik, saya bukan ahli Git
BlueMoon93
13

Saya memiliki masalah serupa dan menggunakan langkah di atas untuk menghapus file. Itu bekerja dengan sempurna.

Saya kemudian mendapat kesalahan pada file kedua yang perlu saya hapus: remote: error: File <path/filename> is 109.99 MB; this exceeds GitHub's file size limit of 100.00 MB

Saya mencoba langkah yang sama, mendapat kesalahan: "A previous backup already exists in <path/filename>"

Dari penelitian di situs web ini saya menggunakan perintah:git filter-branch --force --index-filter "git rm --cached --ignore-unmatch <path/filename>" --prune-empty --tag-name-filter cat -- --all

Bekerja dengan baik, dan file-file besar dihapus.

Tidak bisa dipercaya, push masih gagal dengan kesalahan lain: error: RPC failed; curl 56 OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 104 fatal: The remote end hung up unexpectedly

Ini saya perbaiki dengan secara langsung memodifikasi file konfigurasi .git - postBuffer = 999999999

Setelah itu dorongan diteruskan!

Andre Odendaal
sumber
1
Gotcha tambahan yang harus saya hapus dengan menghapus file besar (seperti di atas) adalah bahwa salah satu folder memiliki karakter # hash di dalamnya. Ini tidak menimbulkan masalah sama sekali untuk operasi normal git namun untuk git rmsaya perlu memberikan nama path repositori lengkap untuk file dan untuk melarikan diri # dengan backslash untuk membuatnya bekerja
jacanterbury
ini bekerja untuk saya juga. Saya menghindari reset hardlangkah di bagian bawah halaman dengan dorongan sederhana. czettner.com/2015/07/16/...
Monte Hayward
Ini berhasil setelah juga menjalankan 'git push -f origin'
kezzos
12

Mengapa GitHub menolak repo saya, bahkan setelah saya menghapus file besar?

Git menyimpan riwayat lengkap proyek Anda, jadi walaupun Anda 'menghapus' file dari proyek Anda, repo Git masih memiliki salinan file dalam riwayatnya, dan jika Anda mencoba untuk mendorong ke repositori lain (seperti yang di-host di GitHub) kemudian Git membutuhkan repo jarak jauh memiliki riwayat yang sama dengan repo lokal Anda (yaitu file besar yang sama dalam riwayatnya).

Bagaimana saya bisa mendapatkan GitHub untuk menerima repo saya?

Anda perlu membersihkan riwayat Git proyek Anda secara lokal, menghapus file-file besar yang tidak diinginkan dari semua riwayat, dan kemudian hanya menggunakan riwayat 'dibersihkan' di masa mendatang. Id Git dari commit yang terpengaruh akan berubah.

Bagaimana cara membersihkan file besar dari repo Git saya?

Alat terbaik untuk membersihkan file besar yang tidak diinginkan dari sejarah Git adalah BFG Repo-Cleaner - ini adalah alternatif yang lebih sederhana dan lebih cepat untuk git-filter-branchsecara khusus dirancang untuk menghapus file yang tidak diinginkan dari sejarah Git.

Ikuti petunjuk penggunaan dengan hati-hati , bagian intinya adalah ini:

$ java -jar bfg.jar --strip-blobs-bigger-than 100M my-repo.git

File apa pun yang berukuran lebih dari 100MB (yang tidak ada dalam komit terbaru Anda ) akan dihapus dari riwayat repositori Git Anda. Anda kemudian dapat menggunakan git gcuntuk membersihkan data yang mati:

$ git gc --prune=now --aggressive

BFG biasanya setidaknya 10-50x lebih cepat daripada berjalan git-filter-branch, dan umumnya jauh lebih mudah digunakan.

Pengungkapan penuh: Saya penulis Repo-Cleaner BFG.

Roberto Tyley
sumber
1
Kasus saya memiliki komplikasi tambahan yang mencegah squashing. Alat BFG bekerja dengan sangat baik. Terima kasih.
dantopa
Ini adalah solusi yang fenomenal
SexualPotatoes
5

Saya telah mencoba semua metode di atas tetapi tidak satupun yang berhasil untuk saya.

Lalu saya datang dengan solusi saya sendiri.

  1. Pertama-tama, Anda memerlukan repo lokal yang bersih dan terkini. Hapus semua file besar.

  2. Sekarang buat folder baru DI LUAR folder repo Anda dan gunakan "Git buat repositori di sini" untuk menjadikannya repositori Git baru, sebut saja new_local_repo. Ini dia! Semua metode di atas mengatakan Anda harus membersihkan sejarah ..., yah, saya muak dengan itu, mari kita buat repo baru yang tidak memiliki sejarah sama sekali!

  3. Salin file dari repo lokal lama Anda ke repo baru yang cantik. Perhatikan bahwa logo hijau pada ikon folder akan hilang, ini menjanjikan karena ini adalah repo baru!

  4. Berkomitmen ke cabang lokal dan kemudian dorong ke cabang baru yang jauh. Sebut saja new_remote_branch. Jika Anda tidak tahu cara mendorong dari repo lokal baru, Google.

  5. Selamat! Anda telah mendorong kode Anda yang bersih dan terkini ke GitHub. Jika Anda tidak membutuhkan cabang master jarak jauh lagi, Anda dapat menjadikan new_remote_branch sebagai cabang master baru. Jika Anda tidak tahu cara melakukannya, Google.

  6. Langkah terakhir, saatnya untuk menghapus repo lokal lama yang kacau. Di masa depan Anda hanya menggunakan new_local_repo.

Shuaibin Chang
sumber
4

Saya mendapat masalah yang sama dan tidak ada jawaban yang cocok untuk saya. Saya dipecahkan dengan langkah-langkah berikut:

1. Temukan komit yang berisi file besar

git log --all -- 'large_file`

Komit bawah adalah komit tertua di daftar hasil.

2. Temukan yang tepat sebelum yang tertua.

git log

Misalkan Anda punya:

commit 3f7dd04a6e6dbdf1fff92df1f6344a06119d5d32

3. Dapatkan rebase

git rebase -i 3f7dd04a6e6dbdf1fff92df1f6344a06119d5d32

Kiat :

  1. Daftar barang
  2. Saya hanya memilih dropuntuk komit berisi file besar.
  3. Anda dapat menemukan konflik selama rebase memperbaikinya dan menggunakannya git rebase --continueuntuk melanjutkan sampai Anda menyelesaikannya.
  4. Jika terjadi kesalahan selama rebase gunakan git rebase --abortuntuk membatalkannya.
William Hu
sumber
1

Solusi untuk menyimpan file / folder besar di dalam folder yang berfungsi

Ini adalah baris yang berfungsi untuk menyelesaikan masalah yang ditanyakan di sini (dari jawaban 1):

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file/dir>' HEAD

Perintah ini juga menghapus file / dir jika file / dir berada di dalam pohon kerja.

Jika Anda ingin menyimpan file / folder di dalam pohon kerja saya mengusulkan mengambil langkah-langkah berikut.

  1. Setelah kesalahan itu berjalan git reset HEAD^
  2. Tambahkan file / folder yang dimaksud ke dalam file `` .gitignore```.

  3. Lanjutkan seperti biasa git add .yang mungkin menangkap file / folder lain tetapi harus menangkap .gitignorefile. Berikutnya git commit -m"message"dan akhirnyagit push origin <branch_name>

Kiprono Elijah Koech
sumber
0

ini berhasil untuk saya. dokumentasi dari github Squashing Git Commit git reset asal / master

git checkout master && git pull;
git merge feature_branch;
git add . --all;
git commit -m "your commit message"

temukan dokumentasi di sini

Njoroge Mathu
sumber
0

Jadi saya menghadapi situasi tertentu: Saya mengkloning repositori dari gitlab, yang berisi file lebih besar dari 100 mb, tetapi dihapus pada beberapa titik dalam sejarah git. Kemudian ketika saya menambahkan repo pribadi github baru dan mencoba mendorong ke repo baru, saya mendapatkan kesalahan 'file terlalu besar' yang terkenal. Pada titik ini, saya tidak lagi memiliki akses ke repo gitlab asli. Namun, saya masih bisa mendorong ke repo github pribadi baru menggunakan bfg-repo-cleanerpada repositori LOCAL di komputer saya:

$ cd ~
$ curl https://repo1.maven.org/maven2/com/madgag/bfg/1.13.0/bfg-1.13.0.jar > bfg.jar
$ cd my-project
$ git gc
$ cd ../
$ java -jar bfg.jar --strip-blobs-bigger-than 100M my-project
$ cd my-project
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
$ git remote -v # confirm origin is the remote you want to push to
$ git push origin master
Donato
sumber
0

Terkadang file disimpan dalam riwayat pelacakan, coba langkah-langkah berikut:

  1. git commit, Jika Anda melihat mode buat dengan file besar terdaftar, maka lakukan:
  2. git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch filename' HEAD. Anda akan melihat banyak Rewrite ditampilkan di konsol Anda yang berakhir dengan:

    rm 'nama file' dan

    baris terakhir Ref ditulis ulang.

Selesai.

Pohon DR
sumber
-1

Saya menambah jawaban pertama.

git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch' KEPALA

Akan ada beberapa konflik gabungan dari asal / master.

Cabang dan 'asal / master' Anda telah berbeda, dan masing-masing memiliki 114 dan 109 komit yang berbeda. (gunakan "git pull" untuk menggabungkan cabang jarak jauh ke cabang Anda)

Tolong jalankan ini

git reset --barang asli / master

Ini akan membuang semua perubahan saya yang dipentaskan dan tidak dipentaskan, lupakan semuanya pada cabang lokal saya saat ini dan membuatnya sama persis dengan asal / master.

RAHUL KUMAR
sumber