Programming

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

procodes 2020. 5. 16. 11:22
반응형

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


이 특정 시나리오와 비슷한 것을 찾지 못했습니다.

500 개 이상의 지점, 500 개 이상의 태그, 2007 년 중반으로 거슬러 올라가는 역사가 많은 자식 저장소가 있습니다. ~ 19,500 개의 커밋이 포함되어 있습니다. 2010 년 1 월 1 일 이전에 모든 기록을 삭제하여 더 작고 다루기 쉽도록 만들었습니다 (기록의 전체 사본을 보관 저장소에 보관함).

나는 새로운 저장소의 뿌리가되고 싶다는 결심을 알고 있습니다. 그러나 해당 커밋으로 시작하기 위해 저장소를 자르는 올바른 git mojo를 알아낼 수는 없습니다. 나는 몇 가지 변형을 추측하고있다.

git filter-branch

이식편과 관련된 것이 필요하다; 또한 우리가 별도로 유지하려는 200여 가지의 각각의 치료 후 (내가 뭔가 다시 함께 REPO을 패치 할 필요가 있습니다 않습니다 어떻게 해야할지).

누구든지 이런 일을 한 적이 있습니까? 중요한 경우 자식 1.7.2.3이 있습니다.


새로운 루트 커밋의 부모에 대한 이식편 을 부모가없는 곳 (또는 저장소의 실제 루트 커밋과 같은 빈 커밋)으로 만드 십시오. 예 :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하게 영구히 만들 수 있습니다.

주의 : filter-branch 단계를 수행 한 후에는 모든 커밋 ID가 변경되므로 이전 저장소를 사용하는 사람은 새 저장소를 사용하는 사람과 병합해서는 안됩니다.


답글을 게시하기에는 너무 늦었을 수 있지만이 페이지가 Google의 첫 번째 결과이므로 여전히 도움이 될 수 있습니다.

git repo에서 공간을 확보하고 싶지만 모든 커밋 (rebase 또는 graft)을 다시 작성하지 않고 전체 저장소가있는 사람들의 푸시 / 풀 / 병합을 계속하려면 git을 사용할 수 있습니다 복제 얕은 복제본 ( --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은 clone / push / pull을 얕은 저장소에서 지원하지 않았습니다.


방법 은 이해하기 쉽고 잘 작동합니다. 스크립트 ( $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 같은 aswer 알고 있지만, 여기에 몇 가지 중요한 추가 명령과 정보가 있습니다. 답변을 수정하려고했지만 @yoyodin의 답변이 크게 변경되었으므로 편집이 거부되었으므로 여기에 정보가 있습니다!


이 방법을 시도하십시오 git history 자르기 :

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

Here $1 is SHA-1 of the commit you want to keep and the script will create new branch that contains all commits between $1 and master and all the older history is dropped. Note that this simple script assumes that you do not have existing branch called temp. Also note that this script does not clear the git data for old history. Run git gc --prune=all && git repack -a -f -F -d after you've verified that you truly want to lose all history. You may also need rebase --preserve-merges but be warned that the git implementation of that feature is not perfect. Inspect the results manually if you use that.


As an alternative to rewriting history, consider using git replace as in this article from the Pro Git book. The example discussed involves replacing a parent commit to simulate the beginning of a tree, while still keeping the full history as a separate branch for safekeeping.


If you want to keep the upstream repository with full history, but local smaller checkouts, do a shallow clone with git clone --depth=1 [repo].

After pushing a commit, you can do

  1. git fetch --depth=1 to prune the old commits. This makes the old commits and their objects unreachable.
  2. git reflog expire --expire-unreachable=now --all. To expire all old commits and their objects
  3. git gc --aggressive --prune=all to remove the old objects

See also How to remove local git history after a commit?.

Note that you cannot push this "shallow" repository to somewhere else: "shallow update not allowed". See Remote rejected (shallow update not allowed) after changing Git remote URL. If you want to to that, you have to stick with grafting.


I needed to read several answers and some other info to understand what I was doing.

1. Ignore everything older than a certain commit

The file .git/info/grafts can define fake parents for a commit. A line with just a commit id, says that the commit doesn't have a parent. If we wanted to say that we care only about the last 2000 commits, we can type:

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

git rev-parse gives us the commit id of the 2000th parent of the current commit. The above command will overwrite the grafts file if present. Check if it's there first.

2. Rewrite the Git history (optional)

If you want to make this grafted fake parent a real one, then run:

git filter-branch -- --all

It will change all commit ids. Every copy of this repository needs to be updated forcefully.

3. Clean up disk space

I didn't done step 2, because I wanted my copy to stay compatible with the upstream. I just wanted to save some disk space. In order to forget all the old commits:

git prune
git gc

Alternative: shallow copies

If you have a shallow copy of another repository and just want to save some disk space, you can update .git/shallow. But be careful that nothing is pointing at a commit from before. So you could run something like this:

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

The entry in shallow works like a graft. But be careful not to use grafts and shallow at the same time. At least, don't have the same entries in there, it will fail.

If you still have some old references (tags, branches, remote heads) that point to older commits, they won't be cleaned up and you won't save more disk space.


When rebase or push to head/master this error may occurred

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'

To resolve this issue in git dashboard should remove master branch from "Protected branches"

enter image description here

then you can run this command

git push -f origin master

or

git rebase --onto temp $1 master

you can delete the directory, files and also the entire history related to the dir or file using the below mentioned jar [ download it] and the commands

bfg.jar file: https://rtyley.github.io/bfg-repo-cleaner/

git clone --bare repo-url cd repo_dir java -jar bfg.jar --delete-folders folder_name git reflog expire --expire=now --all && git gc --prune=now --aggressive git push --mirror repo_url


  1. remove git data, rm .git
  2. git init
  3. add a git remote
  4. force push

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

반응형