다른 개발자에게 히스토리를 공개 한 경우 수행하려는 작업이 크게 손상됩니다. 히스토리 복구 후 필요한 단계 는 git rebase
설명서의 "업스트림 리베이스에서 복구"를 참조하십시오 .
git filter-branch
아래 설명 된 두 가지 옵션 과 대화식 리베이스가 있습니다.
사용 git filter-branch
Subversion 가져 오기에서 부피가 큰 이진 테스트 데이터와 비슷한 문제가 있었고 git 저장소에서 데이터를 제거하는 방법 에 대해 썼습니다 .
git history가 다음과 같다고 가정 해보십시오.
$ git lola --name-status
* f772d66 (HEAD, master) Login page
| A login.html
* cb14efd Remove DVD-rip
| D oops.iso
* ce36c98 Careless
| A oops.iso
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
참고 git lola
비표준이지만 매우 유용 별명입니다. --name-status
스위치를 사용하면 각 커밋과 관련된 트리 수정을 볼 수 있습니다.
“Careless”커밋 (SHA1 객체 이름이 ce36c98 임)에서 파일 oops.iso
은 실수로 추가되고 다음 커밋 cb14efd에서 제거 된 DVD-rip입니다. 앞에서 언급 한 블로그 게시물에 설명 된 기술을 사용하여 실행 명령은 다음과 같습니다.
git filter-branch --prune-empty -d /dev/shm/scratch \
--index-filter "git rm --cached -f --ignore-unmatch oops.iso" \
--tag-name-filter cat -- --all
옵션 :
--prune-empty
필터 작업의 결과로 비어있는 커밋을 제거합니다 ( 즉 , 트리를 변경하지 마십시오). 일반적인 경우이 옵션은 더 명확한 기록을 생성합니다.
-d
필터링 된 기록을 작성하는 데 아직 존재하지 않는 임시 디렉토리의 이름을 지정합니다. 최신 Linux 배포판에서 실행중인 경우 트리를/dev/shm
지정하면 실행 속도가 빨라 집니다.
--index-filter
주요 이벤트이며 기록의 각 단계에서 색인에 대해 실행됩니다. oops.iso
발견 된 곳 을 제거하려고 하지만 모든 커밋에 존재하지는 않습니다. git rm --cached -f --ignore-unmatch oops.iso
DVD-rip이 있으면 명령이 삭제되고 그렇지 않으면 실패하지 않습니다.
--tag-name-filter
태그 이름을 다시 쓰는 방법을 설명합니다. 필터 cat
는 신원 작업입니다. 위의 샘플과 같이 리포지토리에 태그가 없을 수도 있지만 전체 일반을 위해이 옵션을 포함했습니다.
--
옵션의 끝을 git filter-branch
--all
다음 --
은 모든 심판에 대한 속기입니다. 위의 샘플과 같이 리포지토리에는 하나의 심판 (마스터) 만있을 수 있지만이 옵션은 전체 일반을 위해 포함되었습니다.
약간의 이탈 후 역사는 다음과 같습니다.
$ git lola --name-status
* 8e0a11c (HEAD, master) Login page
| A login.html
* e45ac59 Careless
| A other.html
|
| * f772d66 (refs/original/refs/heads/master) Login page
| | A login.html
| * cb14efd Remove DVD-rip
| | D oops.iso
| * ce36c98 Careless
|/ A oops.iso
| A other.html
|
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
새로운 "Careless"커밋은 추가 만하고 " other.html
Remove DVD-rip"커밋은 더 이상 마스터 브랜치에 있지 않습니다. refs/original/refs/heads/master
실수 한 경우를 대비하여 레이블 이 지정된 분기에 원래 커밋 이 포함됩니다. 제거하려면 “리포지토리 축소를위한 점검표” 의 단계를 따르십시오 .
$ git update-ref -d refs/original/refs/heads/master
$ git reflog expire --expire=now --all
$ git gc --prune=now
더 간단한 대안을 위해, 저장소를 복제하여 원하지 않는 비트를 폐기하십시오.
$ cd ~/src
$ mv repo repo.old
$ git clone file:///home/user/src/repo.old repo
file:///...
복제 URL을 사용하면 하드 링크 만 만들지 않고 개체가 복사됩니다.
이제 당신의 역사는 :
$ git lola --name-status
* 8e0a11c (HEAD, master) Login page
| A login.html
* e45ac59 Careless
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
필터 작업이 해당 커밋을 수정하지 않았기 때문에 처음 두 커밋 ( "인덱스"및 "관리 페이지")의 SHA1 개체 이름은 동일하게 유지되었습니다. “무심한”상실 oops.iso
과“로그인 페이지”에 새로운 부모가 생겨 SHA1 이 변경되었습니다.
대화식 리베이스
역사 :
$ git lola --name-status
* f772d66 (HEAD, master) Login page
| A login.html
* cb14efd Remove DVD-rip
| D oops.iso
* ce36c98 Careless
| A oops.iso
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
oops.iso
"Careless"를 추가 한 적이없는 것처럼 제거하려고하면 "DVD-rip 제거"는 쓸모가 없습니다. 따라서 대화식 리베이스로 들어 가려는 계획은 "관리자 페이지"를 유지하고 "무심한"을 편집하고 "DVD-rip 제거"를 버리는 것입니다.
Running $ git rebase -i 5af4522
은 다음 내용으로 편집기를 시작합니다.
pick ce36c98 Careless
pick cb14efd Remove DVD-rip
pick f772d66 Login page
# Rebase 5af4522..f772d66 onto 5af4522
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
계획을 실행하면 다음과 같이 수정됩니다.
edit ce36c98 Careless
pick f772d66 Login page
# Rebase 5af4522..f772d66 onto 5af4522
# ...
즉, 우리가 함께 줄을 삭제 "DVD-RIP 제거"하고로 "부주의"의 조작을 변경 edit
하기보다는 pick
.
편집기를 저장 종료하면 다음 메시지와 함께 명령 프롬프트가 나타납니다.
Stopped at ce36c98... Careless
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
메시지에서 알 수 있듯이 우리는 편집하고자하는“Careless”커밋에 있으므로 두 가지 명령을 실행합니다.
$ git rm --cached oops.iso
$ git commit --amend -C HEAD
$ git rebase --continue
첫 번째는 문제가되는 파일을 인덱스에서 제거합니다. 두 번째는“Careless”를 업데이트 된 인덱스로 수정하거나 수정하고 -C HEAD
git에게 이전 커밋 메시지를 재사용하도록 지시합니다. 마지막으로 git rebase --continue
나머지 rebase 작업을 진행합니다.
이것은 다음과 같은 역사를 제공합니다.
$ git lola --name-status
* 93174be (HEAD, master) Login page
| A login.html
* a570198 Careless
| A other.html
* 5af4522 Admin page
| A admin.html
* e738b63 Index
A index.html
당신이 원하는 것입니다.