Không thể chuyển sang GitHub vì tệp lớn mà tôi đã xóa


272

Hiện tại tôi có

  1. Repo GitHub trống
  2. Repo máy chủ SSH (chính)
  3. Repo địa phương

Repo máy chủ SSH là repo cập nhật nhất (trang sản xuất) vì vậy tôi đã tạo một bản sao Git từ đó đến địa phương. Sau đó tôi đã cố gắng làm một git pushGitHub.

Mọi thứ đều ổn nhưng sau đó nó nói điều gì đó về filename.gz quá lớn đối với GitHub. Tôi không cần tệp này vì vậy tôi đã chạy một số lệnh Git để loại bỏ nó khỏi bộ đệm Git sau đó được đẩy trở lại máy chủ SSH.

Tôi không thấy tệp lớn cục bộ nhưng nó vẫn ở trên máy chủ SSH mặc dù git diffkhông trả về gì và git đẩy trả về "Mọi thứ đều cập nhật" - Và mặc dù tệp không hiển thị trong repo cục bộ khi tôi cố gắng đẩy tới GitHub tôi vẫn nhận được lỗi về nó

từ xa: lỗi: Tệp fpss.tar.gz là 135,17 MB; vượt quá giới hạn kích thước tệp của GitHub là 100 MB

Tôi đã làm theo các bước trong phần "khắc phục sự cố" được liệt kê trên trợ giúp của GitHub để điều đó không đủ?

Làm thế nào là tập tin vẫn còn trong ether khi nó không cục bộ hoặc được liệt kê trong trạng thái git / diff / đẩy?


2
Các tập tin vẫn còn đó trong lịch sử. Bạn cần phải hủy lịch sử, có thể bằng cách xóa các xác nhận đã thêm và xóa tệp.
Shahbaz

@Shahbaz Tôi đã làm theo các bước trong phần "khắc phục sự cố" được liệt kê trên trang web này ... điều đó có đủ không? help.github.com/articles/usiness-with-large-files
Kevin W.

Lệnh ở đó nâng cao hơn kiến ​​thức về git của tôi, vì vậy tôi thực sự không thể biết được. Dù sao, nếu git log -- the_big_filetrả lại cho bạn bất cứ điều gì, thì tập tin vẫn còn trong lịch sử.
Shahbaz

@Shahbaz trả lại thông báo> <
Kevin W.

Có thể là bạn cũng đang đẩy các nhánh khác nơi tệp tồn tại? Ngoài ra, nếu tệp vẫn còn trên máy chủ, tại sao git pushmọi thứ sẽ được cập nhật? Vì bạn đã thay đổi lịch sử, nên đã phàn nàn rằng việc đẩy là không thể và bạn sẽ phải ép buộc.
Shahbaz

Câu trả lời:


446

Bạn có thể dùng

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

Điều này sẽ xóa mọi thứ trong lịch sử của tập tin đó. Vấn đề là tập tin có mặt trong lịch sử.

Lệnh này thay đổi giá trị băm của các cam kết của bạn có thể là một vấn đề thực sự, đặc biệt là trên các kho lưu trữ được chia sẻ. Nó không nên được thực hiện mà không hiểu hậu quả.


23
Làm việc cho tôi nhưng tôi phải 'ép buộc' nó: git filter-Branch --index-filter 'git rm -r --cached --ignore-unmatch <file / dir>' -f Head
alexoviedo999

30
Lệnh này thay đổi giá trị băm của các cam kết của bạn có thể là một vấn đề thực sự, đặc biệt là trên các kho lưu trữ được chia sẻ. Nó không nên được thực hiện mà không hiểu hậu quả.
Chris

6
Bạn có phải thay thế <file / dir> bằng tên của tệp hoặc thư mục gây ra sự cố không?
David Rhoden

12
Lưu ý rằng nếu bạn muốn áp dụng những thay đổi này cho TẤT CẢ các chi nhánh, bạn cần sử dụng --allcờ thay vìHEAD
Nick Spreitzer

9
Tôi đang nhận được: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

Tôi thấy squashing hữu ích hơn filter-branch. Tôi đã làm như sau:

  1. Xóa cục bộ các tệp lớn.
  2. Cam kết xóa địa phương.
  3. Đặt lại mềm X số lần xác nhận (đối với tôi là 3) : git reset --soft HEAD~3.
  4. Sau đó đề xuất tất cả các thay đổi cùng nhau (AKA squash) git commit -m "New message for the combined commit"
  5. Đẩy cam kết.

Trường hợp đặc biệt (từ người dùng @lituo): Nếu ở trên không hoạt động, thì bạn có thể gặp trường hợp này. Cam kết 1 bao gồm tệp lớn và lần đẩy của Cam kết 1 không thành công do lỗi tệp lớn. Cam kết 2 đã xóa tệp lớn bằng cách đẩygit rm --cached [file_name]nhưng Cam kết 2 vẫn thất bại. Bạn có thể làm theo các bước tương tự ở trên nhưng thay vì sử dụngHEAD~3, hãy sử dụngHEAD~2.


2
Làm việc cho tôi, chỉ cần hợp nhất lại các thay đổi từ ba cam kết trở lại vào kho lưu trữ cục bộ của tôi trước khi đẩy bí đao hoạt động.
dasWesen

5
Điều này là tốt hơn so với câu trả lời hàng đầu. Các câu trả lời hàng đầu vít lên toàn bộ lịch sử cam kết của bạn.
manic.coder

Không khắc phục được sự cố của tôi
Hirak Sarkar

3
Đây là câu trả lời duy nhất sửa chữa các tệp lớn không được cam kết hoặc cam kết, mà không hoàn toàn ngăn chặn kho lưu trữ! Được nâng cấp để nó có thể di chuyển lên đầu :-)
Ælex

1
@ nhưng tôi không phải là một lớp bao bọc: cảm ơn bạn rất nhiều! điều này hoạt động như bùa mê :)
POOJA GUPTA

63

Đây là một cái gì đó tôi thấy rất hữu ích nếu bạn đã loay hoay với repo của mình trước khi bạn yêu cầu giúp đỡ. Loại thứ nhất:

git status

Sau này, bạn sẽ thấy một cái gì đó dọc theo dòng

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

Phần quan trọng là "2 cam kết"! Từ đây, tiếp tục và nhập:

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

Vì vậy, với ví dụ trên, người ta sẽ gõ:

git reset HEAD~2

Sau khi bạn gõ nó, "trạng thái git" của bạn sẽ hiện:

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

nothing to commit, working tree clean

Từ đó, bạn có thể xóa tệp lớn (giả sử bạn chưa làm như vậy) và bạn sẽ có thể cam kết lại mọi thứ mà không mất công.
Tôi biết đây không phải là một câu trả lời siêu ưa thích, nhưng tôi hy vọng nó có ích!


11
Người chiến thắng. Đơn giản, sạch sẽ, hiệu quả, git xây dựng giải pháp. Tình yêu trả lời như thế này.
Reece Daniels

3
đây là giải pháp tốt nhất
thúc

40

Nếu tệp được thêm vào với cam kết gần đây nhất của bạn và bạn chưa bị đẩy vào kho lưu trữ từ xa , bạn có thể xóa tệp và sửa đổi cam kết, Lấy từ đây :

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"

1
Giải pháp này sẽ không hoạt động vì tệp không còn trong chỉ mục git (kết quả là untrackeddanh sách tệp tại git status.
loretoparisi

Không có gì xảy ra. Sau khi áp dụng điều này, nó đã giảm tổng số tập tin nhưng sau khi hiển thị quá trình 99% thì nó lại bị kẹt. Bất cứ đề nghị những gì tôi đang thiếu?
CoDe

4
-CHEAD có nghĩa là gì?
Aerin

1
Điều gì xảy ra nếu tôi muốn thử điều này từ một cam kết cụ thể - không phải là cam kết cuối cùng? Tôi đã thử git rm --cached giant_file commit_idnhưng nó không hoạt động :(
puifais 27/12/18

@puifais Tôi sẽ trở lại cam kết trước đó, thực hiện các bước này và sau đó hợp nhất với cam kết hiện tại. Tôi không chắc đây có phải là cách tiếp cận tốt nhất không, tôi không phải là chuyên gia về Git
BlueMoon93

13

Tôi đã có một vấn đề tương tự và sử dụng bước trên để loại bỏ các tập tin. Nó hoạt động hoàn hảo.

Sau đó tôi đã gặp lỗi trên tệp thứ hai mà tôi cần xóa: remote: error: File <path/filename> is 109.99 MB; this exceeds GitHub's file size limit of 100.00 MB

Tôi đã thử bước tương tự, gặp lỗi: "A previous backup already exists in <path/filename>"

Từ nghiên cứu trên trang web này, tôi đã sử dụng lệnh:git filter-branch --force --index-filter "git rm --cached --ignore-unmatch <path/filename>" --prune-empty --tag-name-filter cat -- --all

Làm việc tuyệt vời, và các tập tin lớn đã được gỡ bỏ.

Không thể tin được, việc đẩy vẫn thất bại với một lỗi khác: error: RPC failed; curl 56 OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 104 fatal: The remote end hung up unexpectedly

Điều này tôi đã sửa bằng cách sửa đổi trực tiếp tệp cấu hình .git - postBuffer = 999999999

Sau đó, sự thúc đẩy đã đi qua!


1
một vấn đề bổ sung mà tôi phải đối mặt với việc xóa một tệp lớn (như trên) là một trong các thư mục có ký tự băm # trong đó. Điều này không gây ra vấn đề gì cho hoạt động git bình thường, tuy nhiên git rmtôi cần phải cung cấp tên đường dẫn kho lưu trữ đầy đủ cho tệp và thoát # bằng dấu gạch chéo ngược để làm cho nó hoạt động
jacanterbury

điều này cũng làm việc cho tôi Tôi tránh reset hardbước ở cuối trang chỉ bằng một cú đẩy đơn giản. czettner.com/2015/07/16/
Monte Hayward

Điều này hoạt động sau khi cũng chạy 'git push -f origin'
kezzos

12

Tại sao GitHub từ chối repo của tôi, ngay cả sau khi tôi xóa tệp lớn?

Git lưu trữ toàn bộ lịch sử dự án của bạn, vì vậy ngay cả khi bạn 'xóa' một tệp khỏi dự án của mình, repo Git vẫn có một bản sao của tệp trong lịch sử của nó và nếu bạn cố gắng đẩy sang kho lưu trữ khác (như một lưu trữ tại GitHub) sau đó Git yêu cầu repo từ xa có cùng lịch sử với repo cục bộ của bạn (nghĩa là các tệp lớn tương tự trong lịch sử của nó).

Làm cách nào tôi có thể khiến GitHub chấp nhận repo của mình?

Bạn cần xóa lịch sử Git của dự án của mình cục bộ, xóa các tệp lớn không mong muốn khỏi tất cả lịch sử và sau đó chỉ sử dụng lịch sử 'được làm sạch' trong tương lai. Id id Git của các xác nhận bị ảnh hưởng sẽ thay đổi.

Làm cách nào để xóa các tệp lớn khỏi repo Git của tôi?

Công cụ tốt nhất để dọn dẹp các tệp lớn không mong muốn trong lịch sử Git là BFG Repo-Cleaner - đây là công cụ thay thế đơn giản hơn, nhanh hơn đểgit-filter-branch thiết kế đặc biệt để xóa các tệp không mong muốn khỏi lịch sử Git.

Làm cẩn thận theo các hướng dẫn sử dụng , phần cốt lõi chỉ là thế này:

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

Bất kỳ tệp nào có kích thước trên 100 MB (không có trong cam kết mới nhất ) sẽ bị xóa khỏi lịch sử kho lưu trữ Git của bạn. Sau đó, bạn có thể sử dụng git gcđể dọn sạch dữ liệu chết:

$ git gc --prune=now --aggressive

BFG thường nhanh hơn ít nhất 10-50 lần so với khi chạygit-filter-branch và thường dễ sử dụng hơn rất nhiều.

Tiết lộ đầy đủ: Tôi là tác giả của BFG Repo-Cleaner.


1
Trường hợp của tôi đã có thêm các biến chứng mà loại trừ bẹp. Công cụ BFG hoạt động rất tốt. Cảm ơn.
dantopa

Đây là một giải pháp phi thường
SexualPotatoes

5

Tôi đã thử tất cả các phương pháp trên nhưng không có phương pháp nào phù hợp với tôi.

Sau đó, tôi đã đưa ra giải pháp của riêng tôi.

  1. Trước hết, bạn cần một repo địa phương sạch sẽ, cập nhật. Xóa tất cả các tập tin lớn chết tiệt.

  2. Bây giờ hãy tạo thư mục mới NGOÀI TRỜI thư mục repo của bạn và sử dụng "Git tạo kho lưu trữ tại đây" để biến nó thành kho lưu trữ Git mới, hãy gọi nó là new_local_Vpo. Đây là nó! Tất cả các phương pháp trên đều nói rằng bạn phải xóa lịch sử ..., ừm, tôi phát ốm vì điều đó, hãy tạo một repo mới không có lịch sử nào cả!

  3. Sao chép các tập tin từ cũ của bạn, làm hỏng repo cục bộ sang repo mới, đẹp. Lưu ý rằng logo màu xanh lá cây trên biểu tượng thư mục sẽ biến mất, điều này đầy hứa hẹn vì đây là một repo mới!

  4. Cam kết với chi nhánh địa phương và sau đó đẩy đến chi nhánh mới từ xa. Hãy gọi nó là new_remote_branch. Nếu bạn không biết cách đẩy từ một repo địa phương mới, hãy Google nó.

  5. Chúc mừng! Bạn đã đẩy mã sạch, cập nhật của mình lên GitHub. Nếu bạn không cần nhánh chủ từ xa nữa, bạn có thể đặt new_remote_branch của mình làm nhánh chính mới. Nếu bạn không biết cách thực hiện, hãy Google nó.

  6. Bước cuối cùng, đã đến lúc xóa đi repo cũ. Trong tương lai, bạn chỉ sử dụng new_local_Vpo.


4

Tôi có cùng một vấn đề và không có câu trả lời nào phù hợp với tôi. Tôi đã giải quyết bằng các bước sau:

1. Tìm (các) cam kết chứa tệp lớn

git log --all -- 'large_file`

Cam kết dưới cùng là cam kết cũ nhất trong danh sách kết quả.

2. Tìm một cái ngay trước khi cũ nhất.

git log

Giả sử bạn có:

commit 3f7dd04a6e6dbdf1fff92df1f6344a06119d5d32

3. Cuộc nổi loạn của Git

git rebase -i 3f7dd04a6e6dbdf1fff92df1f6344a06119d5d32

Mẹo :

  1. Danh sách mục
  2. Tôi chỉ chọn dropcho các cam kết chứa các tệp lớn.
  3. Bạn có thể gặp xung đột trong khi rebase sửa chúng và sử dụng git rebase --continueđể tiếp tục cho đến khi bạn hoàn thành nó.
  4. Nếu bất cứ điều gì sai trong quá trình rebase sử dụng git rebase --abortđể hủy bỏ nó.


1

Giải pháp giữ các tệp / thư mục lớn trong thư mục làm việc

Đây là dòng làm việc để giải quyết vấn đề được hỏi ở đây (từ câu trả lời 1):

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

Lệnh này cũng xóa tệp / dir nếu tệp / dir nằm trong cây làm việc.

Nếu bạn muốn giữ tệp / thư mục trong cây làm việc, tôi đề xuất thực hiện các bước sau.

  1. Sau lỗi đó chạy git reset HEAD^
  2. Thêm tệp / thư mục được đề cập vào tệp `` .gitignore```.

  3. Tiếp tục như bình thường git add .có thể chụp các tệp / thư mục khác nhưng phải chụp .gitignoretệp. Tiếp theo là git commit -m"message"và cuối cùnggit push origin <branch_name>


0

Điều này làm việc cho tôi. tài liệu từ github Squashing Git Cam kết git reset origin / master

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

tìm tài liệu ở đây


0

Tôi đang thêm vào câu trả lời đầu tiên.

git lọc-nhánh --index-filter 'git rm -r --cached --ignore-unmatch' Head

Sẽ có một số xung đột hợp nhất từ ​​nguồn gốc / chủ.

Chi nhánh của bạn và 'origin / master' đã chuyển hướng và có lần lượt 114 và 109 cam kết khác nhau. (sử dụng "git pull" để hợp nhất nhánh từ xa vào của bạn)

Làm ơn chạy cái này

thiết lập lại git - nguồn gốc / chủ

Nó sẽ vứt bỏ tất cả những thay đổi được dàn dựng và không theo giai đoạn của tôi, quên mọi thứ trên chi nhánh địa phương hiện tại của tôi và làm cho nó giống hệt như bản gốc / bản gốc.


0

Vì vậy, tôi đã gặp một tình huống cụ thể: Tôi đã sao chép một kho lưu trữ từ gitlab, chứa một tệp lớn hơn 100 mb, nhưng đã bị xóa tại một số điểm trong lịch sử git. Sau đó, khi tôi thêm một repo riêng github mới và cố gắng đẩy sang repo mới, tôi đã gặp phải lỗi 'file quá lớn'. Đến thời điểm này, tôi không còn có quyền truy cập vào repo gitlab ban đầu. Tuy nhiên, tôi vẫn có thể chuyển sang repo github riêng tư mới bằng cách sử dụng bfg-repo-cleanertrên kho lưu trữ ĐỊA PHƯƠNG trên máy của mình:

$ 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

0

Đôi khi tệp được giữ trong lịch sử theo dõi, hãy thử các bước sau:

  1. git commit, Nếu bạn đang thấy chế độ tạo với tệp lớn được liệt kê, thì hãy làm:
  2. git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch filename' HEAD. Bạn sẽ thấy một loạt các phần thưởng được hiển thị trong bảng điều khiển của bạn kết thúc bằng:

    rm 'tên tệp' và

    dòng cuối cùng Ref đã được viết lại.

Xong rôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.