programing

깃 저장소에서 이전 기록을 제거하려면 어떻게 해야 합니까?

bestprogram 2023. 5. 7. 12:04

깃 저장소에서 이전 기록을 제거하려면 어떻게 해야 합니까?

유감스럽게도 이 시나리오와 비슷한 것을 찾을 수 없었습니다.

저는 2007년 중반으로 거슬러 올라가는 500개 이상의 지점, 500개 이상의 태그와 같은 많은 역사를 가진 Git 저장소를 가지고 있습니다.여기에는 최대 19,500개의 커밋이 포함됩니다.2010년 1월 1일 이전의 모든 기록을 삭제하여 더 작고 쉽게 처리하고자 합니다(기록의 전체 복사본을 아카이브 저장소에 보관).

새 저장소의 루트가 되고 싶은 커밋을 알고 있습니다.하지만 저는 그 커밋으로 시작할 레포를 자를 정확한 git mojo를 찾을 수 없습니다.제 생각엔 다른 종류의

git filter-branch

이식을 포함하는 것이 필요할 것입니다. 또한 우리가 유지하고자 하는 200개 이상의 가지를 각각 개별적으로 처리한 다음 레포를 다시 패치하는 것이 필요할 수도 있습니다(가 할 수 있는 방법을 알고 있습니다).

이런 일을 해본 사람이 있습니까?그게 중요하다면 1.7.2.3을 가지고 있습니다.

Git repo에서 공간을 확보하고 싶지만 모든 커밋(기본 또는 이식편)을 재구성하지 않고 전체 repo를 가진 사용자로부터 밀어넣기/풀/합병할 수 있는 경우 Git clone 얕은 클론(--depth 매개 변수)을 사용할 수 있습니다.

; Clone the original repo into limitedRepo
git clone file:///path_to/originalRepo limitedRepo --depth=10

; Remove the original repo, to free up some space
rm -rf originalRepo
cd limitedRepo
git remote rm origin

다음 단계를 수행하면 기존 레포를 얕볼 수 있습니다.

; Shallow to last 5 commits
git rev-parse HEAD~5 > .git/shallow

; Manually remove all other branches, tags and remotes that refers to old commits

; Prune unreachable objects
git fsck --unreachable ; Will show you the list of what will be deleted
git gc --prune=now     ; Will actually delete your data

모든 git 로컬 태그를 제거하는 방법은 무엇입니까?

Ps: 이전 버전의 git는 얕은 저장소에서 복제/푸시/풀을 지원하지 않았습니다.

참고: 이는 다음을 위해 더 이상 사용되지 않습니다.git replace.

새 루트 커밋의 부모 그래프를 부모가 아닌 빈 커밋(예: 저장소의 실제 루트 커밋)에 만들 수 있습니다.예.echo "<NEW-ROOT-SHA1>" > .git/info/grafts

이식편을 만든 후에, 그것은 즉시 효력이 발생합니다; 당신은 그것을 볼 수 있어야 합니다.git log원치 않는 오래된 커밋이 사라졌는지 확인합니다.

$ echo 4a46bc886318679d8b15e05aea40b83ff6c3bd47 > .git/info/grafts
$ git log --decorate | tail --lines=11
commit cb3da2d4d8c3378919844b29e815bfd5fdc0210c
Author: Your Name <your.email@example.com>
Date:   Fri May 24 14:04:10 2013 +0200

    Another message
 
commit 4a46bc886318679d8b15e05aea40b83ff6c3bd47 (grafted)
Author: Your Name <your.email@example.com>
Date:   Thu May 23 22:27:48 2013 +0200

    Some message

대로 보인다면, 은 모든것의보경우이는은,당신럼을 사용할 수 .git filter-branch -- --all영구적으로 만들기 위해.

주의: 필터 분기 단계를 수행한 후에는 모든 커밋 ID가 변경되므로 이전 레포를 사용하는 사람은 새 레포를 사용하는 사람과 병합해서는 안 됩니다.

방법은 이해하기 쉽고 잘 작동합니다.스크립트에 대한 인수($1는입니다.는 기록을 유지할 커밋을 시작하는 참조(태그, 해시, ...)입니다.

#!/bin/bash
git checkout --orphan temp $1 # create a new branch without parent history
git commit -m "Truncated history" # create a first commit on this branch
git rebase --onto temp $1 master # now rebase the part of master branch that we want to keep onto this branch
git branch -D temp # delete the temp branch

# The following 2 commands are optional - they keep your git repo in good shape.
git prune --progress # delete all the objects w/o references
git gc --aggressive # aggressively collect garbage; may take a lot of time on large repos

이전 태그는 여전히 남아 있으므로 수동으로 제거해야 할 수도 있습니다.

비고: 이것이 @yoyodin과 거의 같다는 것을 알지만, 여기에 몇 가지 중요한 추가 명령과 정보가 있습니다.저는 답변을 편집하려고 했지만, @yoyodin의 답변에 상당한 변화가 있기 때문에, 제 편집이 거부되어, 정보를 알려드립니다!

방법을 사용해 보십시오. Git 내역을 잘라내는 방법:

#!/bin/bash
git checkout --orphan temp $1
git commit -m "Truncated history"
git rebase --onto temp $1 master
git branch -D temp

여기서$1는 "" "SHA-1" 사이의 하는 새 합니다.$1그리고.master그리고 모든 오래된 역사는 삭제됩니다.가 이간한스호는기출가없다라는 가정합니다.temp또한 이 스크립트는 이전 기록에 대한 Git 데이터를 지우지 않습니다.려달을 합니다.git gc --prune=all && git repack -a -f -F -d당신이 진정으로 모든 역사를 잃고 싶어한다는 것을 확인한 후에.또한 필요할 수도 있습니다.rebase --preserve-merges하지만 그 기능의 Git 구현이 완벽하지 않다는 것을 경고합니다.사용할 경우 수동으로 결과를 검사합니다.

역사를 다시 쓰는 대신 Pro Git 의 이 기사에서와 같이 사용하는 것을 고려해 보십시오.위에서 설명한 예에서는 트리의 시작을 시뮬레이션하기 위해 상위 커밋을 교체하는 동시에 전체 기록을 안전한 보관을 위한 별도의 분기로 유지하는 것을 포함합니다.

전체 기록은 있지만 로컬 체크아웃은 더 작은 업스트림 저장소를 유지하려면 다음을 사용하여 얕은 복제를 수행합니다.git clone --depth=1 [repo].

커밋을 푸시한 후에는 다음 작업을 수행할 수 있습니다.

  1. git fetch --depth=1오래된 약속들을 정리하는 것.이렇게 하면 이전 커밋과 해당 개체에 연결할 수 없습니다.
  2. git reflog expire --expire-unreachable=now --all모든 이전 커밋과 해당 개체를 만료하려면 다음과 같이 하십시오.
  3. git gc --aggressive --prune=all.

자세한 내용은 커밋 후 로컬 깃 기록을 제거하는 방법을 참조하십시오.

이 "허황된" 리포지토리를 "허황된 업데이트가 허용되지 않음" 다른 위치로 밀어넣을 수 없습니다.Git 원격 URL을 변경한 후 원격 거부(허름한 업데이트는 허용되지 않음)를 참조하십시오. 그러려면 접붙이기 작업을 계속해야 합니다.

저는 제가 무엇을 하고 있는지 이해하기 위해 몇 가지 답변과 다른 정보를 읽어야 했습니다.

특정 커밋보다 오래된 모든 항목 무시

».git/info/grafts커밋에 대해 가짜 부모를 정의할 수 있습니다.커밋 ID만 있는 행은 커밋에 부모가 없음을 나타냅니다.지난 2000개의 커밋에만 관심이 있다고 말하고 싶다면 다음을 입력할 수 있습니다.

git rev-parse HEAD~2000 > .git/info/grafts

git rev-message는 현재 커밋의 2000번째 부모의 커밋 ID를 제공합니다.위 명령은 그래프 파일이 있는 경우 해당 파일을 덮어씁니다.거기 있는지 먼저 확인해 보세요.

Git 기록 다시 쓰기(선택 사항)

이식된 가짜 부모를 진짜 부모로 만들고 싶다면 다음을 실행합니다.

git filter-branch -- --all

모든 커밋 ID가 변경됩니다.이 리포지토리의 모든 복사본을 강제로 업데이트해야 합니다.

디스크 공간 정리

제 복사본이 업스트림과 호환되도록 유지하기 위해 2단계를 수행하지 않았습니다.디스크 공간을 좀 절약하고 싶어서요.이전 커밋을 모두 잊으려면 다음을 수행합니다.

git prune
git gc

대안: 얕은 복사본

공간을 업데이트할 수 ..git/shallow그러나 이전의 커밋을 가리키는 것은 아무것도 없다는 점에 주의해야 합니다.따라서 다음과 같은 작업을 수행할 수 있습니다.

git fetch --prune
git rev-parse HEAD~2000 > .git/shallow
git prune
git gc

얕은 곳의 입구는 접붙이처럼 작용합니다.그러나 이식편과 얕은 것을 동시에 사용하지 않도록 주의해야 합니다.적어도, 거기에 같은 항목이 없으면 실패합니다.

이전 커밋을 가리키는 오래된 참조(태그, 분기, 원격 헤드)가 남아 있으면 해당 참조가 정리되지 않고 더 많은 디스크 공간을 절약할 수 없습니다.

여기에는 최신이 아닌 답변이 너무 많고 일부는 결과를 완전히 설명하지 못합니다.다음은 최신 Git 2.26을 사용하여 역사를 정리하는 데 도움이 되었습니다.

먼저 더미 커밋을 만듭니다.이 커밋은 잘린 보고서의 첫 번째 커밋으로 나타납니다.이 커밋을 수행하면 보관 중인 기록에 대한 모든 기본 파일이 저장되기 때문에 이 작업이 필요합니다.SHA는 유지할 커밋의 이전 커밋 ID입니다(이 예에서는8365366 'Initial은 첫 됩니다.) 첫 번째 커밋의 커밋 메시지로 'Initial' 문자열이 표시됩니다.윈도우즈를 사용하는 경우 GitBash 명령 프롬프트에서 아래 명령을 입력합니다.

# 8365366 is id of parent commit after which you want to preserve history
echo 'Initial' | git commit-tree 8365366^{tree}

SHA를 를 들어, "SHA를 출력합니다. 예를 들어,d10f7503bc1ec9d367da15b540887730db862023.

이제 다음을 입력합니다.

# d10f750 is commit ID from previous command
git rebase --onto d10f750 8365366

이 커밋의 로 저장됩니다.8365366 커밋 .d10f750그런 다음 8365366 이후의 모든 커밋을 재생합니다.d10f750.마침내.master분기 포인터가 재생된 마지막 커밋으로 업데이트됩니다.

, 레포를 자, 이, 그, 냥을 하세요.git push -f.

주의해야 할 몇 가지 사항(이는 이 방법뿐만 아니라 다른 방법에도 적용됨)태그가 전송되지 않습니다.은 이 . 예를 들어, " " " " ID " " " " " " " "와 같은 제목으로 합니다.Commits on XY date.

다행히 잘린 기록을 "아카이브"로 유지할 수 있으며, 나중에 잘린 레포를 다시 아카이브 레포와 결합할 수 있습니다.자세한 내용은 이 안내서를 참조하십시오.

헤드/마스터리베이스 또는 푸시 시 이 오류가 발생할 수 있습니다.

remote: GitLab: You are not allowed to access some of the refs!
To git@giturl:main/xyz.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'git@giturl:main/xyz.git'

이 문제를 해결하려면 git 대시보드에서 "보호된 분기"에서 마스터 분기를 제거해야 합니다.

여기에 이미지 설명 입력

그러면 이 명령을 실행할 수 있습니다.

git push -f origin master

또는

git rebase --onto temp $1 master

에 복제된 기존 이전리 토리의경우로 --depth

git clone --depth=1 ...

그냥 해요

git pull --depth=1 --update-shallow

https://git-scm.com/docs/git-pull

이 경우 저장소를 두 개로 나누고 기록은 유지하되 새 저장소에서 필터링된 파일에서 로그 기록을 정리합니다.

이것이 해결책이었습니다.

PATHS=path_a path_b
git filter-branch -f --prune-empty --index-filter "git read-tree --empty                                                                                    
git reset \$GIT_COMMIT -- $PATHS " -- --all -- $PATHS

이렇게 하면 전체 커밋 로그 기록이 포함된 새 레포를 얻을 수 있지만 유지하고자 하는 경로에 대해서만 얻을 수 있습니다.

참조: https://stackoverflow.com/a/56334887/2397613

BFG 도구의 Gitrepo에 따르면, 그것은 "git-filter-branch가 하는 것처럼 크거나 문제가 되는 블럽을 제거하지만, 더 빠르며 - 스칼라로 작성됩니다."

https://github.com/rtyley/bfg-repo-cleaner

  1. git 데이터 제거, rm.git
  2. 잽싸게
  3. 깃 리모콘 추가
  4. 힘으로 밀기

언급URL : https://stackoverflow.com/questions/4515580/how-do-i-remove-the-old-history-from-a-git-repository