이미 삭제 한 큰 파일로 인해 GitHub에 푸시 할 수 없습니다


272

현재 나는

  1. 빈 GitHub 저장소
  2. SSH 서버 저장소 (기본)
  3. 지역 레포

SSH 서버 저장소는 최신 저장소 (생산 사이트)이므로 Git 복제본을 로컬에서 로컬로 수행했습니다. 그런 다음 git pushGitHub에 시도했습니다 .

모든 것이 괜찮 았지만 filename.gz에 대해 GitHub에 비해 너무 큽니다. 이 파일이 필요하지 않아 Git 캐시에서 제거하기 위해 여러 개의 Git 명령을 실행 한 다음 SSH 서버로 다시 푸시했습니다.

로컬에서 큰 파일을 볼 수는 없지만 git diff아무것도 반환하지 않고 git push가 "Everything is up-to-date"를 반환 하더라도 여전히 SSH 서버에 있습니다. GitHub 여전히 오류가 발생합니다

원격 : 오류 : 파일 fpss.tar.gz는 135.17MB입니다. 이것은 GitHub의 파일 크기 제한 인 100MB를 초과합니다.

GitHub 도움말에 나열된 "문제 해결"아래의 단계를 수행 했으므로 충분하지 않습니까?

파일이 로컬이 아니거나 git status / diff / push에 나열되어있을 때 어떻게 에테르에 남아 있습니까?


2
파일은 여전히 ​​히스토리에 있습니다. 파일을 추가하고 제거한 커밋을 스쿼시하여 기록을 삭제해야합니다.
Shahbaz

@Shahbaz 나는이 사이트에 나열된 "문제 해결"아래 단계를 수행했습니다 ... 충분하지 않습니까? help.github.com/articles/working-with-large-files
Kevin W.

거기에있는 명령은 git에 대한 지식보다 더 발전했기 때문에 실제로 말할 수는 없습니다. 어쨌든, git log -- the_big_file당신에게 무언가를 반환한다면, 파일은 여전히 ​​기록에 있습니다.
Shahbaz

아무것도 반환하지 않는 @Shahbaz> <
Kevin W.

파일이 존재하는 다른 브랜치를 밀어 넣었을 수 있습니까? 또한 파일이 여전히 서버에 있다면 왜 git push모든 것이 최신이라고 말합니까? 역사를 바 꾸었으므로 밀어 넣기가 불가능하고 강제해야한다고 불평해야했습니다.
Shahbaz

답변:


446

당신이 사용할 수있는

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

해당 파일 기록의 모든 내용이 삭제됩니다. 문제는 파일이 기록에 있다는 것입니다.

이 명령은 커밋의 해시를 변경하여 특히 공유 리포지토리에서 실제 문제가 될 수 있습니다. 결과를 이해하지 않고 수행해서는 안됩니다.


23
나를 위해 일했지만 '강제'해야했습니다 : git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch <file / dir>'
alexoviedo999

30
이 명령은 커밋의 해시를 변경하여 특히 공유 리포지토리에서 실제 문제가 될 수 있습니다. 결과를 이해하지 않고 수행해서는 안됩니다.
Chris

6
<file / dir>을 문제의 원인이되는 파일 또는 dir로 바꾸어야합니까?
David Rhoden

12
이러한 변경 사항을 모든 지점에 적용하려면 다음 --all대신 플래그 를 사용해야합니다.HEAD
Nick Spreitzer

9
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

쿼싱 이보다 유용하다는 것을 알았 습니다 filter-branch. 나는 다음을 수행했다.

  1. 큰 파일을 로컬에서 삭제하십시오.
  2. 로컬 삭제를 커밋합니다.
  3. 소프트 커밋 다시 X 커밋 수 (3의 경우) : git reset --soft HEAD~3.
  4. 그런 다음 모든 변경 사항을 다시 커밋하십시오 (AKA 스쿼시) git commit -m "New message for the combined commit"
  5. 스쿼시 커밋을 푸시하십시오.

특수한 경우 (사용자 @lituo) : 위의 방법으로 문제가 해결되지 않으면이 사례가있을 수 있습니다. 커밋 1에 큰 파일이 포함되었고 커밋 1의 푸시는 큰 파일 오류로 인해 실패했습니다. 커밋 2가 큰 파일을 제거git rm --cached [file_name]했지만 커밋 2의 푸시는 여전히 실패했습니다. 당신은 위의 대신 사용하여 동일한 단계를 수행 할 수 있습니다HEAD~3, 사용HEAD~2.


2
나를 위해 일한 것은 스쿼시 푸시가 작동하기 전에 세 가지 커밋의 변경 사항을 로컬 리포지토리로 다시 병합해야했습니다.
dasWesen

5
이것은 최고 답변보다 훨씬 낫습니다. 최고의 답변은 커밋 기록 전체를 망칩니다.
manic.coder

내 문제를 해결하지 못했습니다
히라 크 사르 카

3
이것은 저장소를 완전히 핵을 끄지 않고 커밋되지 않은 커밋되거나 커밋 된 파일을 수정하는 유일한 대답입니다! 상단으로 이동할 수 있도록 상향 조정 :-)
Ælex

1
@하지만 나는 래퍼 클래스가 아닙니다 : 정말 고마워요! 이것은 매력처럼 작동했습니다 :)
POOJA GUPTA

63

도움을 요청하기 전에 이미 리포지토리에 엉망이 되었으면 도움이 될만한 것이 있습니다. 첫 번째 유형 :

git status

이 후, 당신은 라인을 따라 뭔가를 볼 수 있습니다

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

중요한 부분은 "2 commits"입니다! 여기에서 다음을 입력하십시오.

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

따라서 위의 예에서 다음을 입력하십시오.

git reset HEAD~2

입력 한 후에 "git status"는 다음과 같아야합니다.

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

nothing to commit, working tree clean

여기에서 큰 파일을 삭제하고 (아직 수행하지 않은 경우) 작업 손실없이 모든 것을 다시 커밋 할 수 있어야합니다.
나는 이것이 멋진 답변이 아니라는 것을 알고 있지만 도움이되기를 바랍니다.


11
우승자. 간단하고 깨끗하며 효과적인 git 빌드 솔루션. 사랑은 이렇게 대답합니다.
Reece Daniels

3
이것이 가장 좋은 솔루션입니다.
wrahool

40

파일이 경우 가장 최근의 커밋을 당신과 함께 추가 , 당신은 원격 저장소에 밀어하지 않은 , 당신은 파일을 삭제하고이에서 촬영, 커밋 수정할 수 있습니다 여기에 :

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
이 솔루션은 파일이 더 이상 자식 인덱스에 없기 때문에 작동하지 않습니다 ( untracked파일 목록은 git status.
loretoparisi

아무것도 일어나지 않습니다. 이것을 적용한 후 총 파일 수를 줄 였지만 프로세스 99 %를 표시 한 후 다시 붙었습니다. 내가 잃어버린 제안이 있습니까?
CoDe

4
-CHEAD 무엇을 의미합니까?
Aerin

1
마지막 커밋이 아닌 특정 커밋 에서이 작업을 시도하려면 어떻게해야합니까? 나는 시도 git rm --cached giant_file commit_id했지만 작동하지 않았다 :(
puifais

@puifais 이전 커밋으로 되돌리고이 단계를 수행 한 다음 현재 커밋과 병합합니다. 이것이 최선의 접근 방법인지 확실하지 않습니다, 저는 Git 전문가가 아닙니다
BlueMoon93

13

비슷한 문제가 있었고 단계를 사용 하여 파일을 제거했습니다. 완벽하게 작동했습니다.

그런 다음 제거해야 할 두 번째 파일에 오류가 발생했습니다. remote: error: File <path/filename> is 109.99 MB; this exceeds GitHub's file size limit of 100.00 MB

같은 단계를 시도했지만 오류가 발생했습니다. "A previous backup already exists in <path/filename>"

이 웹 사이트 에서 조사한 결과 다음 명령을 사용했습니다.git filter-branch --force --index-filter "git rm --cached --ignore-unmatch <path/filename>" --prune-empty --tag-name-filter cat -- --all

훌륭하게 작동했으며 큰 파일이 제거되었습니다.

믿을 수 없을 정도로, 여전히 다른 오류로 인해 푸시에 실패했습니다. error: RPC failed; curl 56 OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 104 fatal: The remote end hung up unexpectedly

이것은 .git 설정 파일을 직접 수정하여 수정했습니다. postBuffer = 999999999

그 후 푸시는 통과했다!


1
위와 같이 큰 파일을 제거하는 데 어려움을 겪었던 추가 폴더는 폴더 중 하나에 해시 # 문자가 있다는 것입니다. 이것은 일반적인 git 작업에 전혀 문제를 일으키지 않았지만 git rm파일의 전체 저장소 경로 이름을 제공하고 #를 백 슬래시로 이스케이프 처리하여 작동
시켜야

이것도 저에게 효과적이었습니다. reset hard간단한 푸시로 페이지 하단의 단계를 피했습니다 . czettner.com/2015/07/16/…
Monte Hayward

이 후도 '-f 출처를 밀어 자식'실행 일
kezzos

12

큰 파일을 삭제 한 후에도 GitHub가 내 저장소를 거부하는 이유는 무엇입니까?

Git은 프로젝트의 전체 히스토리를 저장하므로 프로젝트에서 파일을 '삭제'하더라도 Git 저장소에는 여전히 히스토리에 파일 사본이 있으며 다른 저장소 (예 : GitHub) 다음 Git 에는 원격 저장소에 로컬 저장소와 동일한 기록이 있어야합니다 (즉, 기록에있는 동일한 큰 파일).

GitHub가 레포를 수락하도록하려면 어떻게해야합니까?

프로젝트의 Git 히스토리를 로컬로 정리하고 모든 히스토리에서 원하지 않는 큰 파일을 제거한 다음 앞으로 '세척 된'히스토리 만 사용하십시오. 영향을받는 커밋의 Git 커밋 ID가 변경됩니다.

Git 저장소에서 큰 파일을 어떻게 정리합니까?

Git 히스토리에서 원하지 않는 큰 파일을 정리하는 가장 좋은 도구는 BFG Repo-Cleanergit-filter-branch 입니다. Git 히스토리에서 원하지 않는 파일을 제거하기 위해 특별히 설계된 것보다 간단하고 빠른 대안 입니다.

사용 지침을주의 깊게 따르십시오. 핵심 부분은 다음과 같습니다.

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

100MB 이상의 파일 ( 최근 커밋에 없는 파일 )은 Git 리포지토리 기록에서 제거됩니다. 그런 다음 git gc죽은 데이터를 정리 하는 데 사용할 수 있습니다 .

$ git gc --prune=now --aggressive

BFG는 일반적으로 적어도이다 10-50x 빠르게 실행하는 것보다 git-filter-branch, 사용이 일반적으로 더 쉽게.

전체 공개 : 저는 BFG Repo-Cleaner의 저자입니다.


1
내 사건에는 스쿼시를 배제하는 추가 합병증이있었습니다. BFG 도구는 훌륭하게 작동했습니다. 감사.
dantopa

이것은 놀라운 해결책입니다
SexualPotatoes

4

나는 같은 문제를 겪었고 아무런 대답도 나에게 도움이되지 않았다. 다음 단계로 해결했습니다.

1. 큰 파일을 포함하는 커밋을 찾습니다

git log --all -- 'large_file`

맨 아래 커밋은 결과 목록에서 가장 오래된 커밋입니다.

2. 가장 오래된 것 중 하나를 찾으십시오.

git log

당신이 가지고 있다고 가정 해보십시오 :

commit 3f7dd04a6e6dbdf1fff92df1f6344a06119d5d32

3. 힘내 rebase

git rebase -i 3f7dd04a6e6dbdf1fff92df1f6344a06119d5d32

:

  1. 목록 항목
  2. drop커밋에 큰 파일이 포함되도록 선택 합니다.
  3. 리베이스 수정 중에 충돌이 발생 git rebase --continue하여 완료 할 때까지 계속 사용할 수 있습니다.
  4. 리베이스 중에 문제가 발생하면이 git rebase --abort를 취소하십시오.

4

위의 모든 방법을 시도했지만 그중 아무것도 나를 위해 작동하지 않습니다.

그런 다음 내 솔루션을 생각해 냈습니다.

  1. 우선, 깨끗하고 최신의 로컬 리포지토리가 필요합니다. 빌어 먹을 큰 파일을 모두 삭제하십시오.

  2. 이제 repo 폴더 외부에 새 폴더를 만들고 "Git create repository here"를 사용하여 새 Git 저장소로 만듭니다.이를 new_local_repo라고합니다. 이거 야! 위의 모든 방법은 당신이 역사를 청소해야한다고 말했습니다 ... 음, 나는 아파요. 역사가 전혀없는 새로운 저장소를 만들어 봅시다!

  3. 낡은 오래된 지역 저장소에서 새롭고 아름다운 저장소로 파일을 복사하십시오. 폴더 아이콘의 녹색 로고가 사라집니다. 이것은 새로운 저장소이므로 유망합니다!

  4. 로컬 지점에 커밋 한 다음 원격 새 지점으로 푸시합니다. 이것을 new_remote_branch라고하겠습니다. 새로운 로컬 리포지토리에서 푸시하는 방법을 모르는 경우 Google에 문의하십시오.

  5. 축하합니다! 깨끗한 최신 코드를 GitHub에 푸시했습니다. 더 이상 원격 마스터 분기가 필요하지 않은 경우 new_remote_branch를 새 마스터 분기로 만들 수 있습니다. 어떻게해야할지 모른다면 Google에 알려주세요.

  6. 마지막 단계는 낡은 지역 저장소를 삭제할 차례입니다. 앞으로는 new_local_repo 만 사용합니다.



1

큰 파일 / 폴더를 작업 폴더 내에 유지하는 솔루션

이것은 (1 답변에서) 여기에 질문 된 문제를 해결하기 위해 노력한 라인입니다.

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

파일 / 디렉토리가 작업 트리 내에 있으면이 명령은 파일 / 디렉토리도 삭제합니다.

작업 트리 내에 파일 / 폴더를 유지하려면 다음 단계를 수행하십시오.

  1. 그 오류 후 git reset HEAD^
  2. 해당 파일 / 폴더를``.gitignore ''파일에 추가하십시오.

  3. git add .다른 파일 / 폴더를 캡처 할 수 있지만 .gitignore파일을 캡처해야하는 평소대로 진행 하십시오. 다음은 git commit -m"message"마지막입니다git push origin <branch_name>


0

이것은 나를 위해 일했습니다. github의 설명서 Squashing Git 커밋 git reset origin / master

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

여기에서 설명서를 찾으 십시오


0

첫 번째 답변에 추가하고 있습니다.

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

원산지 / 마스터와 일부 병합 충돌이 발생합니다.

브랜치와 'origin / master'는 분기되었으며 각각 114와 109 개의 서로 다른 커밋이 있습니다. ( "git pull"을 사용하여 원격 브랜치를 병합하십시오)

이것을 실행하십시오

git reset-하드 오리진 / 마스터

그것은 모든 단계적 및 비 단계적 변화를 버리고 현재 지역 지점의 모든 것을 잊어 버리고 출발지 / 마스터와 정확히 동일하게 만듭니다.


0

그래서 나는 특별한 상황에 직면했습니다 : 100MB보다 큰 파일을 포함하지만 git history의 어느 시점에서 제거 된 gitlab에서 저장소를 복제했습니다. 그런 다음 나중에 새로운 github 개인 저장소를 추가하고 새 저장소로 푸시하려고 할 때 악명 높은 '파일이 너무 큽니다'오류가 발생했습니다. 이 시점에서 더 이상 원래 gitlab 저장소에 액세스 할 수 없었습니다. 그러나 여전히 bfg-repo-cleaner내 컴퓨터의 LOCAL 저장소에서 새로운 개인 github 저장소로 푸시 할 수있었습니다 .

$ 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

때때로 파일이 추적 기록에 유지되는 경우 다음 단계를 시도하십시오.

  1. git commit, 큰 파일이 나열된 작성 모드 가 표시되면 다음을 수행하십시오.
  2. git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch filename' HEAD. 콘솔에 다음과 같이 끝나는 많은 Rewrite가 표시됩니다.

    rm 'filename'및

    마지막 줄 Ref 가 다시 작성되었습니다.

끝났다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.